Jump to content
IGNORED

RMT2LZSS: convert RMT tunes to LZSS for fast playback!


rensoup

Recommended Posts

33 minutes ago, ivop said:

ITYM hijacks ;) Not that I don't make spelling errors, but hiking is something completely different :)

 

OK. It was some "soft" adaption of "unterwandern" ;)

But if hiking doesn't work, hijacking could be the solution ;)

 

 

33 minutes ago, ivop said:

This was at 15.6kHz. At the proposed low replay rate, you can go as low as 16 bytes per period. Perhaps even less, but it complicates the replay routine because of resetting the index register, or LSB with self-modifying code.

 

If someone offers me a good Hex-Editor, or some editor that keeps the original content of the RMT file, I'd like to show something ;)

Link to comment
Share on other sites

20 hours ago, emkay said:

Because there is no oversampling. 

It's technical stuff ;)

If you read my posts carefully, I was explaining it. 

I read your posts left to right and right to left but the meaning escapes me a lot of the time... i need simple stuff with numbers and/or code

 

I do understand that you need twice the play at twice your sample frequency for it to play without artifacts but I don't know why it doesn't work with my bass test...

 

6 hours ago, emkay said:

Ah, I see the problem. 

Normally, RMT is mixing AUDCx together for the generators and the volume. 

The used method here just hikes a channel and writes the volume only . 

Indeed but I tried merging the pure tone gen like Ivop said but it made no difference?

Link to comment
Share on other sites

9 hours ago, ivop said:

Sort of. You can store your 4-bit samples with ora'd with $10, and then ora $a0 if you want to hear the tonegenerator, too.

Sure, but right now it's all LZSSed so... I tried forcing the pure tone generator but it made no difference to the sound ?

Or should a regular Pokey sound be played with $a0 then switch to volume only + $a0 to get some better sound ?

 

9 hours ago, ivop said:

256-bytes is enough for a repeating wave to get a pure tone. The 512 bytes I use in AtariSid contains the same 256 bytes twice! That way it is easier, and faster, to index without checking for overflow everytime, at the cost of usiing double the amount of memory.

I tried generating some super short sine waves with audacity (200+ bytes) and low pass filtered it and it still sounds crap ?

 

8 hours ago, ivop said:

Also, if you are still going on using true samples, be sure to filter them properly before downsampling. For example, if you are going to replay the samples at 800Hz, 400Hz is the maximum frequency it can capture. It's best too filter out every frequency above that, to avoid aliasing when downsampling to 800Hz. Set a low-pass filter to something like 380Hz with a very sharp knee, or run the filter a few times. After that, normalize to the volume you want

tried lowpass filtering that bass... still crap ?

