"String" range issue

savt22

Member
Hi everyone,

I've been working on a Teensy polyphonic synth, and it's been a great learning experience. I'm really happy with the results, but I've got one last bug I can't seem to figure out. (I should warn that this is my first real coding project, so you may have to speak plainly...)

The Karplus Strong 'String' seems to have a fixed lower range - I can't get it to play a note lower than E1, or 41.02(?)hz. I am mixing the voice with another oscillator, and I can hear the frequency of the waveform oscillator decreasing if I play, say, D1 - but the String oscillator plays only E1 in response to any midi note below E1.

Is this an intentional thing? I recognise that it was designed to mirror a guitar sound, and E1 is the bottom note of a standard bass tuning. There doesn't seem to be an upper bound, and any note from E1 up sounds the right frequency.

Thanks,
Tom
 
The length of the delay line is limited to 536 entries:
Code:
    int16_t buffer[536]; // TODO: dynamically use audio memory blocks
Which corresponds to a round-trip delay of 24.3ms, which is 41.13Hz
 
Ahh I see… that’s a shame.

Is this this a necessary limitation for it to work on the teensy, or is it just how the implementation was done?
 
No, just an arbitrary limit in the source code... Note the TODO comment acknowledging this isn't ideal! Someone got time to do a PR on this maybe?
 
The length of the delay line is limited to 536 entries:
Code:
    int16_t buffer[536]; // TODO: dynamically use audio memory blocks
Which corresponds to a round-trip delay of 24.3ms, which is 41.13Hz

Thanks for your help - I might have some time over the next few days to figure this out.

How did you go from 536 to 24.3… to 41.13? Would a simple fix just be to change 536 to the value corresponding to C0, or is it more complicated than that?
 
I started playing with that module, there’s all sorts of changes it needs… Apart from variable-length buffer to allow lower notes (I put that in audio blocks, though it’s not backward-compatible), the feedback filter should be configurable and pitch-adaptive; as it is, the sustain varies significantly with the pitch.

I got halfway then distracted by other more pressing stuff … as you do :)
 
I started playing with that module, there’s all sorts of changes it needs… Apart from variable-length buffer to allow lower notes (I put that in audio blocks, though it’s not backward-compatible), the feedback filter should be configurable and pitch-adaptive; as it is, the sustain varies significantly with the pitch.

I got halfway then distracted by other more pressing stuff … as you do :)
Hmm… your reply suggests it’s not as simple as changing 536 to a different value. Why is a variable length buffer needed?

I’m thinking this is going to all be a bit beyond me…
 
No, it's simple enough just to change the 536 to 1349 to allow going down to C0 - though as noted by @MarkT it's much better practice to use a const int with a name (and a proper comment) and then change every occurrence of 536 to that. It uses more memory, going from 536*2 = 1072 bytes per object to 1349*2 = 2698 bytes. But a Teensy 4.x has a fair bit of RAM, so you'd have to be squeezed for that to worry you.

My naturally parsimonious nature objects to allocating static buffers of a size that's not going to be used 99% of the time, and the comment on the buffer[] has a TODO to use audio blocks for a future development, so that's the approach I took - anything from F3 up only needs one block, F2 up to E3 needs 2, and so on. And a non-playing object consumes no blocks at all.
 
Back
Top