JeremiahRose
Member
I've been experimenting with building my own AudioSynthXXX objects, working towards the eventual goal of doing some very basic physical modelling synthesis on a Teensy 4.1.
My first try used floating point maths and a sin function within the update() loop. This didn't work well, the sound was extremely distorted - I think I was going way over my budget in terms of processor operations per second and causing overruns.
So in an attempt to learn how the inner loop of a synthesis object needs to work, I'm referring to the source code of the AudioSynthWaveformSine object on the Teensy Github. There are several aspects about this code that I don't understand, so I was wondering if someone could explain it to me?
My questions are:
Thanks!
My first try used floating point maths and a sin function within the update() loop. This didn't work well, the sound was extremely distorted - I think I was going way over my budget in terms of processor operations per second and causing overruns.
So in an attempt to learn how the inner loop of a synthesis object needs to work, I'm referring to the source code of the AudioSynthWaveformSine object on the Teensy Github. There are several aspects about this code that I don't understand, so I was wondering if someone could explain it to me?
Code:
void AudioSynthWaveformSine::update(void)
{
audio_block_t *block;
uint32_t i, ph, inc, index, scale;
int32_t val1, val2;
if (magnitude) {
block = allocate();
if (block) {
ph = phase_accumulator;
inc = phase_increment;
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
index = ph >> 24;
val1 = AudioWaveformSine[index];
val2 = AudioWaveformSine[index+1];
scale = (ph >> 8) & 0xFFFF;
val2 *= scale;
val1 *= 0x10000 - scale;
#if defined(__ARM_ARCH_7EM__)
block->data[i] = multiply_32x32_rshift32(val1 + val2, magnitude);
#elif defined(KINETISL)
block->data[i] = (((val1 + val2) >> 16) * magnitude) >> 16;
#endif
ph += inc;
}
phase_accumulator = ph;
transmit(block);
release(block);
return;
}
}
phase_accumulator += phase_increment * AUDIO_BLOCK_SAMPLES;
}
My questions are:
- This code uses a wavetable (AudioWaveformSine). Is this absolutely necessary to achieve acceptable performance on a Teensy 4.1?
- It's using linear interpolation between points in the wavetable, but I don't understand the bitwise maths. What is the purpose of the scale = (ph >> 8) & 0xFFFF; statement and the following lines and why can't we just use normal multiplication and division?
- Why is the multiply_32x32_rshift32(val1 + val2, magnitude); statement used instead of normal math operators and what is it doing?
- Is it possible to do floating point math inside an audio update() function without overruns?
Thanks!