PDSynthInstrument playNote never calling the synthRenderFunc

I'm unable to get PDSynthInstrument to play a note.
I create 10 synths and set them to 0-128 MIDI range.

The generator code is fmsynth as provided in this example:
https://devforum.play.date/t/pd-sound-synth-setgenerator-tutorial

playNote works for a synth with the same config as the ones used in the instrument.

instrument->playNote never calls synthNoteOnFunc.

I'm on SDK 2.0.1. This is running on Linux simulator.

Is there something I'm missing from the PDSynthInstrument API?

#define MAX_NOTES 10
PDSynth* synth;
PDSynth* synths[MAX_NOTES];
PDSynthInstrument* inst;

// fmsynth stuff omitted

static bool synth_setup(void) {
  inst = pd->sound->instrument->newInstrument();
  synth = pd->sound->synth->newSynth();
  for (int i = 0; i < MAX_NOTES; ++i) {
    synths[i] = pd->sound->synth->newSynth();
    if (synths[i] == NULL) return false;
  }

  // same as fmsynth example
  memset(&generator, 0, sizeof(generator));
  generator.modulator.ratio = 1.1;
  generator.modulator.level = 0.2;
  generator.carrier.ratio = 1.0;

  pd->sound->synth->setWaveform(synth, kWaveformSine);
  pd->sound->synth->setAttackTime(synth, 0.005);
  pd->sound->synth->setDecayTime(synth, 0.1);
  pd->sound->synth->setSustainLevel(synth, 0.3);
  pd->sound->synth->setReleaseTime(synth, 1);

  const int stereo = 1;
  pd->sound->synth->setGenerator(synth, stereo, fm_render, fm_noteOn, fm_release, fm_setparam, fm_dealloc, &generator);

  for (int i = 0; i < MAX_NOTES; ++i) {
    pd->sound->synth->setWaveform(synths[i], kWaveformSine);
    pd->sound->synth->setAttackTime(synths[i], 0.005);
    pd->sound->synth->setDecayTime(synths[i], 0.1);
    pd->sound->synth->setSustainLevel(synths[i], 0.3);
    pd->sound->synth->setReleaseTime(synths[i], 1);
    pd->sound->synth->setGenerator(synths[i], stereo, fm_render, fm_noteOn, fm_release, fm_setparam, fm_dealloc, &generator);
  
    const int ok = pd->sound->instrument->addVoice(inst, synths[i], 0, 128, i * 12);
    if (!ok) return false;
  }

  pd->sound->instrument->setVolume(inst, 1, 1);
  return true;
}

void play_note(const float note) {
  const float vel = 1.0;
  const float len = 0.2;
  // plays the note, fm_render (synthRenderFunc) is called
  pd->sound->synth->playNote(synth, note, vel, len, 0);

  // nothing is played, synthNoteOnFunc is called but not fm_render (synthRenderFunc) not called
  // return value is not NULL
  PDSynth* s = pd->sound->instrument->playNote(inst, note, vel, len, 0);
}

int eventHandler(PlaydateAPI* pd, PDSystemEvent event, uint32_t arg) {
    [...]
    play_note(1760.0f);
    [...]
    return 0;
}

Can you post a functional demo? It'll be much quicker for me to spot the problem that way. I took a stab at compiling your code there but filling in fmsynth stuff omitted isn't just a simple matter of copying and pasting my FM synth code. Not to mention you don't tell which one you're using--there's four separate iterations in the original post. You say same as fmsynth example but there's nothing named generator in any version of that code.

playdate_demo.zip (114.6 KB)

Here's a sample demo.
Pressing B plays a note with synth.
Pressing A plays a note with instrument.

Playing with this, I found a strange behaviour: the instrument sound will play but only while the non instrument synth sound is playing. (pressing B then A)
Pressing just A produces no sound.

1 Like