101

Re: next gen engine ideas

Cooking up some new stuff. Seems like I've got phase distortion synthesis working. Not entirely sure if I got the maths correct, but it sounds interesting at least.

Post's attachments

test.tap 600 b, 10 downloads since 2020-12-26 

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

Re: next gen engine ideas

utz wrote:

Cooking up some new stuff. Seems like I've got phase distortion synthesis working. Not entirely sure if I got the maths correct, but it sounds interesting at least.

Sounds best when at lower frequencies. Maybe fine tune it to mimic a low frequency EQ filter, like what the SID can do.

103

Re: next gen engine ideas

Yes, was thinking the same thing. What I'd really want is to have some sort of an lfo-controlled lo-pass. A simple FIR lo-pass at a fixed cut-off is fairly easy to implement, but I haven't been able to pull off a variable cut-off in constant CPU time. Maybe could be done with another table lookup but I'm currently already short one register pair for implementing the second channel.

104

Re: next gen engine ideas

Horray, got it working in 2 channels, with lfo-controlled resonance. That was surprisingly tough. Sadly, no room for a low-pass. It's also fairly noisy when mixing 2 channels. Will try to get it a little cleaner than this, though I'm slowly running out of ideas.

Post's attachments

test_2ch_v2.tap 1.07 kb, 15 downloads since 2020-12-28 

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

105

Re: next gen engine ideas

it has great potential. hopefully it will develop into something bigger.

Re: next gen engine ideas

Oh wow, love it utz.

A new beeper sound again smile

107 (edited by Shiru 2022-02-01 00:57:26)

Re: next gen engine ideas

I forgot if we're used it somewhere, but a phasing effect with a couple of 16-bit adders:

add hl,bc
add ix,de
ld a,h
xor ixh
cp 128
sbc a,a

Actually I was experimenting with the Phaser idea applied to a 4-bit DAC (i.e. AY) with a quirk: instead of toggling the sole bit on and off with the overflow of each of the generators, why not XOR a couple of possible 4-bit values. Like, in the regular operation mode both XOR the output with 15, and we're getting the regular Phaser sound. However, if one of generators XORs a lesser value, the phasing effect kinda gets reduced. So we can control the amount of the effect in the channel, which gives it another dimension. The test is attached (press any key).

Post's attachments

test.sna 48.03 kb, 16 downloads since 2022-02-01 

You don't have the permssions to download the attachments of this post.
website - 1bit music - other music - youtube - bandcamp - patreon - twitter (latest news there)

108

Re: next gen engine ideas

Good find. I've used xor phasing on >1bit signals in a couple of engines, but it never occurred to me that the effect strength could be controlled in this way. Very cool.

Btw, shouldn't it be possible to implement ring modulation like this?

109 (edited by Shiru 2022-03-29 21:53:00)

Re: next gen engine ideas

Got an idea for the next gen engines that I hope to demonstrate soon in a pretty rad new (-ish) engine I'm giving finishing touches to at the moment.

We've got the sampled drums in many engines already, sometimes even non-interrupting ones. Even with the interrupting ones, why not get it one step further and allow to manipulate the sample sound on the fly, through a set of parameters like we do for our synthesized drums?

I tested three ideas and got pretty cool results in a separate test:

- The least impressive one is just a sample offset. Start each drum for specified sample offset instead of 0. A good old technique that comes from MOD trackers (I used it often in the past to imitate opening/closing filter on the reso bass).

- Volume. It is possible to get 4 levels of volume within a 120-t sample loop (~30 kHz samples). This is achieved by out'ing a value 4 times per each bit, and self-modifying nop/xor a between the outs. Much like the tone channel volume balance in Tritone and some other engines.

