Topic: new engine: ulasyn

tldr: 2 pulse channels with lo-pass/hi-pass filters with somewhat variable cutoff.

- 2 pulse wave channels
- variable duty cycle
- duty cycle sweep with variable speed
- noise mode (channel 2 only)
- filters with variable cutoff (6 levels for lo-pass, 5 levels for hi-pass)
- sample rate 9114 Hz
- interrupting PWM sampled drums at 18229 Hz with 7 pitch and 3 volume levels
- player size 3333 bytes (when assembled at a 256b border)

source code


Some points of interest:

- The filter implementation itself is pretty boring, just a lookup into a 14-byte table with values for each pair of (current volume, next raw channel state).

- Noise mode uses a new technique. The engine has one version of the main loop for each volume level, so using self-modifying code to enable/disable the effect was not an option. After just randomly experimenting, I ended up with

  ; hl is oscillator state
  ld a,(MASK)
  and h
  rlca
  xor h
  ld h,a

At 29t it's rather expensive, but I really wanted noise mode and could spare the cycles. Depending on MASK, the divider and the duty cycle, this can produce many wildly different sounds. I found that using a mask of 0x76 and a divider of 0x2712 works well to fake standard white noise, with duties from 0x30-0xc0 being somewhat usable for simulating volume levels. Unfortunately the filters are a bit to crude to really work well on noise.

- Using a rather low sample rate for the PWM drums here. Not sure if that's such a great idea, but hey, we've got noise mode to make up for the low upper frequency limit. Originally I wanted to do synth drums instead (using the new noise mode of course), but in the end PWM is much more convenient for the composer.

- Still got some cycles left, so this can be pushed further. Phaser with filters would be really cool, and might be doable. Aside from needing to find some additional registers, the main challenge would be to swap the xor/or/and without smc.

I'm also wondering whether it is possible to increase the cutoff resolution. In theory the number of volume levels can be doubled by going from 16t to 8t per volume level, but that has the problem that we cannot render level 1 properly on ZX beeper. On hardware, this can be done by sacrificing levels 0 and 1 and using level 2 as new level 0, but on emulators this is inherently beepy (that's why zbmod has an "emulator" version). So I don't want to go down that route. In ulasyn, each volume level is generated twice per sample, so one could theoretically jump to the previous or next level half-way. The problem is that if this happens repeatedly at the same volume, we get an audible parasite tone from the mixing. So the filter tables and total volume calculation would need to take that into account. Right now what's being looked up is the answer to the question: Given the current volume 0..6 and the unfiltered next volume (either 0 or 6), what should be the next volume? This needs an added delta, ie: Assuming that the unfiltered next volume does not change,will the volume increase, decrease, or stay the same in the sample after the next one? Based on this, we can select the next volume "core" as follows:

- If both channels want to increase the volume further, jump half-way from volume to volume+1.
- Likewise, if both channels want to decrease the volume further, jump half-way from volume to volume-1.
- Else, do not jump half-way.

This way, repeated jumps from the same initial volume can only occur when the volume lookahead is wrong (because unfiltered state changed from 0 to 6 or vice versa), which should be rare enough to avoid parasite tones. This would give us one additional bit of cutoff precision.

Post's attachments

ulasyn-demo.tap 4.51 kb, 6 downloads since 2024-01-31 

You don't have the permssions to download the attachments of this post.

Re: new engine: ulasyn

Oh my, now that is definitely some forbidden black magic. I can't wrap my head around it at the moment, but it sounds totally unbelievable for the beeper.

website - 1bit music - other music - youtube - bandcamp - patreon - twitter (latest news there)

Re: new engine: ulasyn

Oh wow !

Utterley amazing. Don't think I've heard another beeper engine sound like this !
Wasn't expecting a new engine at all

Congrats utz

Re: new engine: ulasyn

Ha, last night I realized that volume control is actually possible with this engine. It just requires lots of additional filter tables, but that can be done without increasing the code size.

Anyway, thanks guys.

Re: new engine: ulasyn

Aaaand voilà. Volume control implemented. Lower volume means less precision for the filters, of course. Updated source is on github, see above.

Now what I would really like to have is resonance. Not sure if it's actually possible with this setup. In any case I can't wrap my head around the math of it.

Post's attachments

ulasyn-demo2.tap 4.6 kb, 4 downloads since 2024-02-02 

You don't have the permssions to download the attachments of this post.

Re: new engine: ulasyn

Fixed some bugs, and found a way to properly calculate the cutoff 1.5 tables (by doing level 2 on a rising edge and level 1 on a falling edge). In theory this could be extended to other intermediate levels, doubling the cutoff resultion. However the filter response is such that the perceived difference between eg. level 2 and 3 is actually smaller than between 1.5 and 2, so I didn't bother implementing any more *.5 tables. Users can add their own filter tables if needed.

Re: new engine: ulasyn

Really love this engine utz.

I've created a little yt vid of your demo track on my channel:

https://youtu.be/Yd1G_9fHj5E?si=u55jtwybfNOOBbzD


Do you think it will get included into 1tracker/bintracker or a convertor made?
I've had a look at the asm and the song structure doesn't seem too complicated so I could possibly create a simple track in asm.

I've been listening to this album a lot recently and I think a drone synth tune would be perfect on the ulasynth engine
https://youtu.be/jegp-ObgKNQ?si=1pV1OXimRPVcsfbt

Re: new engine: ulasyn

I'm certainly up to try to implement the 1tracker version, just waiting until it get settled down with the features.

website - 1bit music - other music - youtube - bandcamp - patreon - twitter (latest news there)

Re: new engine: ulasyn

Squashed one more bug today. Also tried to implement resonance, but either I'm doing it wrong, or the volume resolution is insufficient to do it. In any case, this should be it, not planning to do more work on this in the near future.

Would be great to have it in 1tracker. I'm not adding it to Bintracker yet, because the engine plugin format still isn't stable.

10 (edited by garvalf 2024-03-06 13:58:45)

Re: new engine: ulasyn

I really love this sound, it's totally mesmerizing! well done again...