(but I had the volume normalized before though I don't think it would have made any difference)

 

Link to comment
Share on other sites

I added an EnvelopeLoop command in the .erti file to try looping samples

 

I also left the dist setting in AUDC instead of setting it to 0 even though it doesn't seem to make any difference

 

I also modulated the sample volume with the RMT volume table just like regular Pokey sounds so the sample volume can be set in the editor volume column.

 

Sounds meh ? so I'm a bit reluctant to package yet another release just for that...

 

 

sampletest.obx

  • Thanks 1
Link to comment
Share on other sites

lmfao what am I even doing anymore, and why does that "kinda" work LOL
 

 

I'm surprised this even works, even if it's really noisy I tell this is a loop playing in the background :D 
theoretically, what could be the highest sample rate possible? that doesn't render screen update routine impossible I mean.

I need to sleep but that is getting so much fun lol
I love the new envelope step speed btw! this makes these tests much easier
I expected the values to increment would slow it down but then going in the decimal after 0 works to achieve the same so I'm fine with that too

work of art lmao.xex

  • Haha 1
Link to comment
Share on other sites

okay nevermind I couldn't sleep yet until I tried this out even more lol

That's right, I literally sampled part of one of my own tunes and the conversion took it like a champion :D 
Now I know I could execute it better but at such low sample rate there isn't that much to improve anyway hahaha

Please excuse the .ogg file but I really need to sleep now, enjoy (or don't I won't blame anyone with ears to not enjoy lol)

pwm chords sampled like shit.xex

  • Haha 1
Link to comment
Share on other sites

13 hours ago, rensoup said:

I tried generating some super short sine waves with audacity (200+ bytes) and low pass filtered it and it still sounds crap ?

That's not what I meant. If you use super clean, generated snippetes of say 256 bytes, you do not need to filter it. Just ignore the replay rate and play at your own speed with fixed point math to create different musical frequencies. Filtering is only necessary if you have for example a 44.1kHz 1s sample of a bass, and you want to resample that to 800Hz. Some resampling techniques do this sort-of automatigally. SINC resampling IIRC.

 

I'd say, start simple. Waveform buffer: #$1f (128 times), #$10 (128 times). Volume only, do not set any tonegenerator yet. Now play this buffer round-robin at 800Hz, increase pointer by fixed point math, loop at overflow. Depending the increment of the pointer, you get different sound frequencies. Mixing in the tone generator is for later.

  • Like 1
Link to comment
Share on other sites

did another test
streamed a 4 channels mod in this one, 1 mod channel per pokey channel, it... works, and that's about it, very low quality
 

Turns out bitcrushing to 4-bit then saving as 16-bit did a huge amount of improvement, the sampling technique is the same I used yesterday, which was a lot more noisy.
gonna test more things later when I get back home :D 

toytitle.xex

  • Like 4
Link to comment
Share on other sites

11 minutes ago, VinsCool said:

did another test
streamed a 4 channels mod in this one, 1 mod channel per pokey channel, it... works, and that's about it, very low quality
 

Turns out bitcrushing to 4-bit then saving as 16-bit did a huge amount of improvement, the sampling technique is the same I used yesterday, which was a lot more noisy.
gonna test more things later when I get back home :D 

toytitle.xex 37.59 kB · 1 download

 

Funfact:

The low speed of "sampling" drops the "squealing high peak" that you get when doing any "digitizing" at high speeds for all frequency ranges. 

  • Like 3
Link to comment
Share on other sites

@rensoup how do you synchronize a 800Hz replay routine? Seems hard to me. There's a reason HARDbass is 1950Hz on PAL, without sacrificing an IRQ timer.

 

$ bc
312*50/8
1950.000000
312/8
39.000000

312*50/16
975.000000
312/16
19.500000

312*50/24
650.000000
312/24
13.000000

 

Playing a sample once every 8 scanlines. 312 scanlines are exactly 39 times 8 scanlines.

 

Playing one sample every 16 scanlines, resulting in a 975Hz replay rate, does not fit in 312 scanlines. It's 19 and a half period.

 

Once every 24 scanlines fits again.

Edited by ivop
  • Like 1
Link to comment
Share on other sites

1 hour ago, VinsCool said:

did another test
streamed a 4 channels mod in this one, 1 mod channel per pokey channel, it... works, and that's about it, very low quality

 

Yeah, but there are some usable parts in there. The bass and drums sound good.

 

Cool to see a 4 channel mod working straight through like that too (even with some of the low-fi parts)...

 

Edited by MrFish
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

9 hours ago, ivop said:

I'd say, start simple. Waveform buffer: #$1f (128 times), #$10 (128 times). Volume only, do not set any tonegenerator yet. Now play this buffer round-robin at 800Hz, increase pointer by fixed point math, loop at overflow. Depending the increment of the pointer, you get different sound frequencies. Mixing in the tone generator is for later.

I'm guessing you meant $f and $0 | VolumeOnlyBit ?

 

here's a test I did with just a single $f and $0 (128 was way too long to sound interesting) and varying volumes as well as frequencies... wouldn't say there's any improvement...

 

2 hours ago, ivop said:

@rensoup how do you synchronize a 800Hz replay routine? Seems hard to me. There's a reason HARDbass is 1950Hz on PAL, without sacrificing an IRQ timer.

I added the source in the latest release, it' just VCount so it's not super accurate indeed but I doubt that it's going to make much difference... it's fixed point so sometimes it's on the right scanline, sometimes on the scanline before.

 

You could just set the increment to 13 for that 650hz playback.

 

sampletestsquare.obx

  • Like 1
Link to comment
Share on other sites

15 hours ago, VinsCool said:

I will figure it out eventually :P 

the wave is pretty nice in that version but it's still quite chunky, especially compared to your sawtooth at 50hz which was much steeper. Would there be a way to use regular Pokey sound at higher frequencies to be able to play sounds that are close to samples ? 

(ie convert sampled sound into regular pokey sounds)

 

3 hours ago, VinsCool said:

turns out bitcrushing to 4-bit then saving as 16-bit did a huge amount of improvement, the sampling technique is the same I used yesterday, which was a lot more noisy.

interesting that the filesize is okayish at 800hz !

  • Thanks 1
Link to comment
Share on other sites

I just posted a new release:

 

1.71 May 2021
    -sample playback now takes into account channel volume as well as frequency (in a simple linear way)
 

in the .erti example

Quote

[instrument$02]
Sample=bass.wav
SampleStep=15.565334
EnvelopeLoop=0

should be 

Quote

[instrument$02]
Sample=bass.wav
SampleStep=15.565334
SampleLoop=0

 

I'd put the sample data into the envelope but it wasn't really necessary, just somewhat convenient. I decided to store the sample data in its own buffer with this latest release so the envelope should be available as usual.

 

I now take into account the track volume to modulate the sample volume. And I also take into account the track note to modulate the playback frequency... just like a regular tracker but in a crappier way.

 

So you can apply regular envelope effects (and still update the envelope pointer with steps < 1) to the note then the final note will alter the sample playback frequency. I just grab AUDF, with value 128 being regular playback frequency (= 1), 255 = 2(so twice faster), 0 = 0(that would play the same value forever). 

I should of course change the playback frequency to real note's frequency for correctness but I'd need a table for that...

 

 

  • Thanks 1
Link to comment
Share on other sites

16 hours ago, VinsCool said:

I'm surprised this even works, even if it's really noisy I tell this is a loop playing in the background :D 
theoretically, what could be the highest sample rate possible? that doesn't render screen update routine impossible I mean.

hmm... with 4 channels updates, maybe 1200Hz... with a 3channels at 50hz the 4th could perhaps go as high as 3-5Khz

  • Thanks 1
Link to comment
Share on other sites

Damn I missed the newest update, but that's fine since I just did some more experiment with the previous version there :D 

I started an actual tune using samples lol
Not great but it's certainly a proof of concept
I kept running out of memory so it always glitched somewhere as a result XD

 

I just sort of "tuned" my bass sample using the EnvelopeStep= line, it's pretty clunky but it certainly did save me some time manually sampling several things at once lol
The kick drum is the same one included but I resampled it with the 4-bit reduction and applied some low pass filter to remove the unwanted interference.

Figured I'd post it here instead of bumping my thread considering it's relevant to the discussions :P 

Sketch 48 v2.xex

  • Like 3
Link to comment
Share on other sites

I did some test, and without proper resampling on the Atari side, the round-robin 256 bytes at different speeds at such a low sample rate, simply doesn't work. It causes a LOT of aliasing. Code:

 

AUDF1   = $d200
AUDC1   = $d201
AUDCTL  = $d208
IRQEN   = $d20e
WSYNC   = $d40a
NMIEN   = $d40e
_frac   = $e0

    org $4000

waveform
:128 dta $1f
:128 dta $10

main
    sei
    lda #0
    sta _frac
    sta NMIEN
    sta IRQEN
    sta AUDCTL
    sta AUDF1

loop

_index = *+1
    lda waveform
:16    sta WSYNC
    sta AUDC1

    lda _frac
    clc
    adc #$00		; frac increment
    sta _frac
    lda _index
    adc #$08		; int increment
    sta _index

    jmp loop

    run main

It only works with common dividers of the sample window. Try changing the integer increment, or add a fractional part, and you'll hear what I mean.

 

The cause is that you are basically doing a very crude resampling if you use an increment to "hop" through your sample window.

 

A solution is to use varying window sizes for each of the twelve notes per octave. Lower octaves can be achieved by stepping slower through the window, with half the increment/fraction/hop size.

 

Or, trigger an IRQ at AUDF frequency, step through one fixed window byte by byte, but that'll mean interrupts are fired all over the place, depending on the frequency of the tone played.

 

 

Edit: BTW, if you wonder, turning off DMACTL does not have any effect.

 

Edited by ivop
and a typo
  • Like 2
Link to comment
Share on other sites

Proof of concept with varying window sizes.

 

AUDF1   = $d200
AUDC1   = $d201
AUDCTL  = $d208
WSYNC   = $d40a
VCOUNT  = $d40b
NMIEN   = $d40e
_frac   = $e0
_cnt    = $e1

GENWAVEFORM    .macro mem, label, x
    org :mem
.def waveform:label = *
::x dta $1f
::x dta $10
.def len_waveform:label = * - waveform:label    ; should be 2*:x
    .endm

PLAYWAVEFORM .macro x, int, frac
_index = *+1
    lda waveform:x
:+16    sta WSYNC           ; 8=1950Hz, 16=975Hz, PAL
    sta AUDC1
    lda _frac
    add #:frac
    sta _frac
    lda _index
    adc #:int
    cmp #len_waveform:x
    bcc less_than
    sec
    sbc #len_waveform:x
less_than
    sta _index
    .endm

LOOPWAVEFORM .macro x, int, frac
loopwave
    PLAYWAVEFORM :x, :int, :frac

    lda VCOUNT
    bne loopwave

:+8    inc _cnt
    bpl loopwave
    lda #0
    sta _cnt
    .endm

; 12 tones, 12-TET
    GENWAVEFORM $4000,  0, 24
    GENWAVEFORM $4100,  1, 23
    GENWAVEFORM $4200,  2, 22
    GENWAVEFORM $4300,  3, 21
    GENWAVEFORM $4400,  4, 20
    GENWAVEFORM $4500,  5, 19
    GENWAVEFORM $4600,  6, 18
    GENWAVEFORM $4700,  7, 17
    GENWAVEFORM $4800,  8, 16
    GENWAVEFORM $4900,  9, 15
    GENWAVEFORM $4a00, 10, 14
    GENWAVEFORM $4b00, 11, 13
;    GENWAVEFORM $4c00, 12, 12      ; octave

    org $5000

main
    lda #0
    sta _frac
    sta _cnt
    sta NMIEN
    sta AUDCTL
    sta AUDF1

    LOOPWAVEFORM  0, 1, 0
    LOOPWAVEFORM  1, 1, 0
    LOOPWAVEFORM  2, 1, 0
    LOOPWAVEFORM  3, 1, 0
    LOOPWAVEFORM  4, 1, 0
    LOOPWAVEFORM  5, 1, 0
    LOOPWAVEFORM  6, 1, 0
    LOOPWAVEFORM  7, 1, 0
    LOOPWAVEFORM  8, 1, 0
    LOOPWAVEFORM  9, 1, 0
    LOOPWAVEFORM 10, 1, 0
    LOOPWAVEFORM 11, 1, 0
    LOOPWAVEFORM  0, 2, 0
    LOOPWAVEFORM  1, 2, 0
    LOOPWAVEFORM  2, 2, 0
    LOOPWAVEFORM  3, 2, 0
    LOOPWAVEFORM  4, 2, 0
    LOOPWAVEFORM  5, 2, 0
    LOOPWAVEFORM  6, 2, 0
    LOOPWAVEFORM  7, 2, 0
    LOOPWAVEFORM  8, 2, 0
    LOOPWAVEFORM  9, 2, 0
    LOOPWAVEFORM 10, 2, 0
    LOOPWAVEFORM 11, 2, 0
    LOOPWAVEFORM  0, 1, 0

    jmp *

    run main

Note that this is by no means tuned to anything. It plays samples at 975Hz, and the intervals are all the twelve notes in an octave that work without fractions. Tuning means calculating compromises between window size and int.frac increments.

 

 

 

main.s main.xex

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

An attempt at making really crude wavetables using that 800hz through volume only mode.
Not amazing but it's something lol

 

Just been playing around with that stuff a bit more, I got a semi-reliable setup to make any waveform I want now :) 

  • Like 1
Link to comment
Share on other sites

Not sure , if this brings any good result that way. 

If you cannot hear what you were doing while editing, the result will always be "mediocre".

 

Particular, if any "digitizing effect" is to get from 60Hz already. It's 800Hz. 

There is a demo available doing sampling at VBI speed.

Without proper working editing tools, the wasted time only might get bigger and bigger.

 

Using the Envelope in RMT , to set sample volumes, is a good choice, but far aways of any use for music creation.

 

Just again the reminder

The tune "slow" is using "just" 200Hz updates, and it sounds already like 4 channels built sounds using LFOs.

Back then, the tune wasn't released, because the early RMT emulation wasn't even correct procucing this.

 

 

 

 

 

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...