summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse/muse/audio.cpp50
-rw-r--r--muse/muse/driver/alsamidi.cpp18
-rw-r--r--muse/muse/driver/jack.cpp33
-rw-r--r--muse/muse/instruments/minstrument.cpp19
-rw-r--r--muse/muse/instruments/minstrument.h1
-rw-r--r--muse/muse/midi.cpp6
-rw-r--r--muse/muse/midictrl.h2
-rw-r--r--muse/muse/midioutport.cpp443
-rw-r--r--muse/muse/midioutport.h6
-rw-r--r--muse/muse/midiseq.cpp139
-rw-r--r--muse/muse/midiseq.h46
-rw-r--r--muse/muse/seqmsg.cpp15
-rw-r--r--muse/muse/sync.cpp2
-rw-r--r--muse/muse/sync.h4
-rw-r--r--muse/synti/organ/CMakeLists.txt2
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