since the new Midi Control Change hack by Oskari inside Overloader there are now 4 more control numbers apart from the existing standard 128 midi cc messages. These control numbers allow machine developers to allow their machines to recognize some extra midi messages that weren't previously sent by MidiControlChange.
Control Code | Description |
252 | Channel Aftertouch |
253 | Polyphonic Aftertouch |
254 | Program Change |
255 | Pitch Bend |
you use this function to handle the MidiControlChange messages:
void miex::MidiControlChange(int const ctrl, int const channel, int const value)
example:
void miex::MidiControlChange(int const ctrl, int const channel, int const value) { // TODO: check channel switch (ctrl) { case 252: // 252 = channel aftertouch // Note: depth amount is in the higher byte { int c = channel; int stateflags = pmi->pCB->GetStateFlags(); if (stateflags & SF_PLAYING && stateflags & SF_RECORDING) { pseq = pmi->pCB->GetPlayingSequence(pmi->ThisMachine); byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c); pdata[1] = (int)(value >> 8); } else { pseq = NULL; } pmi->Tracks[c]->Depth = (value >> 8); // shifting bits to get correct depth // TODO: Channel aftertouch code here return; } break; case 253: // 253 = polyphonic aftertouch // Note: depth amount is in the lower byte, // and Note is in the higher byte { byte depth = value & 0xFF; byte note = value >> 8; byte n = (((note / 12)-1) << 4) | ((note % 12) + 1); for (int c = 0; c < numTracks; c++) { if (Tracks[c].Note == n) { int stateflags = pmi->pCB->GetStateFlags(); if (stateflags & SF_PLAYING && stateflags & SF_RECORDING) { pseq = pmi->pCB->GetPlayingSequence(pmi->ThisMachine); byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c); pdata[1] = (int)(depth); } else { pseq = NULL; } pmi->Tracks[c]->Depth = (depth); break; } } // TODO: Polyphonic aftertouch code here return; } break; case 254: // 254 = program change { int stateflags = pmi->pCB->GetStateFlags(); if (stateflags & SF_PLAYING && stateflags & SF_RECORDING) { pseq = pmi->pCB->GetPlayingSequence(pmi->ThisMachine); byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 1, 0); pdata[2] = (int)value; } else { pseq = NULL; } pmi->CurrentProgram = value; // TODO: Program change code here return; } break; case 255: // 255 = pitch bend { // Note: value is 14-bit, with a range from 0 to 16383 // with 8192 in the middle. int stateflags = pmi->pCB->GetStateFlags(); if (stateflags & SF_PLAYING && stateflags & SF_RECORDING) { pseq = pmi->pCB->GetPlayingSequence(pmi->ThisMachine); byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 1, 0); pdata[1] = (int)(value / 16383.0 * 254.0); } else { pseq = NULL; } pmi->NoteSpeed = pow(2.0,((float)(value - 8192) * pmi->BendRange / 8192.0)); // TODO: Pitch bend code here return; } break; case 64: // 64 = sustain pedal { // This part was borrowed from MidiRecExample.txt if (value < 64) { CSequence *pseq; int stateflags = pmi->pCB->GetStateFlags(); if (stateflags & SF_PLAYING && stateflags & SF_RECORDING) pseq = pmi->pCB->GetPlayingSequence(pmi->ThisMachine); else pseq = NULL; int notedelay = pmi->pMasterInfo->PosInTick * 24 / pmi->pMasterInfo->SamplesPerTick; pmi->SustainPedal = false; for (int c = 0; c < pmi->numTracks; c++) { if (pmi->Tracks[c].Note != NOTE_NO && pmi->Tracks[c].Sustained) { pmi->Tracks[c].Sustained = false; pmi->MidiNoteOff(c, pseq, notedelay); } } } else { pmi->SustainPedal = true; } // TODO: sustain pedal code here return; } break; default: // unknown control code { return; } break; } }