home *** CD-ROM | disk | FTP | other *** search
- // allocated track:
- // 1. same LastNote if note not in pattern
- // 2. first free with no note in pattern
- // 3. first free
- // 4. track with oldest high note (C6+)
- // 5. track with oldest mid note (C3+)
- // 6. track with oldest note
-
- int mi::AllocateTrack(CSequence *pseq, int note)
- {
-
- for (int c = 0; c < numTracks; c++)
- {
- if (Tracks[c].LastNote == note)
- {
- if (pseq != NULL)
- {
- byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c);
- if (*pdata == NOTE_NO)
- return c;
-
- }
-
- }
- }
-
- int best = -1;
-
-
- for (c = 0; c < numTracks; c++)
- {
- if (Tracks[c].Voices[Tracks[c].FreeVoice^1].State == CVoice::inactive)
- {
- if (pseq != NULL)
- {
- byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c);
- if (*pdata == NOTE_NO)
- return c;
-
- }
-
- if (best == -1)
- best = c;
- }
- }
-
- if (best != -1)
- return best;
-
- // if we got here it means all voices are active
- int oldt = -1;
-
- // check high
- for (c = 0; c < numTracks; c++)
- {
- if (Tracks[c].LastNote >= ((6 << 4) + 1)) // >= C6
- {
- int at = Tracks[c].Voices[Tracks[c].FreeVoice^1].ActiveTime;
- if (at > oldt)
- {
- oldt = at;
- best = c;
- }
- }
-
- }
-
- if (best != -1)
- return best;
-
- // check mid
- for (c = 0; c < numTracks; c++)
- {
- if (Tracks[c].LastNote >= ((3 << 4) + 1)) // >= C3
- {
- int at = Tracks[c].Voices[Tracks[c].FreeVoice^1].ActiveTime;
- if (at > oldt)
- {
- oldt = at;
- best = c;
- }
- }
-
- }
-
- if (best != -1)
- return best;
-
- // check low
- for (c = 0; c < numTracks; c++)
- {
- int at = Tracks[c].Voices[Tracks[c].FreeVoice^1].ActiveTime;
- if (at > oldt)
- {
- oldt = at;
- best = c;
- }
- }
-
-
- assert(best != -1);
-
- return best;
-
- }
-
- void miex::MidiControlChange(int const ctrl, int const channel, int const value)
- {
- // TODO: check channel
-
- if (ctrl != 64) // 64 = sustain pedal
- return;
-
-
- 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;
- }
-
-
-
- }
-
-
- void mi::MidiNoteOff(int c, CSequence *pseq, int notedelay)
- {
- Tracks[c].NoteOff();
-
- if (pseq != NULL)
- {
- byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c);
-
- if (notedelay > 0)
- {
- if (pdata[0] != NOTE_NO)
- {
- if (pdata[2] == 0x0d)
- {
- int ondelay = pdata[3] >> 1;
- pdata[2] = 0x0b;
- pdata[3] = (ondelay << 4) | (notedelay >> 1);
- }
- else
- {
- // ondelay = 0
- pdata[2] = 0x0b;
- pdata[3] = (notedelay >> 1);
- }
- }
- else
- {
- pdata[0] = NOTE_OFF;
- pdata[2] = 0x0d;
- pdata[3] = (byte)notedelay;
- }
- }
- else
- {
- pdata[0] = NOTE_OFF;
- }
-
-
- }
-
- }
-
-
- void mi::MidiNote(int const channel, int const value, int const velocity)
- {
- // TODO: check channel
-
- if (value / 12 > 9)
- return;
-
- byte n = (((value / 12)-1) << 4) | ((value % 12) + 1);
-
- CSequence *pseq;
-
- int stateflags = pCB->GetStateFlags();
-
- if (stateflags & SF_PLAYING && stateflags & SF_RECORDING)
- pseq = pCB->GetPlayingSequence(ThisMachine);
- else
- pseq = NULL;
-
-
- int notedelay = pMasterInfo->PosInTick * 24 / pMasterInfo->SamplesPerTick;
-
- if (velocity > 0)
- {
- int c = AllocateTrack(pseq, n);
-
- Tracks[c].Note = n;
- Tracks[c].Velocity = velocity;
- Tracks[c].NoteOn();
-
- if (pseq != NULL)
- {
- byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c);
- pdata[0] = n;
- pdata[1] = velocity;
-
- if (notedelay > 0)
- {
- pdata[2] = 0x0d;
- pdata[3] = (byte)notedelay;
- }
- }
-
-
- }
- else
- {
- for (int c = 0; c < numTracks; c++)
- {
- if (Tracks[c].Note == n)
- {
- if (SustainPedal)
- Tracks[c].Sustained = true;
- else
- MidiNoteOff(c, pseq, notedelay);
-
- break;
- }
-
-
- }
- }
-
-
- }
-