emmanuel63
Well-known member
Hi,
I would like know if someone can reproduce my problem.
I have a simple 8 voices poly synth, running on a T4.0. I try to make the smallest code I could to help debugging.
When attached to a midi keyboard (real one or from laptop), I get stuck notes when playing lots of notes very fast (I mean some notes are playing forever). Here are some tests results :
- when setting the envelopes release time to 0, there is no stuck notes
- when triggering notes without midi messages (using a MPR121 capacitive module), there is no stuck notes.
I suspect a MIDI problem, because triggering notes with hardware (MPR121) is working fine, even randomly and very fast. I wonder if envelopes release management could cause trouble with reading incoming messages.
Thanks for any help,
Emmanuel
I would like know if someone can reproduce my problem.
I have a simple 8 voices poly synth, running on a T4.0. I try to make the smallest code I could to help debugging.
When attached to a midi keyboard (real one or from laptop), I get stuck notes when playing lots of notes very fast (I mean some notes are playing forever). Here are some tests results :
- when setting the envelopes release time to 0, there is no stuck notes
- when triggering notes without midi messages (using a MPR121 capacitive module), there is no stuck notes.
I suspect a MIDI problem, because triggering notes with hardware (MPR121) is working fine, even randomly and very fast. I wonder if envelopes release management could cause trouble with reading incoming messages.
Thanks for any help,
Emmanuel
Code:
#include <Audio.h>
// GUItool: begin automatically generated code
AudioSynthWaveformModulated waveformMod7; //xy=161,471
AudioSynthWaveformModulated waveformMod8; //xy=163,519
AudioSynthWaveformModulated waveformMod6; //xy=164,427
AudioSynthWaveformModulated waveformMod5; //xy=166,375
AudioSynthWaveformModulated waveformMod4; //xy=168,323
AudioSynthWaveformModulated waveformMod3; //xy=174,272
AudioSynthWaveformModulated waveformMod2; //xy=175,222
AudioSynthWaveformModulated waveformMod1; //xy=179,164
AudioEffectEnvelope envelope1; //xy=400,168
AudioEffectEnvelope envelope2; //xy=400,221
AudioEffectEnvelope envelope4; //xy=401,325
AudioEffectEnvelope envelope3; //xy=403,274
AudioEffectEnvelope envelope5; //xy=404,374
AudioEffectEnvelope envelope6; //xy=407,423
AudioEffectEnvelope envelope7; //xy=411,470
AudioEffectEnvelope envelope8; //xy=412,517
AudioMixer4 mixer2; //xy=592,385
AudioMixer4 mixer1; //xy=594,299
AudioMixer4 mixer3; //xy=719,330
AudioOutputI2S2 i2s2_1; //xy=864,331
AudioConnection patchCord1(waveformMod7, envelope7);
AudioConnection patchCord2(waveformMod8, envelope8);
AudioConnection patchCord3(waveformMod6, envelope6);
AudioConnection patchCord4(waveformMod5, envelope5);
AudioConnection patchCord5(waveformMod4, envelope4);
AudioConnection patchCord6(waveformMod3, envelope3);
AudioConnection patchCord7(waveformMod2, envelope2);
AudioConnection patchCord8(waveformMod1, envelope1);
AudioConnection patchCord9(envelope1, 0, mixer1, 0);
AudioConnection patchCord10(envelope2, 0, mixer1, 1);
AudioConnection patchCord11(envelope4, 0, mixer1, 3);
AudioConnection patchCord12(envelope3, 0, mixer1, 2);
AudioConnection patchCord13(envelope5, 0, mixer2, 0);
AudioConnection patchCord14(envelope6, 0, mixer2, 1);
AudioConnection patchCord15(envelope7, 0, mixer2, 2);
AudioConnection patchCord16(envelope8, 0, mixer2, 3);
AudioConnection patchCord17(mixer2, 0, mixer3, 1);
AudioConnection patchCord18(mixer1, 0, mixer3, 0);
AudioConnection patchCord19(mixer3, 0, i2s2_1, 0);
AudioConnection patchCord20(mixer3, 0, i2s2_1, 1);
// GUItool: end automatically generated code
const byte polyphony = 8;
AudioSynthWaveformModulated *osc1[] = {&waveformMod1, &waveformMod2, &waveformMod3, &waveformMod4, &waveformMod5, &waveformMod6, &waveformMod7, &waveformMod8}; //OSC1
AudioEffectEnvelope *envelope[] = {&envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8};
const float noteFreqs[128] = {8.176, 8.662, 9.177, 9.723, 10.301, 10.913, 11.562, 12.25, 12.978, 13.75, 14.568, 15.434, 16.352, 17.324, 18.354, 19.445, 20.602, 21.827, 23.125, 24.5, 25.957, 27.5, 29.135, 30.868, 32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55, 58.27, 61.735, 65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110, 116.541, 123.471, 130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220, 233.082, 246.942, 261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440, 466.164, 493.883, 523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880, 932.328, 987.767, 1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760, 1864.655, 1975.533, 2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520, 3729.31, 3951.066, 4186.009, 4434.922, 4698.636, 4978.032, 5274.041, 5587.652, 5919.911, 6271.927, 6644.875, 7040, 7458.62, 7902.133, 8372.018, 8869.844, 9397.273, 9956.063, 10548.08, 11175.3, 11839.82, 12543.85};
struct voices {
unsigned int counter; //use to time-stamp a voice when triggered
byte note;
};
voices voice[polyphony];
void setup() {
AudioMemory(500);
//***INIT OSCILLATORS AND ENVELOPES***//
for (byte i = 0; i < polyphony; i++) {
osc1[i]->begin(1, 300, WAVEFORM_SINE);
envelope[i]->attack(1);
envelope[i]->release(300);
}
//***VOICES SUMMING MIXERS***//
for (byte mixer_input = 0; mixer_input < 4; mixer_input++) {
mixer1.gain(mixer_input, 0.1); //low gain for your ears !
mixer2.gain(mixer_input, 0.1);
mixer3.gain(mixer_input, 0.2);
}
//****MIDI CALLBACK****//
usbMIDI.setHandleNoteOn(myNoteOn);
usbMIDI.setHandleNoteOff(myNoteOff);
}
void loop() {
usbMIDI.read();
}
//*********************************************************MIDI NOTE_ON NOTE_OFF*********************************************************//
void myNoteOn(byte MIDI_CHANNEL, byte note, byte velocity) {
voiceOn(note);
}
void myNoteOff(byte MIDI_CHANNEL, byte note, byte velocity) {
voiceOff(note);
}
//*********************************************************VOICES FUNCTION*********************************************************//
void voiceOn(byte myNote) {
for (byte i = 0; i <= polyphony; i++) { // note " i <= polyphony " to loop to number 8
//WHEN POLYPHONY IS REACHED, steal oldest voice
if ( i == polyphony) {
Serial.println("all voices used");
//find oldest voice
unsigned int oldest = 65535;
unsigned int oldest_voice = 0;
for (byte j = 0; j < polyphony; j++) {
if (voice[j].counter < oldest) {
oldest = voice[j].counter;
oldest_voice = j;
}
}
//re-trigger oldest voice with new note
voice[oldest_voice].counter++;
voice[oldest_voice].note = myNote;
osc1[oldest_voice]->frequency(noteFreqs[myNote]);
envelope[oldest_voice]->noteOn();
return;
}
//IF FREE VOICES, find first one
if (!envelope[i]->isActive()) {
voice[i].counter++;
voice[i].note = myNote;
osc1[i]->frequency(noteFreqs[myNote]);
envelope[i]->noteOn();
return;
}
}
}
void voiceOff(byte myNote) {
for (byte i = 0; i < polyphony; i++) {
if (voice[i].note == myNote) {
envelope[i]->noteOff();
voice[i].note = 0;
break;
}
}
}