DSP_EXPORT void processBlock(BlockData& data) { // iterate on MIDI events for(uint i=0;i<data.inputMidiEvents.length;i++) { // forward all events (unchanged) data.outputMidiEvents.push(data.inputMidiEvents[i]); // add transposed Note On and Off events MidiEventType type=MidiEventUtils::getType(data.inputMidiEvents[i]); if(type==kMidiNoteOn || type==kMidiNoteOff) { // determine the index of the note in the major scale int absoluteNoteInScale=MidiEventUtils::getNote(data.inputMidiEvents[i])-key; int noteInScale=(absoluteNoteInScale%12); int noteIndexInScale=majorKeyNotes.find(noteInScale%12); for(uint j=0;j<offsets.length;j++) { if(offsets[j]!=0) { int diff=0; // if the note has been found, use our scale to find the appropriate interval if(noteIndexInScale>=0) { int newNoteInScale=getRelativeNoteValueInScale(noteIndexInScale+offsets[j]); diff=newNoteInScale-noteInScale; // set proper octave if(diff*offsets[j]<0) { diff+=12*sign(offsets[j]); } // handle case for more than one octave diff+=(offsets[j]/7)*12; } else { // use predefined intervals (note is not in the scale anyway) diff=predefinedIntervals[offsets[j]+9]; } // create new note event if valid (not out of MIDI range) int newNote=MidiEventUtils::getNote(data.inputMidiEvents[i])+diff; if(newNote>=0 && newNote<128) { tempEvent=data.inputMidiEvents[i]; MidiEventUtils::setNote(tempEvent,newNote); data.outputMidiEvents.push(tempEvent); } } } } } }
void handleMidiEvent(const MidiEvent& evt) { switch(MidiEventUtils::getType(evt)) { case kMidiNoteOn: { // find voice for the note on event (in case it is already here) // or use the first empty slot (note=-1) tempVoice.currentNote=MidiEventUtils::getNote(evt); int index=voices.find(tempVoice); if(index<0) { if(activeVoicesCount<voices.length) { index=activeVoicesCount; activeVoicesCount++; } } if(index>=0) { voices[index].NoteOn(evt); } break; } case kMidiNoteOff: { // find voice for the note off event tempVoice.currentNote=MidiEventUtils::getNote(evt); int index=voices.find(tempVoice); if(index>=0) { voices[index].NoteOff(); } break; } case kMidiPitchWheel: { // update pitch for all voices currentPitchOffset=2*double(MidiEventUtils::getPitchWheelValue(evt))/8192.0; for(uint i=0;i<activeVoicesCount;i++) { if(voices[i].omega>0) { voices[i].ForcePitch(); } } break; } case kMidiControlChange: { // sustain pedal changed event if(MidiEventUtils::getCCNumber(evt)==64) { // if pedal is down bool down=(MidiEventUtils::getCCValue(evt)>=64); if(down!=pedalIsDown) { pedalIsDown=down; if(pedalIsDown==false) { for(uint i=0;i<activeVoicesCount;i++) { voices[i].PedalReleased(); } } } } } } }