diff options
-rw-r--r-- | muse/muse/audio.cpp | 50 | ||||
-rw-r--r-- | muse/muse/driver/alsamidi.cpp | 18 | ||||
-rw-r--r-- | muse/muse/driver/jack.cpp | 33 | ||||
-rw-r--r-- | muse/muse/instruments/minstrument.cpp | 19 | ||||
-rw-r--r-- | muse/muse/instruments/minstrument.h | 1 | ||||
-rw-r--r-- | muse/muse/midi.cpp | 6 | ||||
-rw-r--r-- | muse/muse/midictrl.h | 2 | ||||
-rw-r--r-- | muse/muse/midioutport.cpp | 443 | ||||
-rw-r--r-- | muse/muse/midioutport.h | 6 | ||||
-rw-r--r-- | muse/muse/midiseq.cpp | 139 | ||||
-rw-r--r-- | muse/muse/midiseq.h | 46 | ||||
-rw-r--r-- | muse/muse/seqmsg.cpp | 15 | ||||
-rw-r--r-- | muse/muse/sync.cpp | 2 | ||||
-rw-r--r-- | muse/muse/sync.h | 4 | ||||
-rw-r--r-- | muse/synti/organ/CMakeLists.txt | 2 |
15 files changed, 400 insertions, 386 deletions
diff --git a/muse/muse/audio.cpp b/muse/muse/audio.cpp index f8b5410b..864f221d 100644 --- a/muse/muse/audio.cpp +++ b/muse/muse/audio.cpp @@ -557,9 +557,55 @@ void Audio::processMsg() case SEQM_IDLE: idle = msg->a; - // fall through + midiBusy = idle; + break; + + case MS_SET_RTC: + midiSeq->initRealtimeTimer(); + break; + + case SEQM_ADD_TRACK: + midiBusy = true; + song->insertTrack2(msg->track); + midiSeq->updatePollFd(); + midiBusy = false; + break; + + case SEQM_REMOVE_TRACK: + midiBusy = true; + song->removeTrack2(msg->track); + midiSeq->updatePollFd(); + midiBusy = false; + break; + case SEQM_ADD_PART: + midiBusy = true; + song->cmdAddPart((Part*)msg->p1); + midiBusy = false; + break; + case SEQM_REMOVE_PART: + midiBusy = true; + song->cmdRemovePart((Part*)msg->p1); + midiBusy = false; + break; + case SEQM_CHANGE_PART: + midiBusy = true; + song->cmdChangePart((Part*)msg->p1, (Part*)msg->p2); + midiBusy = false; + break; + case SEQM_MOVE_TRACK: + midiBusy = true; + song->moveTrack((Track*)(msg->p1), (Track*)(msg->p2)); + midiBusy = false; + break; + case AUDIO_ADDMIDIPLUGIN: + midiBusy = true; + ((MidiTrackBase*)msg->track)->addPlugin(msg->mplugin, msg->ival); + midiBusy = false; + break; default: - midiSeq->sendMsg(msg); + midiBusy = true; + song->processMsg(msg); + midiBusy = false; break; } } diff --git a/muse/muse/driver/alsamidi.cpp b/muse/muse/driver/alsamidi.cpp index be214068..dc030d87 100644 --- a/muse/muse/driver/alsamidi.cpp +++ b/muse/muse/driver/alsamidi.cpp @@ -461,7 +461,7 @@ void AlsaMidi::read(MidiSeq* seq) unsigned char* data = ((unsigned char*)ev->data.ext.ptr) + 1; int len = ev->data.ext.len - 2; if ((len == 4) && (data[0] == 0x7f) && (data[2] == 0x06)) { - seq->mmcInput(data[1], data[3], 0); +//TODO seq->mmcInput(data[1], data[3], 0); break; } if ((len == 11) && (data[0] == 0x7f) @@ -474,7 +474,7 @@ void AlsaMidi::read(MidiSeq* seq) int f = data[9]; int sf = data[10]; AL::Pos pos(h * 60 + m, s, f, sf); - seq->mmcInput(data[1], data[3], pos); +//TODO seq->mmcInput(data[1], data[3], pos); break; } } @@ -500,27 +500,27 @@ void AlsaMidi::read(MidiSeq* seq) break; case SND_SEQ_EVENT_CLOCK: - seq->realtimeSystemInput(0, 0xf8); +//TODO seq->realtimeSystemInput(0, 0xf8); break; case SND_SEQ_EVENT_START: - seq->realtimeSystemInput(0, 0xfa); +//TODO seq->realtimeSystemInput(0, 0xfa); break; case SND_SEQ_EVENT_CONTINUE: - seq->realtimeSystemInput(0, 0xfb); +//TODO seq->realtimeSystemInput(0, 0xfb); break; case SND_SEQ_EVENT_STOP: - seq->realtimeSystemInput(0, 0xfc); +//TODO seq->realtimeSystemInput(0, 0xfc); break; case SND_SEQ_EVENT_TICK: - seq->realtimeSystemInput(0, 0xf9); +//TODO seq->realtimeSystemInput(0, 0xf9); break; case SND_SEQ_EVENT_SONGPOS: - seq->setSongPosition(0, ev->data.control.value); +//TODO seq->setSongPosition(0, ev->data.control.value); break; case SND_SEQ_EVENT_SENSING: break; case SND_SEQ_EVENT_QFRAME: - seq->mtcInputQuarter(0, ev->data.control.value); +//TODO seq->mtcInputQuarter(0, ev->data.control.value); break; // case SND_SEQ_EVENT_CLIENT_START: // case SND_SEQ_EVENT_CLIENT_EXIT: diff --git a/muse/muse/driver/jack.cpp b/muse/muse/driver/jack.cpp index 5e909cda..4fb29676 100644 --- a/muse/muse/driver/jack.cpp +++ b/muse/muse/driver/jack.cpp @@ -822,7 +822,7 @@ void JackAudio::putEvent(Port port, const MidiEvent& e) printf("MidiOut<%s>: jackMidi: ", portName(port).toLatin1().data()); e.dump(); } - void* pb = jack_port_get_buffer(port.jackPort(), segmentSize); + void* pb = jack_port_get_buffer(port.jackPort(), segmentSize); unsigned ft; if (transportState == JackTransportRolling) { ft = e.time() - pos.frame; @@ -837,9 +837,13 @@ printf("time >= segmentSize -- %d\n", segmentSize - ft); } else ft = 0; + switch(e.type()) { case ME_NOTEON: case ME_NOTEOFF: + case ME_POLYAFTER: + case ME_CONTROLLER: + case ME_PITCHBEND: { unsigned char* p = jack_midi_event_reserve(pb, ft, 3, segmentSize); if (p == 0) { @@ -852,13 +856,32 @@ printf("time >= segmentSize -- %d\n", segmentSize - ft); } break; - case ME_POLYAFTER: - case ME_CONTROLLER: case ME_PROGRAM: case ME_AFTERTOUCH: - case ME_PITCHBEND: + { + unsigned char* p = jack_midi_event_reserve(pb, ft, 2, segmentSize); + if (p == 0) { + fprintf(stderr, "JackMidi: buffer overflow, event lost\n"); + return; + } + p[0] = e.type() | e.channel(); + p[1] = e.dataA(); + } + break; case ME_SYSEX: - case ME_META: + { + const unsigned char* data = e.data(); + int len = e.len(); + unsigned char* p = jack_midi_event_reserve(pb, ft, len+2, segmentSize); + if (p == 0) { + fprintf(stderr, "JackMidi: buffer overflow, event lost\n"); + return; + } + p[0] = 0xf0; + p[len+1] = 0xf7; + memcpy(p+1, data, len); + } + break; case ME_SONGPOS: case ME_CLOCK: case ME_START: diff --git a/muse/muse/instruments/minstrument.cpp b/muse/muse/instruments/minstrument.cpp index b69cd1f3..9c766194 100644 --- a/muse/muse/instruments/minstrument.cpp +++ b/muse/muse/instruments/minstrument.cpp @@ -205,25 +205,6 @@ MidiInstrument::~MidiInstrument() } //--------------------------------------------------------- -// reset -// send note off to all channels -//--------------------------------------------------------- - -void MidiInstrument::reset(MidiOutPort* mp) - { - MidiEvent ev; - ev.setType(0x90); - for (int chan = 0; chan < MIDI_CHANNELS; ++chan) { - ev.setChannel(chan); - for (int pitch = 0; pitch < 128; ++pitch) { - ev.setA(pitch); - ev.setB(0); - mp->putEvent(ev); - } - } - } - -//--------------------------------------------------------- // readPatchGroup //--------------------------------------------------------- diff --git a/muse/muse/instruments/minstrument.h b/muse/muse/instruments/minstrument.h index b18eaa13..5d6a5ab3 100644 --- a/muse/muse/instruments/minstrument.h +++ b/muse/muse/instruments/minstrument.h @@ -109,7 +109,6 @@ class MidiInstrument { void read(QDomNode); std::vector<SysEx>* sysexList() { return &sysex; } MidiController* midiController(int num) const; - void reset(MidiOutPort*); std::vector<PatchGroup>* groups() { return &pg; } }; diff --git a/muse/muse/midi.cpp b/muse/muse/midi.cpp index 47556328..987567ce 100644 --- a/muse/muse/midi.cpp +++ b/muse/muse/midi.cpp @@ -63,7 +63,7 @@ unsigned const char gsOnMsg[] = { }; unsigned const char xgOnMsg[] = { 0x43, // yamaha id - 0x10, // device number + 0x10, // device number (0) 0x4c, // model id 0x00, // address (high, mid, low) 0x00, @@ -609,10 +609,8 @@ void Audio::initDevices() MidiOutPort* mp = *i; MidiInstrument* instr = mp->instrument(); if (!instr) - continue; + continue; // TODO: use default instrument? EventList* events = instr->midiInit(); - if (events->empty()) - continue; for (iEvent ie = events->begin(); ie != events->end(); ++ie) { MidiEvent ev(0, 0, ie->second); mp->playMidiEvent(&ev); diff --git a/muse/muse/midictrl.h b/muse/muse/midictrl.h index 25d8220f..f728d58f 100644 --- a/muse/muse/midictrl.h +++ b/muse/muse/midictrl.h @@ -76,10 +76,12 @@ const int CTRL_NO_CTRL = 0x40006; const int CTRL_VAL_UNKNOWN = -1; // used as unknown hwVal +const int CTRL_14_OFFSET = 0x10000; const int CTRL_RPN_OFFSET = 0x20000; const int CTRL_NRPN_OFFSET = 0x30000; const int CTRL_RPN14_OFFSET = 0x50000; const int CTRL_NRPN14_OFFSET = 0x60000; +const int CTRL_NONE_OFFSET = 0x70000; namespace AL { class Xml; diff --git a/muse/muse/midioutport.cpp b/muse/muse/midioutport.cpp index 371ce55a..73351b0c 100644 --- a/muse/muse/midioutport.cpp +++ b/muse/muse/midioutport.cpp @@ -33,6 +33,8 @@ #include "sync.h" #include "gconfig.h" +static const unsigned char mmcDeferredPlayMsg[] = { 0x7f, 0x7f, 0x06, 0x03 }; + //--------------------------------------------------------- // MidiOutPort //--------------------------------------------------------- @@ -120,121 +122,6 @@ void MidiOutPort::read(QDomNode node) } //--------------------------------------------------------- -// putEvent -// send event to alsa midi driver -// called from MidiSeq::processTimerTick -//--------------------------------------------------------- - -#define playEvent(a) midiDriver->putEvent(alsaPort(), a); - -void MidiOutPort::putEvent(const MidiEvent& ev) - { - if (ev.type() == ME_CONTROLLER) { - int a = ev.dataA(); - int b = ev.dataB(); - int chn = ev.channel(); - if (chn == 255) { - // port controller - if (hwCtrlState(a) == ev.dataB()) - return; - setHwCtrlState(a, b); - } - else { - MidiChannel* mc = channel(chn); - // - // optimize controller settings - // - if (mc->hwCtrlState(a) == ev.dataB()) - return; - mc->setHwCtrlState(a, b); - } - - if (a == CTRL_PITCH) { - playEvent(MidiEvent(0, chn, ME_PITCHBEND, b, 0)); - return; - } - if (a == CTRL_PROGRAM) { - // don't output program changes for GM drum channel -// if (!(song->mtype() == MT_GM && chn == 9)) { - int hb = (b >> 16) & 0xff; - int lb = (b >> 8) & 0xff; - int pr = b & 0x7f; - if (hb != 0xff) - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HBANK, hb)); - if (lb != 0xff) - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_LBANK, lb)); - playEvent(MidiEvent(0, chn, ME_PROGRAM, pr, 0)); - return; -// } - } - if (a == CTRL_MASTER_VOLUME) { - unsigned char sysex[] = { - 0x7f, 0x7f, 0x04, 0x01, 0x00, 0x00 - }; - sysex[1] = _deviceId; - sysex[4] = b & 0x7f; - sysex[5] = (b >> 7) & 0x7f; - MidiEvent e(ev.time(), ME_SYSEX, sysex, 6); - playEvent(e); - return; - } - -#if 1 // if ALSA cannot handle RPN NRPN etc. - if (a < 0x1000) { // 7 Bit Controller - //putMidiEvent(MidiEvent(0, chn, ME_CONTROLLER, a, b)); - playEvent(ev); - } - else if (a < 0x20000) { // 14 bit high resolution controller - int ctrlH = (a >> 8) & 0x7f; - int ctrlL = a & 0x7f; - int dataH = (b >> 7) & 0x7f; - int dataL = b & 0x7f; - playEvent(MidiEvent(0, chn, ME_CONTROLLER, ctrlH, dataH)); - playEvent(MidiEvent(0, chn, ME_CONTROLLER, ctrlL, dataL)); - } - else if (a < 0x30000) { // RPN 7-Bit Controller - int ctrlH = (a >> 8) & 0x7f; - int ctrlL = a & 0x7f; - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, b)); - } - else if (a < 0x40000) { // NRPN 7-Bit Controller - int ctrlH = (a >> 8) & 0x7f; - int ctrlL = a & 0x7f; - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, b)); - } - else if (a < 0x60000) { // RPN14 Controller - int ctrlH = (a >> 8) & 0x7f; - int ctrlL = a & 0x7f; - int dataH = (b >> 7) & 0x7f; - int dataL = b & 0x7f; - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); - } - else if (a < 0x70000) { // NRPN14 Controller - int ctrlH = (a >> 8) & 0x7f; - int ctrlL = a & 0x7f; - int dataH = (b >> 7) & 0x7f; - int dataL = b & 0x7f; - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); - playEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); - } - else { - printf("putEvent: unknown controller type 0x%x\n", a); - } -#endif - } - playEvent(ev); - } - -//--------------------------------------------------------- // sendGmOn // send GM-On message to midi device and keep track // of device state @@ -304,7 +191,7 @@ void MidiOutPort::sendXgOn() void MidiOutPort::sendSysex(const unsigned char* p, int n) { MidiEvent event(0, ME_SYSEX, p, n); - putEvent(event); + routeEvent(event); } //--------------------------------------------------------- @@ -314,7 +201,7 @@ void MidiOutPort::sendSysex(const unsigned char* p, int n) void MidiOutPort::sendStart() { MidiEvent event(0, 0, ME_START, 0, 0); - putEvent(event); + routeEvent(event); } //--------------------------------------------------------- @@ -324,7 +211,7 @@ void MidiOutPort::sendStart() void MidiOutPort::sendStop() { MidiEvent event(0, 0, ME_STOP, 0, 0); - putEvent(event); + routeEvent(event); } //--------------------------------------------------------- @@ -334,7 +221,7 @@ void MidiOutPort::sendStop() void MidiOutPort::sendClock() { MidiEvent event(0, 0, ME_CLOCK, 0, 0); - putEvent(event); + routeEvent(event); } //--------------------------------------------------------- @@ -344,7 +231,7 @@ void MidiOutPort::sendClock() void MidiOutPort::sendContinue() { MidiEvent event(0, 0, ME_CONTINUE, 0, 0); - putEvent(event); + routeEvent(event); } //--------------------------------------------------------- @@ -354,7 +241,7 @@ void MidiOutPort::sendContinue() void MidiOutPort::sendSongpos(int pos) { MidiEvent event(0, 0, ME_SONGPOS, pos, 0); - putEvent(event); + routeEvent(event); } //--------------------------------------------------------- @@ -364,26 +251,8 @@ void MidiOutPort::sendSongpos(int pos) void MidiOutPort::playMidiEvent(MidiEvent* ev) { - if (ev->type() == ME_NOTEON) { - _meter[0] += ev->dataB()/2; - if (_meter[0] > 127.0f) - _meter[0] = 127.0f; - } - RouteList* orl = outRoutes(); - bool sendToFifo = false; - for (iRoute i = orl->begin(); i != orl->end(); ++i) { - if (i->type == Route::SYNTIPORT) { - SynthI* synti = (SynthI*)i->track; - if (synti->eventFifo()->put(*ev)) - printf("MidiOut::playMidiEvent(): synti overflow, drop event\n"); - } - else - sendToFifo = true; - } - if (sendToFifo) { - if (eventFifo.put(*ev)) - printf("MidiPort::playMidiEvent(): port overflow, drop event\n"); - } + if (eventFifo.put(*ev)) + printf("MidiPort::playMidiEvent(): port overflow, drop event\n"); } //------------------------------------------------------------------- @@ -423,7 +292,6 @@ void MidiOutPort::process(unsigned fromTick, unsigned toTick, unsigned, unsigned } } - int portVelo = 0; for (int ch = 0; ch < MIDI_CHANNELS; ++ch) { MidiChannel* mc = channel(ch); @@ -463,24 +331,25 @@ void MidiOutPort::process(unsigned fromTick, unsigned toTick, unsigned, unsigned velo += ev.dataB(); } mc->addMidiMeter(velo); - portVelo += velo; } } - addMidiMeter(portVelo); - pipeline()->apply(fromTick, toTick, &el, &_schedEvents); // // route events to destination // - for (iMPEvent i = _schedEvents.begin(); i != _schedEvents.end(); ++i) { - if (i->time() >= toFrame) { - _schedEvents.erase(_schedEvents.begin(), i); + int portVelo = 0; + iMPEvent i = _schedEvents.begin(); + for (; i != _schedEvents.end(); ++i) { + if (i->time() >= toFrame) break; - } routeEvent(*i); + if (i->type() == ME_NOTEON) + portVelo += i->dataB(); } + _schedEvents.erase(_schedEvents.begin(), i); + addMidiMeter(portVelo); } //--------------------------------------------------------- @@ -489,18 +358,37 @@ void MidiOutPort::process(unsigned fromTick, unsigned toTick, unsigned, unsigned void MidiOutPort::routeEvent(const MidiEvent& event) { + if (event.type() == ME_CONTROLLER) { + int a = event.dataA(); + int b = event.dataB(); + int chn = event.channel(); + if (chn == 255) { + // port controller + if (hwCtrlState(a) == event.dataB()) + return; + setHwCtrlState(a, b); + } + else { + MidiChannel* mc = channel(chn); + // + // optimize controller settings + // + if (mc->hwCtrlState(a) == event.dataB()) + return; + mc->setHwCtrlState(a, b); + } + } + for (iRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r) { switch (r->type) { case Route::MIDIPORT: - midiBusy = true; - _playEvents.insert(event); // schedule - midiBusy = false; + queueAlsaEvent(event); break; case Route::SYNTIPORT: ((SynthI*)(r->track))->playEvents()->insert(event); break; case Route::JACKMIDIPORT: - audioDriver->putEvent(jackPort(0), event); + queueJackEvent(event); break; default: fprintf(stderr, "MidiOutPort::process(): invalid routetype\n"); @@ -510,6 +398,197 @@ void MidiOutPort::routeEvent(const MidiEvent& event) } //--------------------------------------------------------- +// queueAlsaEvent +// called from MidiSeq +//--------------------------------------------------------- + +void MidiOutPort::queueAlsaEvent(const MidiEvent& ev) + { + midiBusy = true; + if (ev.type() == ME_CONTROLLER) { + int a = ev.dataA(); + int b = ev.dataB(); + int chn = ev.channel(); + unsigned t = ev.time(); + + if (a == CTRL_PROGRAM) { + // don't output program changes for GM drum channel +// if (!(song->mtype() == MT_GM && chn == 9)) { + int hb = (b >> 16) & 0xff; + int lb = (b >> 8) & 0xff; + int pr = b & 0x7f; + if (hb != 0xff) + _playEvents.insert(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HBANK, hb)); + if (lb != 0xff) + _playEvents.insert(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LBANK, lb)); + _playEvents.insert(MidiEvent(t+2, chn, ME_PROGRAM, pr, 0)); +// } + } + else if (a == CTRL_MASTER_VOLUME) { + unsigned char sysex[] = { + 0x7f, 0x7f, 0x04, 0x01, 0x00, 0x00 + }; + sysex[1] = _deviceId; + sysex[4] = b & 0x7f; + sysex[5] = (b >> 7) & 0x7f; + _playEvents.insert(MidiEvent(t, ME_SYSEX, sysex, 6)); + } + else if (a < CTRL_14_OFFSET) // 7 Bit Controller + _playEvents.insert(ev); + else if (a < CTRL_RPN_OFFSET) { // 14 bit high resolution controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + int dataH = (b >> 7) & 0x7f; + int dataL = b & 0x7f; + _playEvents.insert(MidiEvent(t, chn, ME_CONTROLLER, ctrlH, dataH)); + _playEvents.insert(MidiEvent(t+1, chn, ME_CONTROLLER, ctrlL, dataL)); + } + else if (a < CTRL_NRPN_OFFSET) { // RPN 7-Bit Controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + _playEvents.insert(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); + _playEvents.insert(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); + _playEvents.insert(MidiEvent(t+2, chn, ME_CONTROLLER, CTRL_HDATA, b)); + } + else if (a < CTRL_RPN14_OFFSET) { // NRPN 7-Bit Controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + _playEvents.insert(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); + _playEvents.insert(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); + _playEvents.insert(MidiEvent(t+2, chn, ME_CONTROLLER, CTRL_HDATA, b)); + } + else if (a < CTRL_NRPN14_OFFSET) { // RPN14 Controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + int dataH = (b >> 7) & 0x7f; + int dataL = b & 0x7f; + _playEvents.insert(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); + _playEvents.insert(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); + _playEvents.insert(MidiEvent(t+2, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); + _playEvents.insert(MidiEvent(t+3, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); + } + else if (a < CTRL_NONE_OFFSET) { // NRPN14 Controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + int dataH = (b >> 7) & 0x7f; + int dataL = b & 0x7f; + _playEvents.insert(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); + _playEvents.insert(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); + _playEvents.insert(MidiEvent(t+2, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); + _playEvents.insert(MidiEvent(t+3, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); + } + else { + printf("putEvent: unknown controller type 0x%x\n", a); + } + } + else + _playEvents.insert(ev); + midiBusy = false; + } + +//--------------------------------------------------------- +// queueJackEvent +// called from MidiSeq +//--------------------------------------------------------- + +#define JO(e) audioDriver->putEvent(jackPort(0), e); + +void MidiOutPort::queueJackEvent(const MidiEvent& ev) + { + if (ev.type() == ME_CONTROLLER) { + int a = ev.dataA(); + int b = ev.dataB(); + int chn = ev.channel(); + unsigned t = ev.time(); + + if (a == CTRL_PROGRAM) { + // don't output program changes for GM drum channel +// if (!(song->mtype() == MT_GM && chn == 9)) { + int hb = (b >> 16) & 0xff; + int lb = (b >> 8) & 0xff; + int pr = b & 0x7f; + if (hb != 0xff) + JO(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HBANK, hb)); + if (lb != 0xff) + JO(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LBANK, lb)); + JO(MidiEvent(t+2, chn, ME_PROGRAM, pr, 0)); +// } + } + else if (a == CTRL_MASTER_VOLUME) { + unsigned char sysex[] = { + 0x7f, 0x7f, 0x04, 0x01, 0x00, 0x00 + }; + sysex[1] = _deviceId; + sysex[4] = b & 0x7f; + sysex[5] = (b >> 7) & 0x7f; + JO(MidiEvent(t, ME_SYSEX, sysex, 6)); + } + else if (a < CTRL_14_OFFSET) { // 7 Bit Controller + JO(ev); + } + else if (a < CTRL_RPN_OFFSET) { // 14 bit high resolution controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + int dataH = (b >> 7) & 0x7f; + int dataL = b & 0x7f; + JO(MidiEvent(t, chn, ME_CONTROLLER, ctrlH, dataH)); + JO(MidiEvent(t+1, chn, ME_CONTROLLER, ctrlL, dataL)); + } + else if (a < CTRL_NRPN_OFFSET) { // RPN 7-Bit Controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + JO(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); + JO(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); + JO(MidiEvent(t+2, chn, ME_CONTROLLER, CTRL_HDATA, b)); + } + else if (a < CTRL_RPN14_OFFSET) { // NRPN 7-Bit Controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + JO(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); + JO(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); + JO(MidiEvent(t+2, chn, ME_CONTROLLER, CTRL_HDATA, b)); + } + else if (a < CTRL_NRPN14_OFFSET) { // RPN14 Controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + int dataH = (b >> 7) & 0x7f; + int dataL = b & 0x7f; + JO(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); + JO(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); + JO(MidiEvent(t+2, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); + JO(MidiEvent(t+3, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); + } + else if (a < CTRL_NONE_OFFSET) { // NRPN14 Controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + int dataH = (b >> 7) & 0x7f; + int dataL = b & 0x7f; + JO(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); + JO(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); + JO(MidiEvent(t+2, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); + JO(MidiEvent(t+3, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); + } + else { + printf("putEvent: unknown controller type 0x%x\n", a); + } + } + else { + JO(ev); + } + } +#undef JO + +//--------------------------------------------------------- +// playAlsaEvent +// called from MidiSeq +//--------------------------------------------------------- + +void MidiOutPort::playAlsaEvent(const MidiEvent& event) const + { + midiDriver->putEvent(alsaPort(), event); + } + +//--------------------------------------------------------- // setInstrument //--------------------------------------------------------- @@ -627,14 +706,14 @@ void MidiOutPort::stop() mmcPos[8] = mtc.s(); mmcPos[9] = mtc.f(); mmcPos[10] = mtc.sf(); -//TODO mp->sendSysex(mmcStopMsg, sizeof(mmcStopMsg)); -// mp->sendSysex(mmcPos, sizeof(mmcPos)); +//TODO sendSysex(mmcStopMsg, sizeof(mmcStopMsg)); +// sendSysex(mmcPos, sizeof(mmcPos)); } if (genMCSync) { // Midi Clock // send STOP and // "set song position pointer" -// mp->sendStop(); -// mp->sendSongpos(audio->curTickPos() * 4 / config.division); +// sendStop(); +// sendSongpos(audio->curTickPos() * 4 / config.division); } } } @@ -645,7 +724,6 @@ void MidiOutPort::stop() void MidiOutPort::start() { -#if 0 if (!(genMMC || genMCSync)) return; if (!sendSync()) @@ -658,7 +736,6 @@ void MidiOutPort::start() else sendStart(); } -#endif } //--------------------------------------------------------- @@ -667,6 +744,52 @@ void MidiOutPort::start() void MidiOutPort::reset() { - instrument()->reset(this); +/* TODO + MidiEvent ev; + ev.setType(0x90); + for (int chan = 0; chan < MIDI_CHANNELS; ++chan) { + ev.setChannel(chan); + for (int pitch = 0; pitch < 128; ++pitch) { + ev.setA(pitch); + ev.setB(0); + mp->putEvent(ev); + } + } +*/ } +#if 0 +//--------------------------------------------------------- +// processMidiClock +//--------------------------------------------------------- + +void MidiSeq::processMidiClock() + { + if (genMCSync) + midiPorts[txSyncPort].sendClock(); + if (state == START_PLAY) { + // start play on sync + state = PLAY; + _midiTick = playTickPos; + midiClock = playTickPos; + + int bar, beat, tick; + sigmap.tickValues(_midiTick, &bar, &beat, &tick); + midiClick = sigmap.bar2tick(bar, beat+1, 0); + + double cpos = tempomap.tick2time(playTickPos); + samplePosStart = samplePos - lrint(cpos * sampleRate); + rtcTickStart = rtcTick - lrint(cpos * realRtcTicks); + + endSlice = playTickPos; + lastTickPos = playTickPos; + + tempoSN = tempomap.tempoSN(); + + startRecordPos.setPosTick(playTickPos); + } + midiClock += config.division/24; + } +#endif + + diff --git a/muse/muse/midioutport.h b/muse/muse/midioutport.h index 3f376c43..44460d8d 100644 --- a/muse/muse/midioutport.h +++ b/muse/muse/midioutport.h @@ -45,6 +45,8 @@ class MidiOutPort : public MidiTrackBase { MidiFifo eventFifo; void routeEvent(const MidiEvent&); + void queueAlsaEvent(const MidiEvent& event); + void queueJackEvent(const MidiEvent& event); signals: void instrumentChanged(); @@ -69,7 +71,7 @@ class MidiOutPort : public MidiTrackBase { bool guiVisible() const; bool hasGui() const; - void putEvent(const MidiEvent&); +// void putEvent(const MidiEvent&); MPEventList* playEvents() { return &_playEvents; } @@ -97,6 +99,8 @@ class MidiOutPort : public MidiTrackBase { void stop(); void start(); void reset(); + + void playAlsaEvent(const MidiEvent& event) const; }; #endif diff --git a/muse/muse/midiseq.cpp b/muse/muse/midiseq.cpp index 028e0c0d..1fb8dd19 100644 --- a/muse/muse/midiseq.cpp +++ b/muse/muse/midiseq.cpp @@ -18,14 +18,10 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. //============================================================================= -#include "globals.h" -#include "midi.h" #include "midiseq.h" -#include "midictrl.h" #include "audio.h" #include "driver/mididev.h" #include "driver/audiodev.h" -#include "driver/jackaudio.h" #ifdef __APPLE__ #include "driver/coretimer.h" @@ -38,70 +34,12 @@ #include "sync.h" #include "song.h" #include "gconfig.h" -#include "al/tempo.h" -#include "al/al.h" -#include "instruments/minstrument.h" -#include "midichannel.h" -#include "midiinport.h" #include "midioutport.h" MidiSeq* midiSeq; -static const unsigned char mmcStopMsg[] = { 0x7f, 0x7f, 0x06, 0x01 }; -static const unsigned char mmcDeferredPlayMsg[] = { 0x7f, 0x7f, 0x06, 0x03 }; - volatile bool midiBusy; //--------------------------------------------------------- -// readMsg -//--------------------------------------------------------- - -static void readMsg(void* p, void*) - { - MidiSeq* at = (MidiSeq*)p; - at->readMsg(); - } - -//--------------------------------------------------------- -// processMsg -//--------------------------------------------------------- - -void MidiSeq::processMsg(const ThreadMsg* m) - { - AudioMsg* msg = (AudioMsg*)m; - switch (msg->id) { - case MS_SET_RTC: - initRealtimeTimer(); - break; - case SEQM_ADD_TRACK: - song->insertTrack2(msg->track); - updatePollFd(); - break; - case SEQM_REMOVE_TRACK: - song->removeTrack2(msg->track); - updatePollFd(); - break; - case SEQM_ADD_PART: - song->cmdAddPart((Part*)msg->p1); - break; - case SEQM_REMOVE_PART: - song->cmdRemovePart((Part*)msg->p1); - break; - case SEQM_CHANGE_PART: - song->cmdChangePart((Part*)msg->p1, (Part*)msg->p2); - break; - case SEQM_MOVE_TRACK: - song->moveTrack((Track*)(msg->p1), (Track*)(msg->p2)); - break; - case AUDIO_ADDMIDIPLUGIN: - ((MidiTrackBase*)msg->track)->addPlugin(msg->mplugin, msg->ival); - break; - default: - song->processMsg(msg); - break; - } - } - -//--------------------------------------------------------- // MidiSeq //--------------------------------------------------------- @@ -183,7 +121,6 @@ void MidiSeq::threadStart(void*) // midiRead //--------------------------------------------------------- - static void midiRead(void*, void*) { midiDriver->read(midiSeq); @@ -204,7 +141,7 @@ void MidiSeq::updatePollFd() if (timerFd != -1) addPollFd(timerFd, POLLIN, midiTick, this, 0); } - addPollFd(toThreadFdr, POLLIN, ::readMsg, this, 0); +// addPollFd(toThreadFdr, POLLIN, ::readMsg, this, 0); struct pollfd* pfd; int n; @@ -255,65 +192,28 @@ bool MidiSeq::start(int prio) return false; } -#if 0 -//--------------------------------------------------------- -// processMidiClock -//--------------------------------------------------------- - -void MidiSeq::processMidiClock() - { - if (genMCSync) - midiPorts[txSyncPort].sendClock(); - if (state == START_PLAY) { - // start play on sync - state = PLAY; - _midiTick = playTickPos; - midiClock = playTickPos; - - int bar, beat, tick; - sigmap.tickValues(_midiTick, &bar, &beat, &tick); - midiClick = sigmap.bar2tick(bar, beat+1, 0); - - double cpos = tempomap.tick2time(playTickPos); - samplePosStart = samplePos - lrint(cpos * sampleRate); - rtcTickStart = rtcTick - lrint(cpos * realRtcTicks); - - endSlice = playTickPos; - lastTickPos = playTickPos; - - tempoSN = tempomap.tempoSN(); - - startRecordPos.setPosTick(playTickPos); - } - midiClock += config.division/24; - } -#endif - //--------------------------------------------------------- // midiTick +// schedule events in MidiOutPort->playEvents() +// midiBusy locks access to MidiOutPortList and +// MidiOutPort. +// Locking is somwhat special and assumes that MidiSeq +// is a realtime thread and has higher priority than +// the audio thread (JACK callback) and can therefore not +// be interrupted. Instead of waiting for midiBusy to +// get false we simply miss this clock tick. //--------------------------------------------------------- void MidiSeq::midiTick(void* p, void*) { - MidiSeq* at = (MidiSeq*)p; - at->processTimerTick(); - } - -//--------------------------------------------------------- -// processTimerTick -//--------------------------------------------------------- - -void MidiSeq::processTimerTick() - { extern int watchMidi; ++watchMidi; // make a simple watchdog happy - timer->getTimerTicks(); // read elapsed rtc timer ticks + MidiSeq* at = (MidiSeq*)p; + at->getTimerTicks(); // read elapsed rtc timer ticks - if (midiBusy) { - // miss this timer tick + if (midiBusy) return; - } // // schedule all events upto framePos-segmentSize // (previous segment) @@ -328,22 +228,9 @@ void MidiSeq::processTimerTick() for (; i != el->end(); ++i) { if (i->time() > curFrame) break; - mp->putEvent(*i); + mp->playAlsaEvent(*i); } el->erase(el->begin(), i); } } -//--------------------------------------------------------- -// msgMsg -//--------------------------------------------------------- - -void MidiSeq::msgMsg(int id) - { - AudioMsg msg; - msg.id = id; - Thread::sendMsg(&msg); - } - -void MidiSeq::msgSetRtc() { msgMsg(MS_SET_RTC); } - diff --git a/muse/muse/midiseq.h b/muse/muse/midiseq.h index 91a90b1a..7fee4bf1 100644 --- a/muse/muse/midiseq.h +++ b/muse/muse/midiseq.h @@ -22,17 +22,7 @@ #define __MIDISEQ_H__ #include "thread.h" -#include "midievent.h" - #include "driver/timerdev.h" -namespace AL { - class Pos; - }; -class AL::Pos; - -class MPEventList; -class SynthI; -class MTC; //--------------------------------------------------------- // MidiSeq @@ -41,47 +31,17 @@ class MTC; class MidiSeq : public Thread { int realRtcTicks; Timer* timer; - int midiClock; -/* Testing */ -// int lastTickPos; // position of last sync tick - // run values: -// unsigned _midiTick; -// double mclock1, mclock2; -// double songtick1, songtick2; -// int recTick1, recTick2; -// int lastTempo; -// double timediff[24]; -// int storedtimediffs; -/* Testing */ - - bool initRealtimeTimer(); static void midiTick(void* p, void*); - void processTimerTick(); - virtual void processMsg(const ThreadMsg*); - void updatePollFd(); - - void mtcSyncMsg(const MTC& mtc, bool seekFlag); - void mtcInputFull(const unsigned char* p, int n); - void nonRealtimeSystemSysex(const unsigned char* p, int n); + int getTimerTicks() { return timer->getTimerTicks(); } public: MidiSeq(const char* name); bool start(int); virtual void threadStop(); virtual void threadStart(void*); - - void realtimeSystemInput(int, int); - void mtcInputQuarter(int, unsigned char); - void setSongPosition(int, int); - void mmcInput(int id, int cmd, const AL::Pos&); - - void msgMsg(int id); - void msgStart(); - void msgSetRtc(); - void msgAddSynthI(SynthI* synth); - void msgRemoveSynthI(SynthI* synth); - + void updatePollFd(); + bool initRealtimeTimer(); }; extern MidiSeq* midiSeq; diff --git a/muse/muse/seqmsg.cpp b/muse/muse/seqmsg.cpp index c21080ff..c9e1d349 100644 --- a/muse/muse/seqmsg.cpp +++ b/muse/muse/seqmsg.cpp @@ -591,16 +591,11 @@ void Audio::msgPanic() void Audio::msgLocalOff() { -#if 0 //TODO3 - MidiEvent ev1(0, 0, 0, ME_CONTROLLER, CTRL_LOCAL_OFF, 0); - for (int i = 0; i < MIDI_PORTS; ++i) { - for (int chan = 0; chan < MIDI_CHANNELS; ++chan) { - ev1.setPort(i); - ev1.setChannel(chan); - msgPlayMidiEvent(&ev1); - } - } -#endif + MidiEvent ev1(0, 0, ME_CONTROLLER, CTRL_LOCAL_OFF, 0); + + MidiChannelList* cl = song->midiChannel(); + for (iMidiChannel i = cl->begin(); i != cl->end(); ++i) + (*i)->playMidiEvent(&ev1); } //--------------------------------------------------------- diff --git a/muse/muse/sync.cpp b/muse/muse/sync.cpp index 2176453b..ecef91fe 100644 --- a/muse/muse/sync.cpp +++ b/muse/muse/sync.cpp @@ -64,6 +64,7 @@ enum { MMC_GOTO = 0x44 }; +#if 0 //--------------------------------------------------------- // mmcInput // Midi Machine Control Input received @@ -495,4 +496,5 @@ void MidiSeq::mtcSyncMsg(const MTC& /*mtc*/, bool /*seekFlag*/) printf(" state %d diff %f\n", mtcState, diff); #endif } +#endif diff --git a/muse/muse/sync.h b/muse/muse/sync.h index b87bae7c..b8d8920b 100644 --- a/muse/muse/sync.h +++ b/muse/muse/sync.h @@ -24,10 +24,6 @@ #include "mtc.h" extern bool debugSync; - -// extern int rxDeviceId; -// extern int txDeviceId; - extern MTC mtcOffset; extern bool extSyncFlag; extern bool genMTCSync; // output MTC Sync diff --git a/muse/synti/organ/CMakeLists.txt b/muse/synti/organ/CMakeLists.txt index 4a185799..2c23daea 100644 --- a/muse/synti/organ/CMakeLists.txt +++ b/muse/synti/organ/CMakeLists.txt @@ -29,8 +29,6 @@ add_library ( organ SHARED ${organ_uis} ) -target_link_libraries( organ synti ) - # - tell cmake to name target organ.so instead of # liborgan.so # - use precompiled header files |