I put together a tutorial for the new custom synth generator feature in 1.12 (didn't wind up in 1.11 after all like I'd tweeted above) as I was working on it, figured I'd go ahead and post it here for feedback.
I've structured this as if you're wrapping third party code into a custom generator so I've kept the synth implementation separate from the Playdate code. In this example we've got a very simple 2-operator FM synth, no real features yet, just to make sure synth->setGenerator()
works and we can get sound through. The important bit here is the render
callback which fills the audio buffers passed to it, nsamples
(=256) samples at a time. Since we called setGenerator
with the stereo
flag equal to zero, only the left
buffer is passed to the render function.
static int fm_render(void* userdata, int32_t* left, int32_t* right, int nsamples, uint32_t rate, int32_t drate)
{
FMSynth* fm = userdata;
for ( int i = 0; i < nsamples; ++i )
left[i] = FMSynth_getNextSample(fm) * 0x7fffff;
return nsamples;
}
Samples in the output buffer are in signed 8.24 fixed-point format, meaning +/- 0x7fffff
is the normal range and values outside this range will be clipped, unless they're scaled down, e.g. by lowering the channel volume. We ignore rate
and drate
here because we're using the pitch from the noteOn callback. If we wanted to add a frequency modulator by calling snd->synth->setFrequencyModulator()
we'd need to use rate
and drate
instead for it to work correctly. (We'll do that in a future installment to show how that works.)
fmsynth tutorial pt 1.zip (10.7 KB)