- Pitch. It may be tricky to implement it in a way that would not affect the drum duration in an unpredictable way (to compensate the tempo properly). And here comes a fun find. I was thinking of the modern slice-based methods of the pitch adjustment that does not affect the pitch (like YouTube's 0.5x..1.5x etc), and thought it technically could boil down to just not playing some of bits within a byte. And it actually works! At least it gives an illusion of the reduced pitch on some samples, and I assume it'll give at least some sound character changes in other cases.

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

110

Re: next gen engine ideas

Those are some great ideas/findings. I very much agree that we can and should push 1-bit drums further.

Sample offset can actually be very useful for kick drums. By skipping the initial attack phase you can make a kick punch less, so that gives you a means of varying expression. Also, I once read somewhere that the first 20ms of the attack phase have a profound impact on how we perceive a timbre, so that's generally something to keep in mind for the future.

Volume control is great to have of course. With 4 levels you could actually start to think about doing PCM drums. One idea I had regarding this is to use some sort of 1-bit ADPCM, where the A part is that you can "wrap" the volume around, ie if you currently have volume 4 and the next bit read is 1, that translates to vol 0, and viice versa with current vol 0 and reading a 0-bit. That way you can preserve the high end of noise-heavy samples.

The pitch via slicing seems very interesting. I think that could be useful for other purposes as well. Will have to dig into esex' source code, hehe.

111

Re: next gen engine ideas

trollolol

Post's attachments

test.tap 32.1 kb, 5 downloads since 2022-04-13 

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

112

Re: next gen engine ideas

Next iteration. Up to 24.3 KHz sample rate, don't think I can go much faster.
And yes, this is completely pointless...

Post's attachments

test.tap 32.1 kb, 8 downloads since 2022-04-14 

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

Re: next gen engine ideas

Oh wow !

Never heard sample playback that good before on the Speccy 48k :0

Re: next gen engine ideas

Shiru wrote:

I forgot if we're used it somewhere, but a phasing effect with a couple of 16-bit adders:

add hl,bc
add ix,de
ld a,h
xor ixh
cp 128
sbc a,a

Actually I was experimenting with the Phaser idea applied to a 4-bit DAC (i.e. AY) with a quirk: instead of toggling the sole bit on and off with the overflow of each of the generators, why not XOR a couple of possible 4-bit values. Like, in the regular operation mode both XOR the output with 15, and we're getting the regular Phaser sound. However, if one of generators XORs a lesser value, the phasing effect kinda gets reduced. So we can control the amount of the effect in the channel, which gives it another dimension. The test is attached (press any key).

Very cool sound Shiru

115

Re: next gen engine ideas

I've been toying with a very promising new engine design that makes it possible to use computation-heavy effects, while also eliminating row transition noise. I don't have time to develop this into a full engine at the moment, but I thought I'd share the idea in case anybody else wants to play with it.

The design revolves around using a crude scheduler to implement basic multi-threading. Within every iteration of the sound loop, the scheduler allots a fixed portion of the available cpu time to the main thread, which updates frequency counters and calculates the output value(s) for the next iteration. The rest is allotted to a variable pool of secondary threads, which run consecutively in between each main thread run. In other words, our sound loop consists of two parts - the first part is always the same and runs all those updates that are required on each sound loop iteration. The second part runs varying tasks that do not require fast updates, for example counting length, computing some effect, or reading in note data.

The scheduler is implemented by pointing the stack pointer to the music data, and then simply RETurning after the main thread. To keep the music data size manageable, we need to implement sequence loops and subroutines as abstract operations running as secondary threads. Ideally we'd do nested subroutines, however that's a bit expensive to compute and in some cases one could probably get away without nesting. No nesting basically mirrors the sequence/pattern approach we normally use. The following example would play two notes over and over again:

sequence
    dw set_note_ch1, some_note
    dw init_loop, #3fe     ; set note length
    dw jump_sub, delay
    dw set_note_ch1, some_other_note
    dw init_loop, #3fe     ; set note length
    dw jump_sub, delay
    dw jump_seq, sequence

delay
    dw do_nothing
    dw loop, delay
    dw return

Now, that may seem like a rather inefficient way to just do

seq
    dw pattern
    dw seq_end
    dw seq

pattern
    dw length, note
    dw length, other_note
    db ptn_end

Perhaps it makes more sense to pick a certain number of threads, and think of the time they will take as your refresh rate/tick length, eg.

    ...
    dw set_note, note
    dw init_loop, #80         ; 0x80 * 0x10 + 3 = 0x803 loops/ca. 8 ticks (so we can get away with just an 8-bit length counter)
    dw jump_sub, fx01
    dw set_note, other_note
    dw init_loop, #40
    dw jump_sub, fx02
    ...

fx01
    dw calculate_expensive_fx_part1
    dw calculate_expensive_fx_part2
    dw do_something_else
    dw jump_sub, delay11
    dw loop, l1     ; 16 

fx02
    dw calculate_other_expensive_fx_part1
    dw calculate_other_expensive_fx_part2
    dw calculate_other_expensive_fx_part3
    dw calculate_other_expensive_fx_part4
    dw do_something_else
    dw jump_sub, delay9
    dw loop, l1

delay11
    dw do_nothing
    dw do_nothing
delay9
    dw do_nothing
    dw do_nothing
    dw do_nothing
    dw do_nothing
    dw do_nothing
    dw do_nothing
    dw do_nothing
    dw do_nothing
    dw return

Still expensive in terms of data size, but essentially we can now run things that we used to run in the outer sound loop (so, every 256*innter_loop_length t) at a much faster rate without affecting sound. This allows us to do stuff like fast&precise slides/vibrato and all sorts of variable-rate modulation effects. Also with recursive subroutines, you could actually have subroutines that generate subroutines... I think one could go pretty wild with this.

116 (edited by Shiru 2023-01-07 17:17:40)

Re: next gen engine ideas

I'm not sure if we ever used it somewhere, sometimes I'm forgetting all the tricks we've discovered prior. Anyways, a weird kind of modulation:

 add hl,bc
 ld a,h
 cp duty
 sbc a,a
 out (#fe),a
 ... 256 times

 each frame:

 ld de,1000
 add hl,de

I.e. each frame add another value to the accumulator. Different values produce various kinds of modulation, a good variety of those.

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

117

Re: next gen engine ideas

Neat idea, don't think we've used that anywhere yet.

I wonder if it could be pushed even further. Like, instead of every frame, add the offset at a variable rate. That could perhaps turn into a sort of 1-bit FM, without the use of PCM emulation trickery. (Sorry for hijacking your idea immediately, but I recently tried to implement actual FM again, and came to the same conclusion as last time: It's possible to do the necessary calculations fast enough, but the output is too noisy for reasons not entirely clear to me.)

118

Re: next gen engine ideas

One problem with it is that I still can't figure out the math required to control the modulation in a predictable way - without it a suitable modulator needs to be hand picked for each and every note. So yeah, maybe a variable rate offset will turn it into something more useful and controllable.

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

119

Re: next gen engine ideas

I think that generally, pre-calc is a viable option. The number of unique notes in a song is usually not that high, so size-wise it's probably ok. More broadly speaking, pre-calc could open up quite a few new paths for beeper. We'd just need an editor that supports that *cough cough*

The alternative would be to, well, use a suitable modulator, which boils down to having one or more additional counters/oscs. Which is what lead me to the "scheduler" design I described above. The whole scheduling part is actually not that important. The core idea is to unroll the sound loop, say, 8 or 16 times, updating the main counters on each iteration and spreading out the more expensive computations across the various iterations. When using a 12-bit main counter, updating an auxilliary 8-bit counter every 16 sound loop iterations should give sufficient precision and speed.

My last, failed experiment uses something along those lines. It's running off 32 byte wavetables (which, in conjunction with an 8-bit main counter, gives a reasonable frequency range). When the aux counter overflows, a variable offset is added to the wavetable pointer, and the offset itself is negated. The problem is that my usual 16-32-64-112t PCM renderer is too noisy, so I would need to rewrite the whole thing using multi-core (ie, one copy of the sound loop for each volume level). It should be possible without duplicating all the "expensive calculation" versions of the sound loop, but eh... it's still a lot of tedious work.

120 (edited by utz 2023-01-09 12:33:06)

Re: next gen engine ideas

BASE=#18

init
    di
    ld hl,0
    ld de,BASE*#400
    exx
    ld hl,0
    ld de,0
    ld bc,BASE*#20
    ld sp,BASE*8

.play_note
    add hl,bc
    ld a,h
    cp #20
    sbc a,a
    out (#fe),a

    ex de,hl
    add hl,sp
    sbc a,a
.mod1=$+1
    and #40
    ex de,hl
    add a,h
    ld h,a

    exx
    add hl,de
    ld a,(.mod1)
    adc a,0
    ld (.mod1),a
    exx

    jr .play_note

??? Now what. If I could get it to only do the part where it goes "oooeoouuwww", that'd be cool.

Post's attachments

test.tap 154 b, 1 downloads since 2023-01-09 

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

121

Re: next gen engine ideas

Btw, I think I know what you mean re: maths now. It's often kinda tricky to know what the resulting perceived tonal frequency will be.

122 (edited by Shiru 2023-01-09 15:46:14)

Re: next gen engine ideas

Yeah, I trying to get my head around it, but it doesn't really works the expected way. The inner adder works as usual, 3500000/t-states of inner loop/(65536/FREQ1). The outer adder is presumably 3500000*number of inner loop iterations/t-states of inner loop/(65536/FREQ2). However, when the second (modulation) frequency happens to be above the inner loop sample rate, i.e. a few phase changes should happen, it introduces another frequency into the equation, a kind of low frequency carrier, and the resulting frequency kinda gets unpredictable.

Not that it is useless anyways, but to make it usable from composer standpoint it is better to find a way to provide the secondary divider in a form better than a 0..65535 value per note.

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

123

Re: next gen engine ideas

    di
    ld hl,0
    ld de,0
    ld bc,#180
    ld sp,#38+#180/4

.play_note
    add hl,bc

    ex de,hl
    add hl,sp
    ccf
    sbc a,a
    ex de,hl
    and h
    ld h,a

    cp #20
    sbc a,a
    out (#fe),a

    dec ixl
    jr nz,.play_note
    dec bc
    jr .play_note

Not going to pretend I have any idea what's going on here. Some interesting sounds happening though. Seems that the note frequency is actually determined by the value in sp, not the one in bc. Just resetting the phase without additional modulation in the outer loop does something rather Earth Shaker-y. inc sp instead of dec bc is fun, too. No idea how to make any practical use of all of this, though.

Post's attachments

test.tap 139 b, 4 downloads since 2023-01-09 

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

Re: next gen engine ideas

the last test.tap reminds me of some bytebeat effects!  Sounds a bit like a human voice...

125 (edited by Shiru 2023-01-10 13:30:06)

Re: next gen engine ideas

Just come up with a dumb, but more controllable and thus usable PWM-like modulation idea:


    ld hl,0
    ld bc,100
    exx
    ld hl,0
    ld bc,201
    
loop

    add hl,bc
    ld a,h
    exx
    add hl,bc
    cp h
    exx
    sbc a,a
    and 16
    out (#fe),a

    jp loop

bc=100, bc'=100+detune is the regular PWM like drift, bc=100, bc'=bc*2+detune is one with octave etc, bc'=bc*4+detune is another octave, etc. Other not related values is kinda Earth Shaker'y, but not so much, a different kind of the sound.


Edit: I tested it out, and it actually matches exactly to Phaser1 in the resulting sound for any given adders I thought to test. Interesting.

Re-Edit: Nah, I messed up the previous test (was testing it inside Ear Shaver EX framework, and used a wrong pointer). It is really different both from EarthShaker and Phaser1! Hence giving this potential engine a name of CrossPhase, will add it as an Ear Shaver EX's update for now.

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