501
583
case SEQM_PLAY_MIDI_EVENT:
502
data->playEvent((MidiEvent*)(msg->p1));
585
MidiPlayEvent* ev = (MidiPlayEvent*)(msg->p1);
586
midiPorts[ev->port()].putEvent(ev);
504
589
case SEQM_SET_RTC_TICKS:
508
if (data->state == PLAY)
511
598
case SEQM_SCAN_ALSA_MIDI_PORTS:
512
599
alsaScanMidiPorts();
515
if (data->state == IDLE && msg->a)
517
else if ((data->state == PLAY || data->state == PRECOUNT)
602
if (state == IDLE && msg->a)
603
startPlay(song->cpos());
604
else if ((state == PLAY || state == PRECOUNT) && !msg->a)
521
607
case MIDI_ADD_SYNTHI:
524
610
case MIDI_SHOW_INSTR_GUI:
525
((MidiInstrument*)(msg->p1))->showGui(msg->a);
611
// ((MidiInstrument*)(msg->p1))->showGui(msg->a);
529
song->processMsg(msg);
534
//---------------------------------------------------------
536
//---------------------------------------------------------
538
void MidiThreadPrivate::playEvent(MidiEvent* event)
540
MidiTrack* t = event->trk();
541
MidiPort* port = &midiPorts[event->port()];
542
switch (event->type()) {
543
case MidiEvent::Note:
545
int len = event->lenTick();
546
int pitch = event->pitch();
547
int velo = event->velo();
551
pitch += t->transposition;
558
velo = (velo * t->compression) / 100;
561
if (velo < 1) // no off event
564
len = (len * t->len) / 100;
565
t->addActivity(velo);
567
if (len <= 0) // don�t allow zero length
569
MidiEvent* noteOff = new MidiEvent(*event);
570
noteOff->setType(MidiEvent::NoteOff);
571
noteOff->setPosTick(event->posTick() + len);
572
noteOff->setPitch(pitch);
573
stuckNotes->add(noteOff, noteOff->posTick());
574
if (len != event->lenTick() || pitch != event->pitch()
575
| velo != event->velo()) {
577
MidiEvent* ev = new MidiEvent(*event);
587
case MidiEvent::Ctrl7:
588
case MidiEvent::Ctrl14:
591
controlChanged = true;
593
case MidiEvent::NoteOff:
596
t->addActivity(-(event->velo()));
599
if (t && song->mute(t))
603
port->putEvent(event);
604
if (port->instrument()->hasGui())
605
port->instrument()->writeToGui(event);
615
song->processMidiMsg(msg);
608
620
//---------------------------------------------------------
610
622
//---------------------------------------------------------
612
void MidiThreadPrivate::stopPlay()
624
void MidiThread::stopPlay()
626
endRecord.setPosTick(playTickPos);
627
audio->msgPlay(false);
614
629
//---------------------------------------------------
616
631
//---------------------------------------------------
618
for (iEvent i = stuckNotes->begin(); i != stuckNotes->end(); ++i)
619
playEvent((MidiEvent*)(i->second));
633
// printf("stopPlay: stuck notes %d\n", stuckNotes.size());
635
// midiOutputTrace = true;
636
for (iMPEvent i = stuckNotes.begin(); i != stuckNotes.end(); ++i)
637
playEvent(&i->second);
639
// midiOutputTrace = false;
622
641
//---------------------------------------------------
864
920
midiClick = sigmap.bar2tick(bar, beat, 0);
865
// printf("tick %d(%d) %d %d %d = %d\n",
866
// midiTick, song->cpos(), bar, beat, tick, midiClick);
868
// start real play on next midi sync
869
// current state is START_PLAY
922
// start real play on next midiClock
923
// current state is START_PLAY (set in seek)
872
926
//---------------------------------------------------------
874
928
//---------------------------------------------------------
876
void MidiThreadPrivate::seek(int pos)
930
void MidiThread::seek(int pos)
878
933
playTickPos = pos;
934
midiClick = pos; // first click on loop start
880
936
//---------------------------------------------------
882
938
//---------------------------------------------------
884
for (iEvent i = stuckNotes->begin(); i != stuckNotes->end(); ++i)
885
playEvent((MidiEvent*)(i->second));
940
for (iMPEvent i = stuckNotes.begin(); i != stuckNotes.end(); ++i)
941
playEvent(&i->second);
888
MidiDevice* syncDev = midiPorts[extSyncPort].device();
944
MidiDevice* syncDev = midiPorts[txSyncPort].device();
889
945
if (genMCSync && syncDev) {
890
946
int beat = (playTickPos * 4) / division;
891
947
syncDev->putStop(); // ??
892
948
syncDev->putSongpos(beat);
893
949
syncDev->putContinue(); // ??
895
audioThread->seek(playTickPos);
951
audio->msgSeek(playTickPos);
896
952
loopPassed = true; // for record loop mode
901
//---------------------------------------------------------
903
//---------------------------------------------------------
905
void MidiThreadPrivate::processMidiTick()
956
//---------------------------------------------------------
958
//---------------------------------------------------------
960
void MidiThread::playEvent(const MidiPlayEvent* event)
962
MidiPort* port = &midiPorts[event->port()];
963
port->putEvent(event);
964
if (port->instrument()->hasGui())
965
port->instrument()->writeToGui(event);
968
//---------------------------------------------------------
970
// collects all events between stick - etick
971
//---------------------------------------------------------
973
void MidiThread::nextEvents(int stick, int etick)
975
for (iTrack t = song->tracks()->begin(); t != song->tracks()->end(); ++t) {
976
if ((*t)->type() != Track::MIDI && (*t)->type() != Track::DRUM)
978
MidiTrack* track = (MidiTrack*)(*t);
979
if (track->node()->isMute())
981
PartList* pl = track->parts();
982
for (iPart p = pl->begin(); p != pl->end(); ++p) {
983
MidiPart* part = (MidiPart*)(p->second);
984
// dont play muted parts
987
EventList* events = part->events();
989
int partTick = part->posTick();
990
int delay = track->delay;
991
iEvent ie = events->lower_bound(stick - delay - partTick);
992
iEvent iend = events->lower_bound(etick - delay - partTick);
994
for (; ie != iend; ++ie) {
995
MidiEvent* ev = (MidiEvent*)ie->second;
997
// don�t play any meta events
999
if (ev->type() == MidiEvent::Meta)
1001
if (track->type() == Track::DRUM) {
1002
int instr = ev->pitch();
1003
if (ev->isNote() && drumMap[instr].mute) //Ignore muted drums
1006
int tick = ev->posTick() + delay + part->posTick();
1007
int port = track->outPort();
1008
int channel = track->outChannel();
1009
switch (ev->type()) {
1010
case MidiEvent::Note:
1011
case MidiEvent::NoteOff:
1013
int len = ev->lenTick();
1014
int pitch = ev->pitch();
1015
if (track->type() == Track::DRUM) { //Map drum-notes to the drum-map values
1016
int instr = ev->pitch();
1017
pitch = drumMap[instr].anote;
1018
port = drumMap[instr].port;
1019
channel = drumMap[instr].channel;
1022
pitch+= (track->transposition + song->globalPitchShift()); //Transpose non-drum notes
1025
int velo = ev->velo();
1030
velo += track->velocity;
1031
velo = (velo * track->compression) / 100;
1034
if (velo < 1) // no off event
1036
len = (len * track->len) / 100;
1037
if (len <= 0) // don�t allow zero length
1039
int veloOff = ev->veloOff();
1041
if (ev->type() == MidiEvent::Note)
1042
playEvents.add(tick,
1043
port, channel, 0x90, pitch, velo);
1045
playEvents.add(tick,
1046
port, channel, 0x80, pitch, veloOff);
1047
if (ev->type() == MidiEvent::Note) {
1048
stuckNotes.add(tick + len,
1050
veloOff ? 0x80 : 0x90, pitch, veloOff);
1051
track->addActivity(velo);
1056
case MidiEvent::Ctrl7:
1057
case MidiEvent::Ctrl14:
1058
controlChanged = true;
1060
playEvents.add(tick, ev, port, channel);
1068
//---------------------------------------------------------
1070
//---------------------------------------------------------
1072
void MidiThread::processMidiClock()
908
midiPorts[extSyncPort].clock();
1075
midiPorts[txSyncPort].clock();
909
1076
if (state == START_PLAY) {
910
1077
// start play on sync
912
midiTickStart = playTickPos;
913
midiTick = playTickPos;
914
midiSync = playTickPos;
915
rtcTickStart = rtcTick;
916
endSlice = playTickPos;
917
recTick = playTickPos;
918
lastTickPos = playTickPos;
919
startTime = curTime();
920
recStartTick = playTickPos;
921
write(sigFd, "1", 1); // PLAY
1079
_midiTick = playTickPos;
1080
midiClock = playTickPos;
1082
int bar, beat, tick;
1083
sigmap.tickValues(_midiTick, &bar, &beat, &tick);
1084
midiClick = sigmap.bar2tick(bar, beat+1, 0);
1086
double cpos = tempomap.tick2time(playTickPos);
1087
samplePosStart = samplePos - lrint(cpos * sampleRate);
1088
rtcTickStart = rtcTick - lrint(cpos * realRtcTicks);
1090
endSlice = playTickPos;
1091
recTick = playTickPos;
1092
lastTickPos = playTickPos;
1094
tempoSN = tempomap.tempoSN();
1096
startRecord.setPosTick(playTickPos);
1097
audio->msgPlay(true);
1099
midiClock += division/24;
925
1102
//---------------------------------------------------------
926
1103
// processTimerTick
1104
// fast hardware timer tick interrupt at
927
1106
//---------------------------------------------------------
929
void MidiThreadPrivate::processTimerTick()
1108
void MidiThread::processTimerTick()
1110
extern int watchMidi;
1111
++watchMidi; // make watchdog happy
1113
//---------------------------------------------------
1114
// if tempomap changed, fix
1115
// samplePosStart and rtcTickStart
1116
//---------------------------------------------------
1118
if (tempoSN != tempomap.tempoSN()) {
1119
double cpos = tempomap.tick2time(_midiTick);
1120
samplePosStart = samplePos - lrint(cpos * sampleRate);
1121
rtcTickStart = rtcTick - lrint(cpos * realRtcTicks);
1122
tempoSN = tempomap.tempoSN();
1125
//---------------------------------------------------
1126
// read elapsed rtc timer ticks
1127
//---------------------------------------------------
932
1130
if (timerFd != -1) {
933
1131
unsigned long nn;
934
1132
if (read(timerFd, &nn, sizeof(unsigned long)) != sizeof(unsigned long)) {
935
perror("illegal timer return");
1133
perror("rtc timer read error");
939
// rtcTicks (ticks per second);
941
if (tempoSN != tempomap.tempoSN()) {
942
midiTickStart = midiTick;
943
rtcTickStart = rtcTick;
944
tempoSN = tempomap.tempoSN();
947
midiTick = tempomap.time2tick(1.0/realRtcTicks
948
* (rtcTick - rtcTickStart)) + midiTickStart;
950
if (!extSyncFlag.value() && midiTick >= midiSync) {
952
midiSync += division/24;
1140
//---------------------------------------------------
1141
// compute current midiTick value
1142
//---------------------------------------------------
1144
if (audioTimebase) {
1145
samplePos = audio->curPlayPos();
1146
_midiTick = tempomap.time2tick(
1147
double(samplePos - samplePosStart) / double(sampleRate));
1150
_midiTick = tempomap.time2tick(
1151
double(rtcTick - rtcTickStart) / double(realRtcTicks)
1155
if (!extSyncFlag.value() && _midiTick >= midiClock)
955
1158
if (genMTCSync) {
956
1159
// printf("Midi Time Code Sync generation not impl.\n");
959
1162
if (state == PLAY) {
960
playTickPos = midiTick;
961
if (song->loop() && !extSyncFlag.value()
962
&& (playTickPos >= song->rpos())) {
1163
playTickPos = _midiTick;
1164
// start loop division/24-1 ticks earlier
1165
if (song->loop() && !extSyncFlag.value() && (playTickPos >= song->rpos()-division/24+1)) {
963
1166
seek(song->lpos());
964
// loop on next midiSync
1167
// loop on next midiClock
967
1170
if (playTickPos >= endSlice) {
968
1171
int next = endSlice + TICK_SLICE;
969
song->nextEvents(endSlice, next, playEvents);
1172
nextEvents(endSlice, next);
970
1173
endSlice = next;
972
if (playTickPos >= song->len() && !song->record() && !song->loop()) {
1175
if (playTickPos >= song->len() && (!song->record() || song->bounceTrack)
976
1180
if ((state == PRECOUNT || (song->click() && (state == PLAY)))
977
&& (midiTick >= midiClick)) {
978
MidiEvent* ev = new MidiEvent(clickPort, clickChan,
979
midiTick, MidiEvent::Note,
980
beatClickNote, beatClickVelo, 0, 4);
1181
&& (_midiTick >= midiClick)) {
1182
int bar, beat, tick;
981
1183
bool isMeasure = false;
983
1184
switch (state) {
985
if ((clickno % clicksMeasure) == 0)
1186
isMeasure = (clickno % clicksMeasure) == 0;
1187
midiClick += ticksBeat;
989
midiClick += ticksBeat;
992
sigmap.tickValues(playTickPos, &bar, &beat, &tick);
993
if (beat == 0 && tick == 0)
995
midiClick = sigmap.bar2tick(bar, beat+1, 0);
999
sigmap.tickValues(midiTick, &bar, &beat, &tick);
1000
//tick==0?*/ if (beat == 0 && tick == 0)
1195
sigmap.tickValues(_midiTick, &bar, &beat, &tick);
1002
1196
midiClick = sigmap.bar2tick(bar, beat+1, 0);
1197
isMeasure = beat == 0;
1007
1203
if (isMeasure) {
1008
ev->setPitch(measureClickNote);
1009
ev->setVelo(measureClickVelo);
1011
playEvents->add(ev);
1204
playEvents.add(_midiTick, clickPort, clickChan, 0x90,
1205
measureClickNote, measureClickVelo);
1206
stuckNotes.add(_midiTick+10, clickPort, clickChan, 0x90,
1207
measureClickNote, 0);
1210
playEvents.add(_midiTick, clickPort, clickChan, 0x90,
1211
beatClickNote, beatClickVelo);
1212
stuckNotes.add(_midiTick+10, clickPort, clickChan, 0x90,
1217
// play all event upto/including _midiTick
1013
1219
SEventList sevents;
1014
// printf("midiTick %d\n", midiTick);
1015
EventRange range1 = stuckNotes->equal_range(midiTick);
1016
// for (iEvent k = range1.first; k != range1.second; ++k)
1017
for (iEvent k = stuckNotes->begin(); k != range1.second; ++k)
1018
sevents.push_back(SEvent((MidiEvent*)(k->second)));
1019
EventRange range2 = playEvents->equal_range(midiTick);
1020
// for (iEvent k = range2.first; k != range2.second; ++k)
1021
for (iEvent k = playEvents->begin(); k != range2.second; ++k)
1022
sevents.push_back(SEvent((MidiEvent*)(k->second)));
1222
// collect stuck notes
1223
MPEventRange range1 = stuckNotes.equal_range(_midiTick);
1224
for (iMPEvent k = stuckNotes.begin(); k != range1.second; ++k)
1225
sevents.push_back(SEvent(&k->second));
1227
// collect play notes
1228
MPEventRange range2 = playEvents.equal_range(_midiTick);
1229
for (iMPEvent k = playEvents.begin(); k != range2.second; ++k)
1230
sevents.push_back(SEvent(&k->second));
1023
1232
if (!sevents.empty()) {
1024
1233
sevents.sort();
1025
1234
for (iSEvent sk = sevents.begin(); sk != sevents.end(); ++sk)
1026
1235
playEvent(sk->ev);
1027
EventRange range1 = stuckNotes->equal_range(midiTick);
1028
// stuckNotes->erase(range1.first, range1.second);
1029
// playEvents->erase(range2.first, range2.second);
1030
stuckNotes->erase(stuckNotes->begin(), range1.second);
1031
playEvents->erase(playEvents->begin(), range2.second);
1237
// why recompute range1?
1238
MPEventRange range1 = stuckNotes.equal_range(_midiTick);
1239
stuckNotes.erase(stuckNotes.begin(), range1.second);
1240
playEvents.erase(playEvents.begin(), range2.second);