diff options
56 files changed, 2139 insertions, 845 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog index f7b15ef7..bf30b856 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,15 @@ +18.06.2011: + (By Tim. Marked as p4.0.27) + - Major work, all synthesizers. Sysexes now wrapped in a header MFG ID (0x7c) + synth ID. Fixed leaks, crashes. + Each MESS synth (or just the single DSSI host) now has a unique ID, used in the sysex header. + TODOS: Finish DeicsOnze::getControllerInfo. Fix Fluid - must set to High Bank #2 to see any patch names! + *NOTE: Some data will now change upon saving a song! Compatibility with old songs is built-in and transparent. + Ask Tim for details. + *Feature: SimpleDrums now FULLY functional including effects. Support old songs + MusE-1 songs, tested OK. + - Fluid soft synth now remembers and displays the font name. + - Fixed midi TrackInfo patch name not initializing at position 0 even when value stored, with FluidSynth (possibly others). + - Fixed some leaks, lack of dtors cleanup call when repeatedly loading songs. Should be a weee bit more stable now. + - EXPERIMENT: Midi track input routes can now come from any of the synthesizers! This is a WIP and might change or disappear. 04.06.2011: - fixed regression with switching ctrl/shift when manipulating items in canvas. drag+shift limits movement, drag+ctrl copies (rj) diff --git a/muse2/muse/ctrl.cpp b/muse2/muse/ctrl.cpp index 922da337..65a04ba1 100644 --- a/muse2/muse/ctrl.cpp +++ b/muse2/muse/ctrl.cpp @@ -264,7 +264,6 @@ void CtrlList::read(Xml& xml) } */ - // Added by Tim. p3.3.6 //printf("CtrlList::read tag:%s\n", tag.toLatin1().constData()); int len = tag.length(); @@ -320,7 +319,6 @@ void CtrlList::read(Xml& xml) break; } - // Added by Tim. p3.3.6 //printf("CtrlList::read i:%d len:%d fs:%s frame %d: vs:%s val %f \n", i, len, fs.toLatin1().constData(), frame, vs.toLatin1().constData(), val); add(frame, val); @@ -333,7 +331,6 @@ void CtrlList::read(Xml& xml) case Xml::TagEnd: if (xml.s1() == "controller") { - // Added by Tim. p3.3.6 //printf("CtrlList::read _id:%d _curVal:%f\n", _id, _curVal); return; diff --git a/muse2/muse/ctrl/ctrlcanvas.cpp b/muse2/muse/ctrl/ctrlcanvas.cpp index f2f335cf..ceffee68 100644 --- a/muse2/muse/ctrl/ctrlcanvas.cpp +++ b/muse2/muse/ctrl/ctrlcanvas.cpp @@ -308,7 +308,9 @@ void CtrlCanvas::setPos(int idx, unsigned val, bool adjustScrollbar) void CtrlCanvas::setMidiController(int num) { _cnum = num; - partControllers(curPart, _cnum, &_dnum, &_didx, &_controller, &ctrl); + //if(curPart) + partControllers(curPart, _cnum, &_dnum, &_didx, &_controller, &ctrl); + if(_panel) { if(_cnum == CTRL_VELOCITY) @@ -474,6 +476,9 @@ void CtrlCanvas::songChanged(int type) //return; } + if(!curPart) // p4.0.27 + return; + if(type & (SC_CONFIG | SC_DRUMMAP | SC_PART_MODIFIED | SC_EVENT_INSERTED | SC_EVENT_REMOVED | SC_EVENT_MODIFIED)) // p4.0.18 updateItems(); else @@ -500,6 +505,19 @@ void CtrlCanvas::partControllers(const MidiPart* part, int num, int* dnum, int* } else { + if(!part) // p4.0.27 + { + if(mcvl) + *mcvl = 0; + if(mc) + *mc = 0; + if(dnum) + *dnum = 0; + if(didx) + *didx = 0; + return; + } + MidiTrack* mt = part->track(); MidiPort* mp; int di; @@ -667,9 +685,10 @@ void CtrlCanvas::updateItems() MidiPart* part = (MidiPart*)(p->second); EventList* el = part->events(); - MidiController* mc; + //MidiController* mc; MidiCtrlValList* mcvl; - partControllers(part, _cnum, 0, 0, &mc, &mcvl); + //partControllers(part, _cnum, 0, 0, &mc, &mcvl); + partControllers(part, _cnum, 0, 0, 0, &mcvl); unsigned len = part->lenTick(); for (iEvent i = el->begin(); i != el->end(); ++i) @@ -740,6 +759,9 @@ void CtrlCanvas::updateSelections() void CtrlCanvas::viewMousePressEvent(QMouseEvent* event) { + if(!_controller) // p4.0.27 + return; + start = event->pos(); Tool activeTool = tool; @@ -751,9 +773,9 @@ void CtrlCanvas::viewMousePressEvent(QMouseEvent* event) switch (activeTool) { case PointerTool: - drag = DRAG_LASSO_START; - + if(curPart) // p4.0.27 { + drag = DRAG_LASSO_START; bool do_redraw = false; if (!ctrlKey) { @@ -846,6 +868,9 @@ void CtrlCanvas::viewMousePressEvent(QMouseEvent* event) void CtrlCanvas::viewMouseMoveEvent(QMouseEvent* event) { + if(!_controller) // p4.0.27 + return; + QPoint pos = event->pos(); QPoint dist = pos - start; bool moving = dist.y() >= 3 || dist.y() <= 3 || dist.x() >= 3 || dist.x() <= 3; @@ -918,6 +943,7 @@ void CtrlCanvas::viewMouseReleaseEvent(QMouseEvent* event) lasso.setRect(-1, -1, -1, -1); case DRAG_LASSO: + if(_controller) // p4.0.27 { ///if (!ctrlKey) /// deselectAll(); @@ -967,6 +993,9 @@ void CtrlCanvas::viewMouseReleaseEvent(QMouseEvent* event) void CtrlCanvas::newValRamp(int x1, int y1, int x2, int y2) { + if(!curPart || !_controller) // p4.0.27 + return; + if(x2 - x1 < 0) { int a = x1; @@ -1088,6 +1117,9 @@ void CtrlCanvas::newValRamp(int x1, int y1, int x2, int y2) void CtrlCanvas::changeValRamp(int x1, int y1, int x2, int y2) { + if(!curPart || !_controller) // p4.0.27 + return; + int h = height(); bool changed = false; int type = _controller->num(); @@ -1178,6 +1210,9 @@ void CtrlCanvas::changeValRamp(int x1, int y1, int x2, int y2) void CtrlCanvas::changeVal(int x1, int x2, int y) { + if(!curPart || !_controller) // p4.0.27 + return; + bool changed = false; int newval = computeVal(_controller, y, height()); int type = _controller->num(); @@ -1409,6 +1444,9 @@ void CtrlCanvas::newVal(int x1, int x2, int y) void CtrlCanvas::newVal(int x1, int y) { + if(!curPart || !_controller) // p4.0.27 + return; + int xx1 = editor->rasterVal1(x1); int xx2 = editor->rasterVal2(x1); // If x1 happens to lie directly on a raster, xx1 will equal xx2, @@ -1620,6 +1658,9 @@ void CtrlCanvas::newVal(int x1, int y) void CtrlCanvas::newVal(int x1, int y1, int x2, int y2) { + if(!curPart || !_controller) // p4.0.27 + return; + if(x2 - x1 < 0) { int a = x1; @@ -1821,6 +1862,9 @@ void CtrlCanvas::newVal(int x1, int y1, int x2, int y2) void CtrlCanvas::deleteVal(int x1, int x2, int) { + if(!curPart) // p4.0.27 + return; + if(x2 - x1 < 0) { int a = x1; @@ -1971,6 +2015,9 @@ void CtrlCanvas::pdrawItems(QPainter& p, const QRect& rect, const MidiPart* part } else { + if(!part) // p4.0.27 + return; + MidiTrack* mt = part->track(); MidiPort* mp; @@ -2095,7 +2142,9 @@ void CtrlCanvas::pdrawItems(QPainter& p, const QRect& rect, const MidiPart* part void CtrlCanvas::pdraw(QPainter& p, const QRect& rect) { - + if(!_controller) // p4.0.27 + return; + int x = rect.x() - 1; // compensate for 3 pixel line width int y = rect.y(); int w = rect.width() + 2; diff --git a/muse2/muse/ctrl/ctrlpanel.cpp b/muse2/muse/ctrl/ctrlpanel.cpp index b23ce855..b70c4d65 100644 --- a/muse2/muse/ctrl/ctrlpanel.cpp +++ b/muse2/muse/ctrl/ctrlpanel.cpp @@ -946,7 +946,7 @@ void CtrlPanel::ctrlRightClicked(const QPoint& p, int /*id*/) // _knob->selectFaceColor(true); //if(_dnum == -1) // return; - if(!editor->curCanvasPart()) + if(!editor->curCanvasPart() || !_ctrl) return; int cdi = editor->curDrumInstrument(); diff --git a/muse2/muse/driver/jack.cpp b/muse2/muse/driver/jack.cpp index c4d7a8ca..4857ede5 100644 --- a/muse2/muse/driver/jack.cpp +++ b/muse2/muse/driver/jack.cpp @@ -75,7 +75,8 @@ inline bool checkJackClient(jack_client_t* _client) bool checkAudioDevice() { if (audioDevice == NULL) { - printf("Muse:checkAudioDevice: no audioDevice\n"); + if(debugMsg) + printf("Muse:checkAudioDevice: no audioDevice\n"); return false; } return true; diff --git a/muse2/muse/driver/jackmidi.cpp b/muse2/muse/driver/jackmidi.cpp index 1765fabb..e514af7a 100644 --- a/muse2/muse/driver/jackmidi.cpp +++ b/muse2/muse/driver/jackmidi.cpp @@ -1061,7 +1061,8 @@ void MidiJackDevice::eventReceived(jack_midi_event_t* ev) // For now, do not accept if the last byte is not EOX, meaning it's a chunk with more chunks to follow. if(*(((unsigned char*)ev->buffer) + ev->size - 1) != ME_SYSEX_END) { - printf("MidiJackDevice::eventReceived sysex chunks not supported!\n"); + if(debugMsg) + printf("MidiJackDevice::eventReceived sysex chunks not supported!\n"); return; } @@ -1092,15 +1093,17 @@ void MidiJackDevice::eventReceived(jack_midi_event_t* ev) //break; // return; default: - printf("MidiJackDevice::eventReceived unsupported system event 0x%02x\n", type); + if(debugMsg) + printf("MidiJackDevice::eventReceived unsupported system event 0x%02x\n", type); return; } } //return; break; default: - printf("MidiJackDevice::eventReceived unknown event 0x%02x\n", type); - //printf("MidiJackDevice::eventReceived unknown event 0x%02x size:%d buf:0x%02x 0x%02x 0x%02x ...0x%02x\n", type, ev->size, *(ev->buffer), *(ev->buffer + 1), *(ev->buffer + 2), *(ev->buffer + (ev->size - 1))); + if(debugMsg) + printf("MidiJackDevice::eventReceived unknown event 0x%02x\n", type); + //printf("MidiJackDevice::eventReceived unknown event 0x%02x size:%d buf:0x%02x 0x%02x 0x%02x ...0x%02x\n", type, ev->size, *(ev->buffer), *(ev->buffer + 1), *(ev->buffer + 2), *(ev->buffer + (ev->size - 1))); return; } diff --git a/muse2/muse/dssihost.cpp b/muse2/muse/dssihost.cpp index 2384ed02..fd33a135 100644 --- a/muse2/muse/dssihost.cpp +++ b/muse2/muse/dssihost.cpp @@ -24,8 +24,8 @@ // Turn on debugging messages //#define DSSI_DEBUG -// Support vst state saving/loading with vst chunks. Requires patches to DSSI and DSSI-vst! -//#define DSSI_VST_CHUNK_SUPPORT +// Support vst state saving/loading with vst chunks. +//#define DSSI_VST_CHUNK_SUPPORT #include <string.h> #include <signal.h> @@ -1350,6 +1350,13 @@ DssiSynthIF::~DssiSynthIF() delete[] controlsOut; } +int DssiSynthIF::oldMidiStateHeader(const unsigned char** data) const +{ + unsigned char const d[2] = {MUSE_SYNTH_SYSEX_MFG_ID, DSSI_SYNTH_UNIQUE_ID}; + *data = &d[0]; + return 2; +} + //--------------------------------------------------------- // getParameter //--------------------------------------------------------- @@ -1433,38 +1440,45 @@ void DssiSynthIF::write(int level, Xml& xml) const //bool vstsaved = false; #ifdef DSSI_VST_CHUNK_SUPPORT - //--------------------------------------------- - // dump current state of synth - //--------------------------------------------- - printf("dumping DSSI custom data! %d\n", synth->dssi->getCustomData); - - // this is only needed and supported if - // we are talking to a VST plugin at the other end. - std::string name = synth->dssi->LADSPA_Plugin->Name; - if ((name.length()> 4) && name.substr(name.length() - 4) == " VST") - { - printf("is vst plugin, commencing data dump, apiversion=%d!\n", synth->dssi->DSSI_API_Version); - unsigned long len = 0; - void* p = 0; - synth->dssi->getCustomData(handle,&p, &len); - if (len) { - xml.tag(level++, "midistate"); - xml.nput(level++, "<event type=\"%d\"", Sysex); - xml.nput(" datalen=\"%d\">\n", len+7 /*VSTSAVE*/); - xml.nput(level, ""); - xml.nput("56 53 54 53 41 56 45 "); // embed a save marker "string 'VSTSAVE' - for (long unsigned int i = 0; i < len; ++i) { - if (i && (((i+7) % 16) == 0)) { - xml.nput("\n"); - xml.nput(level, ""); - } - xml.nput("%02x ", ((char*)(p))[i] & 0xff); - } - xml.nput("\n"); - xml.tag(level--, "/event"); - xml.etag(level--, "midistate"); - //vstsaved = true; - } + if(synth->dssi->getCustomData) + { + //--------------------------------------------- + // dump current state of synth + //--------------------------------------------- + printf("dumping DSSI custom data! %p\n", synth->dssi->getCustomData); + + // this is only needed and supported if + // we are talking to a VST plugin at the other end. + std::string name = synth->dssi->LADSPA_Plugin->Name; + if ((name.length()> 4) && name.substr(name.length() - 4) == " VST") + { + printf("is vst plugin, commencing data dump, apiversion=%d!\n", synth->dssi->DSSI_API_Version); + unsigned long len = 0; + void* p = 0; + synth->dssi->getCustomData(handle,&p, &len); + if (len) { + //xml.tag(level++, "midistate"); + xml.tag(level++, "midistate version=\"%d\"", SYNTH_MIDI_STATE_SAVE_VERSION); // p4.0.27 + xml.nput(level++, "<event type=\"%d\"", Sysex); + //xml.nput(" datalen=\"%d\">\n", len+7 /*VSTSAVE*/); + xml.nput(" datalen=\"%d\">\n", len+9 /* 2 bytes header + "VSTSAVE" */); + xml.nput(level, ""); + xml.nput("%02x %02x ", (char)MUSE_SYNTH_SYSEX_MFG_ID, (char)DSSI_SYNTH_UNIQUE_ID); // p4.0.27 Wrap in a proper header + xml.nput("56 53 54 53 41 56 45 "); // embed a save marker "string 'VSTSAVE' + for (long unsigned int i = 0; i < len; ++i) { + //if (i && (((i+7) % 16) == 0)) { + if (i && (((i+9) % 16) == 0)) { + xml.nput("\n"); + xml.nput(level, ""); + } + xml.nput("%02x ", ((char*)(p))[i] & 0xff); + } + xml.nput("\n"); + xml.tag(level--, "/event"); + xml.etag(level--, "midistate"); + //vstsaved = true; + } + } } #else printf("support for vst chunks not compiled in!\n"); @@ -1922,88 +1936,110 @@ bool DssiSynthIF::processEvent(const MidiPlayEvent& e, snd_seq_event_t* event) event->queue = SND_SEQ_QUEUE_DIRECT; snd_seq_ev_set_chanpress(event, chn, a); break; - case ME_SYSEX: - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent midi event is ME_SYSEX\n"); - #endif - - if (QString((const char*)e.data()).startsWith("VSTSAVE")) { -#ifdef DSSI_VST_CHUNK_SUPPORT - printf("loading chunk from sysex %s!\n", e.data()+7); - dssi->setCustomData(handle, e.data()+7 /* len of str*/,e.len()-7); -#else - printf("support for vst chunks not compiled in!\n"); -#endif - // Event not filled. - return false; - } - /* - // p3.3.39 Read the state of current bank and program and all input control values. - // TODO: Needs to be better. See write(). - else - if (QString((const char*)e.data()).startsWith("PARAMSAVE")) + case ME_SYSEX: { #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::processEvent midi event is ME_SYSEX PARAMSAVE\n"); + fprintf(stderr, "DssiSynthIF::processEvent midi event is ME_SYSEX\n"); #endif - unsigned long dlen = e.len() - 9; // Minus "PARAMSAVE" - if(dlen > 0) + // Changed p4.0.27 + const unsigned char* data = e.data(); + if(e.len() >= 2) { - //if(dlen < 2 * sizeof(unsigned long)) - if(dlen < (2 + 2 * sizeof(unsigned long))) // Version major and minor bytes, bank and program. - printf("DssiSynthIF::processEvent Error: PARAMSAVE data length does not include at least version major and minor, bank and program!\n"); - else + if(data[0] == MUSE_SYNTH_SYSEX_MFG_ID) { - // Not required, yet. - //char vmaj = *((char*)(e.data() + 9)); // After "PARAMSAVE" - //char vmin = *((char*)(e.data() + 10)); - - unsigned long* const ulp = (unsigned long*)(e.data() + 11); // After "PARAMSAVE" + version major and minor. - // TODO: TODO: Set plugin bank and program. - _curBank = ulp[0]; - _curProgram = ulp[1]; - - dlen -= (2 + 2 * sizeof(unsigned long)); // After the version major and minor, bank and program. - - if(dlen > 0) + if(data[1] == DSSI_SYNTH_UNIQUE_ID) { - if((dlen % sizeof(float)) != 0) - printf("DssiSynthIF::processEvent Error: PARAMSAVE float data length not integral multiple of float size!\n"); - else + if(e.len() >= 9) { - const unsigned long n = dlen / sizeof(float); - if(n != synth->_controlInPorts) - printf("DssiSynthIF::processEvent Warning: PARAMSAVE number of floats:%lu != number of controls:%lu\n", n, synth->_controlInPorts); - - // Point to location after "PARAMSAVE", version major and minor, bank and progam. - float* const fp = (float*)(e.data() + 9 + 2 + 2 * sizeof(unsigned long)); - - for(unsigned long i = 0; i < synth->_controlInPorts && i < n; ++i) + //if (QString((const char*)e.data()).startsWith("VSTSAVE")) { + if (QString((const char*)(data + 2)).startsWith("VSTSAVE")) { +#ifdef DSSI_VST_CHUNK_SUPPORT + if(dssi->setCustomData) + { + //printf("loading chunk from sysex %s!\n", e.data()+7); + printf("loading chunk from sysex %s!\n", data+9); + //dssi->setCustomData(handle, e.data()+7 /* len of str*/,e.len()-7); + dssi->setCustomData(handle, (unsigned char*)(data+9) /* len of str*/,e.len()-9); + } +#else + printf("support for vst chunks not compiled in!\n"); +#endif + // Event not filled. + return false; + } + } + } + } + } + /* + // p3.3.39 Read the state of current bank and program and all input control values. + // TODO: Needs to be better. See write(). + //else + if (QString((const char*)e.data()).startsWith("PARAMSAVE")) + { + #ifdef DSSI_DEBUG + fprintf(stderr, "DssiSynthIF::processEvent midi event is ME_SYSEX PARAMSAVE\n"); + #endif + + unsigned long dlen = e.len() - 9; // Minus "PARAMSAVE" + if(dlen > 0) + { + //if(dlen < 2 * sizeof(unsigned long)) + if(dlen < (2 + 2 * sizeof(unsigned long))) // Version major and minor bytes, bank and program. + printf("DssiSynthIF::processEvent Error: PARAMSAVE data length does not include at least version major and minor, bank and program!\n"); + else + { + // Not required, yet. + //char vmaj = *((char*)(e.data() + 9)); // After "PARAMSAVE" + //char vmin = *((char*)(e.data() + 10)); + + unsigned long* const ulp = (unsigned long*)(e.data() + 11); // After "PARAMSAVE" + version major and minor. + // TODO: TODO: Set plugin bank and program. + _curBank = ulp[0]; + _curProgram = ulp[1]; + + dlen -= (2 + 2 * sizeof(unsigned long)); // After the version major and minor, bank and program. + + if(dlen > 0) + { + if((dlen % sizeof(float)) != 0) + printf("DssiSynthIF::processEvent Error: PARAMSAVE float data length not integral multiple of float size!\n"); + else { - const float v = fp[i]; - controls[i].val = v; + const unsigned long n = dlen / sizeof(float); + if(n != synth->_controlInPorts) + printf("DssiSynthIF::processEvent Warning: PARAMSAVE number of floats:%lu != number of controls:%lu\n", n, synth->_controlInPorts); + + // Point to location after "PARAMSAVE", version major and minor, bank and progam. + float* const fp = (float*)(e.data() + 9 + 2 + 2 * sizeof(unsigned long)); + + for(unsigned long i = 0; i < synth->_controlInPorts && i < n; ++i) + { + const float v = fp[i]; + controls[i].val = v; + } } - } + } } } - } - // Event not filled. - return false; - } - */ - else - { - // NOTE: There is a limit on the size of a sysex. Got this: - // "DssiSynthIF::processEvent midi event is ME_SYSEX" - // "WARNING: MIDI event of type ? decoded to 367 bytes, discarding" - // That might be ALSA doing that. - snd_seq_ev_clear(event); - event->queue = SND_SEQ_QUEUE_DIRECT; - snd_seq_ev_set_sysex(event, len, - //(unsigned char*)ba.data()); - (unsigned char*)ca); - } + // Event not filled. + return false; + } + */ + //else + { + // NOTE: There is a limit on the size of a sysex. Got this: + // "DssiSynthIF::processEvent midi event is ME_SYSEX" + // "WARNING: MIDI event of type ? decoded to 367 bytes, discarding" + // That might be ALSA doing that. + snd_seq_ev_clear(event); + event->queue = SND_SEQ_QUEUE_DIRECT; + snd_seq_ev_set_sysex(event, len, + //(unsigned char*)ba.data()); + (unsigned char*)ca); + } + } break; default: if(debugMsg) @@ -3251,7 +3287,7 @@ int DssiSynthIF::oscMidi(int a, int b, int c) MidiPlayEvent event(0, port, channel, a, b, c); #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::oscMidi midi event chn:%d a:%d b:%d\n", event.channel(), event.dataA(), event.dataB()); + printf(stderr, "DssiSynthIF::oscMidi midi event chn:%d a:%d b:%d\n", event.channel(), event.dataA(), event.dataB()); #endif midiPorts[port].sendEvent(event); diff --git a/muse2/muse/dssihost.h b/muse2/muse/dssihost.h index b917bbf6..d46cb570 100644 --- a/muse2/muse/dssihost.h +++ b/muse2/muse/dssihost.h @@ -27,6 +27,11 @@ #include <map> #include <string> +// Make sure this number is unique among all the MESS synths and DSSI host synth. +#define DSSI_SYNTH_UNIQUE_ID 8 +// Midistate sysex initialization command. +#define DSSI_INIT_DATA_CMD 1 + #ifdef OSC_SUPPORT #include <lo/lo.h> #include "osc.h" @@ -150,11 +155,14 @@ class DssiSynthIF : public SynthIF, public PluginIBase protected: //int guiPid; //QProcess* guiQProc; - + public: DssiSynthIF(SynthI* s); //DssiSynthIF(); + // This is only a kludge required to support old songs' midistates. Do not use in any new synth. + virtual int oldMidiStateHeader(const unsigned char** data) const; + virtual ~DssiSynthIF(); virtual DssiSynth* dssiSynth() { return synth; } diff --git a/muse2/muse/evdata.h b/muse2/muse/evdata.h index 59155d48..b8c2bde4 100644 --- a/muse2/muse/evdata.h +++ b/muse2/muse/evdata.h @@ -57,6 +57,8 @@ class EvData { } } void setData(const unsigned char* p, int l) { + if(data) + delete[] data; // p4.0.27 data = new unsigned char[l]; memcpy(data, p, l); dataLen = l; diff --git a/muse2/muse/instruments/minstrument.cpp b/muse2/muse/instruments/minstrument.cpp index 10cb3ec2..613e5bdf 100644 --- a/muse2/muse/instruments/minstrument.cpp +++ b/muse2/muse/instruments/minstrument.cpp @@ -333,6 +333,7 @@ void removeMidiInstrument(const MidiInstrument* instr) void MidiInstrument::init() { + _tmpMidiStateVersion = 1; // Assume old version. readMidiState will overwrite anyway. _nullvalue = -1; _initScript = 0; _midiInit = new EventList(); @@ -675,9 +676,44 @@ void Patch::write(int level, Xml& xml) //--------------------------------------------------------- void MidiInstrument::readMidiState(Xml& xml) - { - _midiState->read(xml, "midistate", true); - } +{ + ///_midiState->read(xml, "midistate", true); + + // p4.0.27 A kludge to support old midistates by wrapping them in the proper header. + _tmpMidiStateVersion = 1; // Assume old (unmarked) first version 1. + for (;;) + { + Xml::Token token = xml.parse(); + const QString tag = xml.s1(); + switch (token) + { + case Xml::Error: + case Xml::End: + return; + case Xml::TagStart: + if (tag == "event") + { + Event e(Note); + e.read(xml); + _midiState->add(e); + } + else + xml.unknown("midistate"); + break; + case Xml::Attribut: + if(tag == "version") + _tmpMidiStateVersion = xml.s2().toInt(); + else + xml.unknown("MidiInstrument"); + break; + case Xml::TagEnd: + if(tag == "midistate") + return; + default: + break; + } + } +} //--------------------------------------------------------- // read diff --git a/muse2/muse/instruments/minstrument.h b/muse2/muse/instruments/minstrument.h index 15942537..dacd17fc 100644 --- a/muse2/muse/instruments/minstrument.h +++ b/muse2/muse/instruments/minstrument.h @@ -77,6 +77,9 @@ class MidiInstrument { EventList* _midiInit; EventList* _midiReset; EventList* _midiState; + // Set when loading midi state in SynthI::read, to indicate version + // to SynthI::initInstance, which is called later. + int _tmpMidiStateVersion; char* _initScript; QString _name; QString _filePath; diff --git a/muse2/muse/midi.cpp b/muse2/muse/midi.cpp index 39ae7874..6abcaa81 100644 --- a/muse2/muse/midi.cpp +++ b/muse2/muse/midi.cpp @@ -150,7 +150,8 @@ QString nameSysex(unsigned int len, const unsigned char* buf) case 0x43: s = "Yamaha: "; break; case 0x44: s = "Casio"; break; case 0x45: s = "Akai"; break; - case 0x7c: s = "MusE Soft Synth"; break; + //case 0x7c: s = "MusE Soft Synth"; break; + case MUSE_SYNTH_SYSEX_MFG_ID: s = "MusE Soft Synth"; break; // p4.0.27 case 0x7d: s = "Educational Use"; break; case 0x7e: s = "Universal: Non Real Time"; break; case 0x7f: s = "Universal: Real Time"; break; diff --git a/muse2/muse/midi.h b/muse2/muse/midi.h index ab649377..8250a0e3 100644 --- a/muse2/muse/midi.h +++ b/muse2/muse/midi.h @@ -62,6 +62,12 @@ extern const unsigned int mmcLocateMsgLen; QString nameSysex(unsigned int len, const unsigned char* buf); QString midiMetaName(int); +// Use these in all the synths and their guis. +// Did this here for ease, since they all include this file. +// +// A special MusE soft synth sysex manufacturer ID. +#define MUSE_SYNTH_SYSEX_MFG_ID 0x7c + class EventList; class MPEventList; class MidiTrack; diff --git a/muse2/muse/midiport.cpp b/muse2/muse/midiport.cpp index 7c4f73fb..553c8e31 100644 --- a/muse2/muse/midiport.cpp +++ b/muse2/muse/midiport.cpp @@ -334,6 +334,56 @@ const QString& MidiPort::portname() const void MidiPort::tryCtrlInitVal(int chan, int ctl, int val) { + // p4.0.27 + // Look for an initial value in the song for this midi controller, on this midi channel... + //for(iMidiCtrlValList i = _controller->begin(); i != _controller->end(); ++i) + iMidiCtrlValList i = _controller->find(chan, ctl); + if(i != _controller->end()) + { + //int channel = i->first >> 24; + //int cntrl = i->first & 0xffffff; + //if(channel == chan && cntrl == ctl) + int v = i->second->value(0); // Value at tick 0. + if(v != CTRL_VAL_UNKNOWN) + { + if(_device) + { + ///#ifdef DSSI_SUPPORT + + // Not for dssi synths... + ///if(!_device->isSynti() || (dynamic_cast<DssiSynthIF*>(((SynthI*)_device)->sif()) == 0)) + ///{ + + ///#endif + + //_device->putEvent(MidiPlayEvent(0, portno(), channel, + // ME_CONTROLLER, cntrl, v)); + // Retry added. Use default attempts and delay. p4.0.15 + _device->putEventWithRetry(MidiPlayEvent(0, portno(), chan, + ME_CONTROLLER, ctl, v)); + //if(_device->putEventWithRetry(MidiPlayEvent(0, portno(), chan, + // ME_CONTROLLER, ctl, v))) + // return; + + ///#ifdef DSSI_SUPPORT + + ///} + + ///#endif + + } + + // Set it once so the 'last HW value' is set, and control knobs are positioned at the value... + setHwCtrlState(chan, ctl, v); + // Set it again so that control labels show 'off'... + //setHwCtrlState(chan, ctl, CTRL_VAL_UNKNOWN); + //setHwCtrlStates(chan, ctl, CTRL_VAL_UNKNOWN, v); + + return; + } + } + + // No initial value was found in the song for this midi controller on this midi channel. Try the instrument... if(_instrument) { MidiControllerList* cl = _instrument->controller(); @@ -370,6 +420,7 @@ void MidiPort::tryCtrlInitVal(int chan, int ctl, int val) } } + // No initial value was found in the song or instrument for this midi controller. Just send the given value. if(_device) { //MidiPlayEvent ev(song->cpos(), portno(), chan, ME_CONTROLLER, ctl, val); @@ -749,8 +800,8 @@ bool MidiPort::sendEvent(const MidiPlayEvent& ev, bool forceSend) // } // printf("set HW Ctrl State ch:%d 0x%x 0x%x\n", ev.channel(), ev.dataA(), ev.dataB()); if(!setHwCtrlState(ev.channel(), da, db)) { - if (debugMsg) - printf("setHwCtrlState failed\n"); + if (debugMsg && forceSend) + printf("sendEvent: State already set. Forcing anyway...\n"); if (!forceSend) return false; } diff --git a/muse2/muse/node.cpp b/muse2/muse/node.cpp index 06dbbc8d..da3874f0 100644 --- a/muse2/muse/node.cpp +++ b/muse2/muse/node.cpp @@ -1889,35 +1889,43 @@ void AudioTrack::setChannels(int n) void AudioTrack::setTotalOutChannels(int num) { - if(num == _totalOutChannels) - return; - + //if(num == _totalOutChannels) + // return; + // p4.0.27 Fixes crash if file loaded with track channels less than synth channels. int chans = _totalOutChannels; - // Number of allocated buffers is always MAX_CHANNELS or more, even if _totalOutChannels is less. - if(chans < MAX_CHANNELS) - chans = MAX_CHANNELS; - for(int i = 0; i < chans; ++i) + if(num != chans) { - if(outBuffers[i]) - free(outBuffers[i]); - } - delete[] outBuffers; - _totalOutChannels = num; - chans = num; - // Number of allocated buffers is always MAX_CHANNELS or more, even if _totalOutChannels is less. - if(chans < MAX_CHANNELS) - chans = MAX_CHANNELS; + //int chans = _totalOutChannels; + // Number of allocated buffers is always MAX_CHANNELS or more, even if _totalOutChannels is less. + if(chans < MAX_CHANNELS) + chans = MAX_CHANNELS; + for(int i = 0; i < chans; ++i) + { + if(outBuffers[i]) + free(outBuffers[i]); + } + delete[] outBuffers; - outBuffers = new float*[chans]; - for (int i = 0; i < chans; ++i) - posix_memalign((void**)&outBuffers[i], 16, sizeof(float) * segmentSize); - + _totalOutChannels = num; + chans = num; + // Number of allocated buffers is always MAX_CHANNELS or more, even if _totalOutChannels is less. + if(chans < MAX_CHANNELS) + chans = MAX_CHANNELS; + + outBuffers = new float*[chans]; + for (int i = 0; i < chans; ++i) + posix_memalign((void**)&outBuffers[i], 16, sizeof(float) * segmentSize); + + //chans = num; + // Limit the actual track (meters, copying etc, all 'normal' operation) to two-channel stereo. + //if(chans > MAX_CHANNELS) + // chans = MAX_CHANNELS; + } chans = num; // Limit the actual track (meters, copying etc, all 'normal' operation) to two-channel stereo. if(chans > MAX_CHANNELS) chans = MAX_CHANNELS; - setChannels(chans); } diff --git a/muse2/muse/synth.cpp b/muse2/muse/synth.cpp index 4f43a02a..f8946a9f 100644 --- a/muse2/muse/synth.cpp +++ b/muse2/muse/synth.cpp @@ -36,6 +36,7 @@ #include "midictrl.h" //#include "stringparam.h" #include "popupmenu.h" +#include "globaldefs.h" std::vector<Synth*> synthis; // array of available synthis @@ -429,10 +430,34 @@ bool SynthI::initInstance(Synth* s, const QString& instanceName) cl->add(c); } + // Restore the midi state... EventList* iel = midiState(); if (!iel->empty()) { for (iEvent i = iel->begin(); i != iel->end(); ++i) { Event ev = i->second; + + // p4.0.27 A kludge to support old midistates by wrapping them in the proper header. + if(ev.type() == Sysex && _tmpMidiStateVersion < SYNTH_MIDI_STATE_SAVE_VERSION) + { + int len = ev.dataLen(); + if(len > 0) + { + const unsigned char* data = ev.data(); + const unsigned char* hdr; + // Get the unique header for the synth. + int hdrsz = _sif->oldMidiStateHeader(&hdr); + if(hdrsz > 0) + { + int newlen = hdrsz + len; + unsigned char* d = new unsigned char[newlen]; + memcpy(d, hdr, hdrsz); + memcpy(d + hdrsz, data, len); + ev.setData(d, newlen); + delete[] d; + } + } + } + MidiPlayEvent pev(0, 0, 0, ev); if (_sif->putEvent(pev)) break; // try later @@ -702,7 +727,8 @@ void MessSynthIF::write(int level, Xml& xml) const const unsigned char* p; _mess->getInitData(&len, &p); if (len) { - xml.tag(level++, "midistate"); + ///xml.tag(level++, "midistate"); + xml.tag(level++, "midistate version=\"%d\"", SYNTH_MIDI_STATE_SAVE_VERSION); xml.nput(level++, "<event type=\"%d\"", Sysex); xml.nput(" datalen=\"%d\">\n", len); xml.nput(level, ""); @@ -816,6 +842,7 @@ void SynthI::read(Xml& xml) if (initInstance(s, name())) return; song->insertTrack0(this, -1); + if (port != -1 && port < MIDI_PORTS) midiPorts[port].setMidiDevice(this); @@ -1033,3 +1060,18 @@ bool MessSynthIF::putEvent(const MidiPlayEvent& ev) return true; } +//unsigned long MessSynthIF::uniqueID() const +//{ +// return _mess ? _mess->uniqueID() : 0; +//} + +//MidiPlayEvent& MessSynthIF::wrapOldMidiStateVersion(MidiPlayEvent& e) const +//{ +// return _mess ? _mess->wrapOldMidiStateVersion(e) : e; +//} + +int MessSynthIF::oldMidiStateHeader(const unsigned char** data) const +{ + return _mess ? _mess->oldMidiStateHeader(data) : 0; +} + diff --git a/muse2/muse/synth.h b/muse2/muse/synth.h index 88fa70b8..0c48a231 100644 --- a/muse2/muse/synth.h +++ b/muse2/muse/synth.h @@ -22,6 +22,9 @@ #include <QFileInfo> +// Current version of saved midistate data. +#define SYNTH_MIDI_STATE_SAVE_VERSION 2 + //class QMenu; class PopupMenu; @@ -105,17 +108,25 @@ class Mess; //--------------------------------------------------------- // SynthIF // synth instance interface +// NOTICE: If implementing sysex support, be sure to make a unique ID and use +// it to filter out unrecognized sysexes. Headers should be constructed as: +// MUSE_SYNTH_SYSEX_MFG_ID The MusE SoftSynth Manufacturer ID byte (0x7C) found in midi.h +// 0xNN The synth's unique ID byte //--------------------------------------------------------- class SynthIF { + protected: SynthI* synti; - + public: //SynthIF() {} SynthIF(SynthI* s) { synti = s; } virtual ~SynthIF() {} + // This is only a kludge required to support old songs' midistates. Do not use in any new synth. + virtual int oldMidiStateHeader(const unsigned char** /*data*/) const { return 0; } + virtual bool initGui() = 0; virtual void guiHeartBeat() = 0; virtual bool guiVisible() const = 0; @@ -280,6 +291,10 @@ class SynthI : public AudioTrack, public MidiDevice, //--------------------------------------------------------- // MessSynthIF // mess synthesizer instance +// NOTICE: If implementing sysex support, be sure to make a unique ID and use +// it to filter out unrecognized sysexes. Headers should be constructed as: +// MUSE_SYNTH_SYSEX_MFG_ID The MusE SoftSynth Manufacturer ID byte (0x7C) found in midi.h +// 0xNN The synth's unique ID byte //--------------------------------------------------------- class MessSynthIF : public SynthIF { @@ -290,6 +305,9 @@ class MessSynthIF : public SynthIF { MessSynthIF(SynthI* s) : SynthIF(s) { _mess = 0; } virtual ~MessSynthIF() { } + // This is only a kludge required to support old songs' midistates. Do not use in any new synth. + virtual int oldMidiStateHeader(const unsigned char** data) const; + virtual bool initGui() { return true; } virtual void guiHeartBeat() { } virtual bool guiVisible() const { return false; } diff --git a/muse2/muse/ticksynth.cpp b/muse2/muse/ticksynth.cpp index 7456b856..90e01417 100644 --- a/muse2/muse/ticksynth.cpp +++ b/muse2/muse/ticksynth.cpp @@ -12,7 +12,9 @@ //#include <QMenu> #include "popupmenu.h" -// Added by Tim. p3.3.18 +// If sysex support is ever added, make sure this number is unique among all the MESS synths. +//#define METRONOME_UNIQUE_ID 7 + //#define METRONOME_DEBUG MetronomeSynthI* metronome = 0; diff --git a/muse2/muse/widgets/mtrackinfo.cpp b/muse2/muse/widgets/mtrackinfo.cpp index 6dd02931..c5cdac0b 100644 --- a/muse2/muse/widgets/mtrackinfo.cpp +++ b/muse2/muse/widgets/mtrackinfo.cpp @@ -65,6 +65,7 @@ MidiTrackInfo::MidiTrackInfo(QWidget* parent, Track* sel_track) : QWidget(parent { setupUi(this); _midiDetect = false; + heartBeatCounter = 0; selected = sel_track; @@ -327,54 +328,72 @@ void MidiTrackInfo::heartBeat() } } else - if(program != nprogram) { - program = nprogram; - - //int hb, lb, pr; - //if (program == CTRL_VAL_UNKNOWN) { - // hb = lb = pr = 0; - // iPatch->setText("---"); - // } - //else - //{ - MidiInstrument* instr = mp->instrument(); - QString name = instr->getPatchName(outChannel, program, song->mtype(), track->type() == Track::DRUM); - if(iPatch->text() != name) - iPatch->setText(name); - - int hb = ((program >> 16) & 0xff) + 1; - if (hb == 0x100) - hb = 0; - int lb = ((program >> 8) & 0xff) + 1; - if (lb == 0x100) - lb = 0; - int pr = (program & 0xff) + 1; - if (pr == 0x100) - pr = 0; - //} - - //printf("Arranger::midiTrackInfoHeartBeat setting program\n"); - - if(iHBank->value() != hb) - { - iHBank->blockSignals(true); - iHBank->setValue(hb); - iHBank->blockSignals(false); - } - if(iLBank->value() != lb) - { - iLBank->blockSignals(true); - iLBank->setValue(lb); - iLBank->blockSignals(false); - } - if(iProgram->value() != pr) - { - iProgram->blockSignals(true); - iProgram->setValue(pr); - iProgram->blockSignals(false); - } + // p4.0.27 The optimizing below, to avoid repeatedly calling getPatchName, generally worked OK. + // But Fluidsynth revealed a flaw. When loading a song, updateTrackInfo is called which correctly + // sets program = nprogram. But a synth will not receive midistate sysexes until later. + // With Fluidsynth, that messed up our optimizing because the soundfont has not loaded yet. + // fluid_synth_get_channel_preset returns 0 in FluidSynth::getPatchName which returns <unknown> + // when asked by updateTrackInfo, which then sets the patch box text to <unknown>. Then nothing + // happens here because program = nprogram. + // I don't like the idea of calling getPatchName here at a high rate. + // So force an update of program at a slower rate here. + // + // The alternative is to have a system where the synth can signal the host when a change has happened. + // Or an 'isValidPatch' function, or make getPatchName (and several others) return 0, so that updateTrackInfo + // can ignore it. Oops. No! Even if we make updateTrackInfo ignore it, then the same thing happens here. + // Thats is, program = nprogram but the text is still wrong. Not much choice but to do this for now... + if(++heartBeatCounter >= 20) + heartBeatCounter = 0; + if(program != nprogram || heartBeatCounter == 0) + { + program = nprogram; + + //int hb, lb, pr; + //if (program == CTRL_VAL_UNKNOWN) { + // hb = lb = pr = 0; + // iPatch->setText("---"); + // } + //else + //{ + MidiInstrument* instr = mp->instrument(); + QString name = instr->getPatchName(outChannel, program, song->mtype(), track->type() == Track::DRUM); + if(iPatch->text() != name) + iPatch->setText(name); + + int hb = ((program >> 16) & 0xff) + 1; + if (hb == 0x100) + hb = 0; + int lb = ((program >> 8) & 0xff) + 1; + if (lb == 0x100) + lb = 0; + int pr = (program & 0xff) + 1; + if (pr == 0x100) + pr = 0; + //} + + //printf("Arranger::midiTrackInfoHeartBeat setting program\n"); + if(iHBank->value() != hb) + { + iHBank->blockSignals(true); + iHBank->setValue(hb); + iHBank->blockSignals(false); + } + if(iLBank->value() != lb) + { + iLBank->blockSignals(true); + iLBank->setValue(lb); + iLBank->blockSignals(false); + } + if(iProgram->value() != pr) + { + iProgram->blockSignals(true); + iProgram->setValue(pr); + iProgram->blockSignals(false); + } + + } } MidiController* mc = mp->midiController(CTRL_VOLUME); diff --git a/muse2/muse/widgets/mtrackinfo.h b/muse2/muse/widgets/mtrackinfo.h index ed229ad6..20fd3a69 100644 --- a/muse2/muse/widgets/mtrackinfo.h +++ b/muse2/muse/widgets/mtrackinfo.h @@ -21,6 +21,7 @@ class MidiTrackInfo : public QWidget, public Ui::MidiTrackInfoBase Track* selected; bool _midiDetect; int program, pan, volume; + int heartBeatCounter; private slots: void iOutputChannelChanged(int); diff --git a/muse2/muse/widgets/routepopup.cpp b/muse2/muse/widgets/routepopup.cpp index 910d693d..0afbbdb6 100644 --- a/muse2/muse/widgets/routepopup.cpp +++ b/muse2/muse/widgets/routepopup.cpp @@ -848,7 +848,7 @@ void RoutePopupMenu::popupActivated(QAction* action) //if(!(md->rwFlags() & 2)) //if(!(md->rwFlags() & (gIsOutRoutingPopupMenu ? 1 : 2))) if(md && !(md->rwFlags() & (_isOutMenu ? 1 : 2))) - return; + return; int chmask = 0; ciRoute iir = rl->begin(); @@ -1058,7 +1058,9 @@ void RoutePopupMenu::prepare() for( ; pi < MIDI_PORTS; ++pi) { MidiDevice* md = midiPorts[pi].device(); - if(md && !md->isSynti() && (md->rwFlags() & 2)) + //if(md && !md->isSynti() && (md->rwFlags() & 2)) + //if(md && (md->rwFlags() & 2)) // p4.0.27 + if(md && (md->rwFlags() & 2 || md->isSynti()) ) // p4.0.27 break; } if(pi == MIDI_PORTS) @@ -1085,10 +1087,12 @@ void RoutePopupMenu::prepare() // continue; // Do not list synth devices! - if(md && md->isSynti()) - continue; - - if(md && !(md->rwFlags() & 2)) + ///if(md && md->isSynti()) + /// continue; + ///if(md && !(md->rwFlags() & 2)) + /// continue; + // p4.0.27 Go ahead. Synths esp MESS send out stuff. + if( md && !(md->rwFlags() & 2) && !md->isSynti() ) continue; //printf("MusE::prepareRoutingPopupMenu adding submenu portnum:%d\n", i); diff --git a/muse2/synti/deicsonze/common_defs.h b/muse2/synti/deicsonze/common_defs.h new file mode 100644 index 00000000..3c433e2a --- /dev/null +++ b/muse2/synti/deicsonze/common_defs.h @@ -0,0 +1,10 @@ +#ifndef __DEICSONZE_UNIQUE_ID_H +#define __DEICSONZE_UNIQUE_ID_H + +// Make sure this number is unique among all the MESS synths. +#define DEICSONZE_UNIQUE_ID 5 + +//#define DEICSONZE_DEBUG + +#endif + diff --git a/muse2/synti/deicsonze/deicsonze.cpp b/muse2/synti/deicsonze/deicsonze.cpp index 1da9fbc4..b723e925 100644 --- a/muse2/synti/deicsonze/deicsonze.cpp +++ b/muse2/synti/deicsonze/deicsonze.cpp @@ -37,6 +37,7 @@ #include "muse/midi.h" #include "libsynti/mess.h" +//#include "common_defs.h" #include "deicsonze.h" #include "plugin.h" @@ -91,6 +92,9 @@ DeicsOnze::DeicsOnze() : Mess(2) { waveTable[W8][i] = (float)(i<RESOLUTION/2?sin(t)*sin(t):0.0);} } + initBuffer = 0; + initLen = 0; + //alloc temp buffers chorus and reverb tempInputChorus = (float**) malloc(sizeof(float*)*NBRFXINPUTS); for(int i = 0; i < NBRFXINPUTS; i++) @@ -236,6 +240,9 @@ DeicsOnze::DeicsOnze() : Mess(2) { DeicsOnze::~DeicsOnze() { + if(_gui) + delete _gui; // p4.0.27 + //if (--useCount == 0) //delete[] sine_table; //dealloc temp buffers chorus and reverb @@ -251,8 +258,18 @@ DeicsOnze::~DeicsOnze() free(tempInputDelay); for(int i = 0; i < NBRFXOUTPUTS; i++) free(tempOutputDelay[i]); free(tempOutputDelay); + + if (initBuffer) + delete [] initBuffer; } +int DeicsOnze::oldMidiStateHeader(const unsigned char** data) const +{ + unsigned char const d[2] = {MUSE_SYNTH_SYSEX_MFG_ID, DEICSONZE_UNIQUE_ID}; + *data = &d[0]; + return 2; +} + //--------------------------------------------------------- // getSinusWaveTable //--------------------------------------------------------- @@ -2266,9 +2283,23 @@ void DeicsOnze::writeConfiguration(AL::Xml* xml) { } //--------------------------------------------------------- +// getInitBuffer +//--------------------------------------------------------- +void DeicsOnze::setupInitBuffer(int len) +{ + if (len > initLen) { + if (initBuffer) + delete [] initBuffer; + initBuffer = new unsigned char[len]; + initLen = len; + } +} + +//--------------------------------------------------------- // getInitData //--------------------------------------------------------- -void DeicsOnze::getInitData(int* length, const unsigned char** data) const { +//void DeicsOnze::getInitData(int* length, const unsigned char** data) const { +void DeicsOnze::getInitData(int* length, const unsigned char** data) { //write the set in a temporary file and in a QByteArray QTemporaryFile file; file.open(); @@ -2284,141 +2315,150 @@ void DeicsOnze::getInitData(int* length, const unsigned char** data) const { //save the set *length = NUM_CONFIGLENGTH + //*length = 2 + NUM_CONFIGLENGTH // 2 for Header ///+ (_pluginIReverb?sizeof(float)*_pluginIReverb->plugin()->parameter():0) + (_pluginIReverb?sizeof(float)*_pluginIReverb->plugin()->controlInPorts():0) ///+ (_pluginIChorus?sizeof(float)*_pluginIChorus->plugin()->parameter():0) + (_pluginIChorus?sizeof(float)*_pluginIChorus->plugin()->controlInPorts():0) + baComp.size(); - unsigned char* buffer = new unsigned char[*length]; + ///unsigned char* buffer = new unsigned char[*length]; + setupInitBuffer(*length); + //save init data - buffer[0]=SYSEX_INIT_DATA; - buffer[1]=SYSEX_INIT_DATA_VERSION; + + ///buffer[0]=SYSEX_INIT_DATA; + initBuffer[0]=MUSE_SYNTH_SYSEX_MFG_ID; + initBuffer[1]=DEICSONZE_UNIQUE_ID; + initBuffer[2]=SYSEX_INIT_DATA; + initBuffer[3]=SYSEX_INIT_DATA_VERSION; //save global data - buffer[NUM_MASTERVOL] = (unsigned char) getMasterVol(); + initBuffer[NUM_MASTERVOL] = (unsigned char) getMasterVol(); for(int c = 0; c < NBRCHANNELS; c++) { - buffer[NUM_CHANNEL_ENABLE + c] = (unsigned char) getChannelEnable(c); - buffer[NUM_CHANNEL_VOL + c] = (unsigned char) getChannelVol(c); - buffer[NUM_CHANNEL_PAN + c] = (unsigned char) getChannelPan(c); + initBuffer[NUM_CHANNEL_ENABLE + c] = (unsigned char) getChannelEnable(c); + initBuffer[NUM_CHANNEL_VOL + c] = (unsigned char) getChannelVol(c); + initBuffer[NUM_CHANNEL_PAN + c] = (unsigned char) getChannelPan(c); int b = getChannelBrightness(c); - buffer[NUM_CHANNEL_BRIGHTNESS + 2*c] = (unsigned char) (b%256); - buffer[NUM_CHANNEL_BRIGHTNESS + 2*c + 1] = (unsigned char) (b/256); - buffer[NUM_CHANNEL_MODULATION + c] = + initBuffer[NUM_CHANNEL_BRIGHTNESS + 2*c] = (unsigned char) (b%256); + initBuffer[NUM_CHANNEL_BRIGHTNESS + 2*c + 1] = (unsigned char) (b/256); + initBuffer[NUM_CHANNEL_MODULATION + c] = (unsigned char) getChannelModulation(c); - buffer[NUM_CHANNEL_DETUNE + c] = + initBuffer[NUM_CHANNEL_DETUNE + c] = (unsigned char) getChannelDetune(c) + MAXCHANNELDETUNE; - buffer[NUM_CHANNEL_ATTACK + c] = (unsigned char) getChannelAttack(c); - buffer[NUM_CHANNEL_RELEASE + c] = (unsigned char) getChannelRelease(c); - buffer[NUM_CHANNEL_REVERB + c] = (unsigned char) getChannelReverb(c); - buffer[NUM_CHANNEL_CHORUS + c] = (unsigned char) getChannelChorus(c); - buffer[NUM_CHANNEL_DELAY + c] = (unsigned char) getChannelDelay(c); - buffer[NUM_CURRENTPROG + c] = (unsigned char) _preset[c]->prog; - buffer[NUM_CURRENTLBANK + c] = + initBuffer[NUM_CHANNEL_ATTACK + c] = (unsigned char) getChannelAttack(c); + initBuffer[NUM_CHANNEL_RELEASE + c] = (unsigned char) getChannelRelease(c); + initBuffer[NUM_CHANNEL_REVERB + c] = (unsigned char) getChannelReverb(c); + initBuffer[NUM_CHANNEL_CHORUS + c] = (unsigned char) getChannelChorus(c); + initBuffer[NUM_CHANNEL_DELAY + c] = (unsigned char) getChannelDelay(c); + initBuffer[NUM_CURRENTPROG + c] = (unsigned char) _preset[c]->prog; + initBuffer[NUM_CURRENTLBANK + c] = (unsigned char) _preset[c]->_subcategory->_lbank; - buffer[NUM_CURRENTHBANK + c] = + initBuffer[NUM_CURRENTHBANK + c] = (unsigned char) _preset[c]->_subcategory->_category->_hbank; - buffer[NUM_NBRVOICES + c] = (unsigned char) getNbrVoices(c); + initBuffer[NUM_NBRVOICES + c] = (unsigned char) getNbrVoices(c); } - buffer[NUM_SAVEONLYUSED]=(unsigned char) _saveOnlyUsed; - buffer[NUM_SAVECONFIG]=(unsigned char) _saveConfig; + initBuffer[NUM_SAVEONLYUSED]=(unsigned char) _saveOnlyUsed; + initBuffer[NUM_SAVECONFIG]=(unsigned char) _saveConfig; //save config data if(_saveConfig) { - buffer[NUM_QUALITY]=(unsigned char)_global.quality; - buffer[NUM_FILTER]=(unsigned char)getFilter(); - buffer[NUM_FONTSIZE]=(unsigned char)_global.fontSize; - buffer[NUM_RED_TEXT]=(unsigned char)_gui->tColor->red(); - buffer[NUM_GREEN_TEXT]=(unsigned char)_gui->tColor->green(); - buffer[NUM_BLUE_TEXT]=(unsigned char)_gui->tColor->blue(); - buffer[NUM_RED_BACKGROUND]=(unsigned char)_gui->bColor->red(); - buffer[NUM_GREEN_BACKGROUND]=(unsigned char)_gui->bColor->green(); - buffer[NUM_BLUE_BACKGROUND]=(unsigned char)_gui->bColor->blue(); - buffer[NUM_RED_EDITTEXT]=(unsigned char)_gui->etColor->red(); - buffer[NUM_GREEN_EDITTEXT]=(unsigned char)_gui->etColor->green(); - buffer[NUM_BLUE_EDITTEXT]=(unsigned char)_gui->etColor->blue(); - buffer[NUM_RED_EDITBACKGROUND]=(unsigned char)_gui->ebColor->red(); - buffer[NUM_GREEN_EDITBACKGROUND]=(unsigned char)_gui->ebColor->green(); - buffer[NUM_BLUE_EDITBACKGROUND]=(unsigned char)_gui->ebColor->blue(); - buffer[NUM_ISINITSET]=(unsigned char)_isInitSet; - strncpy((char*)&buffer[NUM_INITSETPATH], + initBuffer[NUM_QUALITY]=(unsigned char)_global.quality; + initBuffer[NUM_FILTER]=(unsigned char)getFilter(); + initBuffer[NUM_FONTSIZE]=(unsigned char)_global.fontSize; + initBuffer[NUM_RED_TEXT]=(unsigned char)_gui->tColor->red(); + initBuffer[NUM_GREEN_TEXT]=(unsigned char)_gui->tColor->green(); + initBuffer[NUM_BLUE_TEXT]=(unsigned char)_gui->tColor->blue(); + initBuffer[NUM_RED_BACKGROUND]=(unsigned char)_gui->bColor->red(); + initBuffer[NUM_GREEN_BACKGROUND]=(unsigned char)_gui->bColor->green(); + initBuffer[NUM_BLUE_BACKGROUND]=(unsigned char)_gui->bColor->blue(); + initBuffer[NUM_RED_EDITTEXT]=(unsigned char)_gui->etColor->red(); + initBuffer[NUM_GREEN_EDITTEXT]=(unsigned char)_gui->etColor->green(); + initBuffer[NUM_BLUE_EDITTEXT]=(unsigned char)_gui->etColor->blue(); + initBuffer[NUM_RED_EDITBACKGROUND]=(unsigned char)_gui->ebColor->red(); + initBuffer[NUM_GREEN_EDITBACKGROUND]=(unsigned char)_gui->ebColor->green(); + initBuffer[NUM_BLUE_EDITBACKGROUND]=(unsigned char)_gui->ebColor->blue(); + initBuffer[NUM_ISINITSET]=(unsigned char)_isInitSet; + strncpy((char*)&initBuffer[NUM_INITSETPATH], _initSetPath.toLatin1().constData(), MAXSTRLENGTHINITSETPATH); - buffer[NUM_ISBACKGROUNDPIX]=(unsigned char)_isBackgroundPix; - strncpy((char*)&buffer[NUM_BACKGROUNDPIXPATH], + initBuffer[NUM_ISBACKGROUNDPIX]=(unsigned char)_isBackgroundPix; + strncpy((char*)&initBuffer[NUM_BACKGROUNDPIXPATH], _backgroundPixPath.toLatin1().constData(), MAXSTRLENGTHBACKGROUNDPIXPATH); } //FX //reverb - buffer[NUM_IS_REVERB_ON]=(unsigned char)_global.isReverbActivated; - buffer[NUM_REVERB_RETURN]=(unsigned char)getReverbReturn(); - buffer[NUM_REVERB_PARAM_NBR]= + initBuffer[NUM_IS_REVERB_ON]=(unsigned char)_global.isReverbActivated; + initBuffer[NUM_REVERB_RETURN]=(unsigned char)getReverbReturn(); + initBuffer[NUM_REVERB_PARAM_NBR]= ///(_pluginIReverb?(unsigned char)_pluginIReverb->plugin()->parameter() : 0); (_pluginIReverb?(unsigned char)_pluginIReverb->plugin()->controlInPorts() : 0); - strncpy((char*)&buffer[NUM_REVERB_LIB], + strncpy((char*)&initBuffer[NUM_REVERB_LIB], (_pluginIReverb? _pluginIReverb->plugin()->lib().toLatin1().constData() : "\0"), MAXSTRLENGTHFXLIB); - strncpy((char*)&buffer[NUM_REVERB_LABEL], + strncpy((char*)&initBuffer[NUM_REVERB_LABEL], (_pluginIReverb? _pluginIReverb->plugin()->label().toLatin1().constData() : "\0"), MAXSTRLENGTHFXLABEL); //chorus - buffer[NUM_IS_CHORUS_ON]=(unsigned char)_global.isChorusActivated; - buffer[NUM_CHORUS_RETURN]=(unsigned char)getChorusReturn(); - buffer[NUM_CHORUS_PARAM_NBR]= + initBuffer[NUM_IS_CHORUS_ON]=(unsigned char)_global.isChorusActivated; + initBuffer[NUM_CHORUS_RETURN]=(unsigned char)getChorusReturn(); + initBuffer[NUM_CHORUS_PARAM_NBR]= ///(_pluginIChorus?(unsigned char)_pluginIChorus->plugin()->parameter() : 0); (_pluginIChorus?(unsigned char)_pluginIChorus->plugin()->controlInPorts() : 0); - strncpy((char*)&buffer[NUM_CHORUS_LIB], + strncpy((char*)&initBuffer[NUM_CHORUS_LIB], (_pluginIChorus? _pluginIChorus->plugin()->lib().toLatin1().constData() : "\0"), MAXSTRLENGTHFXLIB); - strncpy((char*)&buffer[NUM_CHORUS_LABEL], + strncpy((char*)&initBuffer[NUM_CHORUS_LABEL], (_pluginIChorus? _pluginIChorus->plugin()->label().toLatin1().constData() : "\0"), MAXSTRLENGTHFXLABEL); //delay - buffer[NUM_IS_DELAY_ON]=(unsigned char)_global.isDelayActivated; - buffer[NUM_DELAY_RETURN]=(unsigned char)getDelayReturn(); + initBuffer[NUM_IS_DELAY_ON]=(unsigned char)_global.isDelayActivated; + initBuffer[NUM_DELAY_RETURN]=(unsigned char)getDelayReturn(); //save FX parameters //reverb - for(int i = 0; i < (int)buffer[NUM_REVERB_PARAM_NBR]; i++) { + for(int i = 0; i < (int)initBuffer[NUM_REVERB_PARAM_NBR]; i++) { float val = (float)getReverbParam(i); - memcpy(&buffer[NUM_CONFIGLENGTH + sizeof(float)*i], &val, sizeof(float)); + memcpy(&initBuffer[NUM_CONFIGLENGTH + sizeof(float)*i], &val, sizeof(float)); } //chorus - for(int i = 0; i < (int)buffer[NUM_CHORUS_PARAM_NBR]; i++) { + for(int i = 0; i < (int)initBuffer[NUM_CHORUS_PARAM_NBR]; i++) { float val = (float)getChorusParam(i); - memcpy(&buffer[NUM_CONFIGLENGTH - + sizeof(float)*(int)buffer[NUM_REVERB_PARAM_NBR] + memcpy(&initBuffer[NUM_CONFIGLENGTH + + sizeof(float)*(int)initBuffer[NUM_REVERB_PARAM_NBR] + sizeof(float)*i], &val, sizeof(float)); } //delay float delayfloat; delayfloat = getDelayBPM(); - memcpy(&buffer[NUM_DELAY_BPM], &delayfloat, 4); + memcpy(&initBuffer[NUM_DELAY_BPM], &delayfloat, 4); delayfloat = getDelayBeatRatio(); - memcpy(&buffer[NUM_DELAY_BEATRATIO], &delayfloat, sizeof(float)); + memcpy(&initBuffer[NUM_DELAY_BEATRATIO], &delayfloat, sizeof(float)); delayfloat = getDelayFeedback(); - memcpy(&buffer[NUM_DELAY_FEEDBACK], &delayfloat, sizeof(float)); + memcpy(&initBuffer[NUM_DELAY_FEEDBACK], &delayfloat, sizeof(float)); delayfloat = getDelayLFOFreq(); - memcpy(&buffer[NUM_DELAY_LFO_FREQ], &delayfloat, sizeof(float)); + memcpy(&initBuffer[NUM_DELAY_LFO_FREQ], &delayfloat, sizeof(float)); delayfloat = getDelayLFODepth(); - memcpy(&buffer[NUM_DELAY_LFO_DEPTH], &delayfloat, sizeof(float)); + memcpy(&initBuffer[NUM_DELAY_LFO_DEPTH], &delayfloat, sizeof(float)); //save set data int offset = NUM_CONFIGLENGTH - + sizeof(float)*(int)buffer[NUM_REVERB_PARAM_NBR] - + sizeof(float)*(int)buffer[NUM_CHORUS_PARAM_NBR]; + + sizeof(float)*(int)initBuffer[NUM_REVERB_PARAM_NBR] + + sizeof(float)*(int)initBuffer[NUM_CHORUS_PARAM_NBR]; for(int i = offset; i < *length; i++) - buffer[i]=(unsigned char)baComp.at(i - offset); + initBuffer[i]=(unsigned char)baComp.at(i - offset); - *data=buffer; + ///*data=buffer; + *data=initBuffer; } //--------------------------------------------------------- // parseInitData //--------------------------------------------------------- void DeicsOnze::parseInitData(int length, const unsigned char* data) { - if(data[1]==SYSEX_INIT_DATA_VERSION) { + ///if(data[1]==SYSEX_INIT_DATA_VERSION) { + if(data[3]==SYSEX_INIT_DATA_VERSION) { //load global parameters //master volume setMasterVol(data[NUM_MASTERVOL]); @@ -2600,7 +2640,7 @@ void DeicsOnze::parseInitData(int length, const unsigned char* data) { (const char*)&data[NUM_REVERB_LABEL]); if(p) { initPluginReverb(p); - //for(int i = 0; i < _pluginIReverb->plugin()->parameter(); i++) { + ///for(int i = 0; i < _pluginIReverb->plugin()->parameter(); i++) { for(int i = 0; i < (int)_pluginIReverb->plugin()->controlInPorts(); i++) { float val; memcpy(&val, &data[NUM_CONFIGLENGTH + sizeof(float)*i], sizeof(float)); @@ -2630,7 +2670,7 @@ void DeicsOnze::parseInitData(int length, const unsigned char* data) { (const char*)&data[NUM_CHORUS_LABEL]); if(p) { initPluginChorus(p); - //for(int i = 0; i < _pluginIChorus->plugin()->parameter(); i++) { + ///for(int i = 0; i < _pluginIChorus->plugin()->parameter(); i++) { for(int i = 0; i < (int)_pluginIChorus->plugin()->controlInPorts(); i++) { float val; memcpy(&val, &data[NUM_CONFIGLENGTH @@ -2788,87 +2828,123 @@ bool DeicsOnze::sysex(int length, const unsigned char* data) { return false; } bool DeicsOnze::sysex(int length, const unsigned char* data, bool fromGui) { - int cmd=data[0]; + + if(length < 3 || data[0] != MUSE_SYNTH_SYSEX_MFG_ID + || data[1] != DEICSONZE_UNIQUE_ID) + { + #ifdef DEICSONZE_DEBUG + printf("MusE DeicsOnze: Unknown sysex header\n"); + #endif + return false; + } + + int l = length - 2; + const unsigned char* d = data + 2; + ///int cmd=data[0]; + int cmd=d[0]; int index; float f; switch(cmd) { case SYSEX_INIT_DATA: parseInitData(length, data); + //parseInitData(l, d); break; case SYSEX_MASTERVOL: - setMasterVol((int)data[1]); + ///setMasterVol((int)data[1]); + setMasterVol((int)d[1]); if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; //case SYSEX_CHANNELNUM: - //_global.channelNum = (char)data[1]; + ///_global.channelNum = (char)data[1]; + //_global.channelNum = (char)d[1]; //if(!fromGui) { - // MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + /// MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + // MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); // _gui->writeEvent(evSysex); //} //break; case SYSEX_QUALITY: - setQuality((Quality)data[1]); + ///setQuality((Quality)data[1]); + setQuality((Quality)d[1]); if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_FILTER: - setFilter((bool)data[1]); + ///setFilter((bool)data[1]); + setFilter((bool)d[1]); if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_FONTSIZE: - _global.fontSize = (int)data[1]; + ///_global.fontSize = (int)data[1]; + _global.fontSize = (int)d[1]; if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_SAVECONFIG: - _saveConfig = (bool)data[1]; + ///_saveConfig = (bool)data[1]; + _saveConfig = (bool)d[1]; if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_SAVEONLYUSED: - _saveOnlyUsed = (bool)data[1]; + ///_saveOnlyUsed = (bool)data[1]; + _saveOnlyUsed = (bool)d[1]; if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_ISINITSET: - _isInitSet = (bool)data[1]; + ///_isInitSet = (bool)data[1]; + _isInitSet = (bool)d[1]; if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_INITSETPATH: - _initSetPath = (char*)&data[1]; + ///_initSetPath = (char*)&data[1]; + _initSetPath = (char*)&d[1]; if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_ISBACKGROUNDPIX: - _isBackgroundPix = (bool)data[1]; + ///_isBackgroundPix = (bool)data[1]; + _isBackgroundPix = (bool)d[1]; if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_BACKGROUNDPIXPATH: - _backgroundPixPath = (char*)&data[1]; + ///_backgroundPixPath = (char*)&data[1]; + _backgroundPixPath = (char*)&d[1]; if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; @@ -2876,112 +2952,142 @@ bool DeicsOnze::sysex(int length, const unsigned char* data, bool fromGui) { resetVoices(); break; case SYSEX_CHORUSACTIV: - _global.isChorusActivated = (bool)data[1]; + ///_global.isChorusActivated = (bool)data[1]; + _global.isChorusActivated = (bool)d[1]; if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_CHORUSPARAM: - index = (int)data[1]; - memcpy(&f, &data[2], sizeof(float)); + ///index = (int)data[1]; + ///memcpy(&f, &data[2], sizeof(float)); + index = (int)d[1]; + memcpy(&f, &d[2], sizeof(float)); setChorusParam(index, (double)f); if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_REVERBACTIV: - _global.isReverbActivated = (bool)data[1]; + ///_global.isReverbActivated = (bool)data[1]; + _global.isReverbActivated = (bool)d[1]; if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_REVERBPARAM: - index = (int)data[1]; - memcpy(&f, &data[2], sizeof(float)); + ///index = (int)data[1]; + ///memcpy(&f, &data[2], sizeof(float)); + index = (int)d[1]; + memcpy(&f, &d[2], sizeof(float)); setReverbParam(index, (double)f); if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_DELAYACTIV: - _global.isDelayActivated = (bool)data[1]; + ///_global.isDelayActivated = (bool)data[1]; + _global.isDelayActivated = (bool)d[1]; if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_CHORUSRETURN: - setChorusReturn((int)data[1]); + ///setChorusReturn((int)data[1]); + setChorusReturn((int)d[1]); if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_REVERBRETURN: - setReverbReturn((int)data[1]); + ///setReverbReturn((int)data[1]); + setReverbReturn((int)d[1]); if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_DELAYRETURN: - setDelayReturn((int)data[1]); + ///setDelayReturn((int)data[1]); + setDelayReturn((int)d[1]); if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_SELECTREVERB: Plugin* pluginReverb; - memcpy(&pluginReverb, &data[1], sizeof(Plugin*)); + ///memcpy(&pluginReverb, &data[1], sizeof(Plugin*)); + memcpy(&pluginReverb, &d[1], sizeof(Plugin*)); initPluginReverb(pluginReverb); break; case SYSEX_SELECTCHORUS: Plugin* pluginChorus; - memcpy(&pluginChorus, &data[1], sizeof(Plugin*)); + ///memcpy(&pluginChorus, &data[1], sizeof(Plugin*)); + memcpy(&pluginChorus, &d[1], sizeof(Plugin*)); initPluginChorus(pluginChorus); break; case SYSEX_DELAYBPM: - memcpy(&f, &data[1], sizeof(float)); + ///memcpy(&f, &data[1], sizeof(float)); + memcpy(&f, &d[1], sizeof(float)); setDelayBPM(f); if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_DELAYBEATRATIO: - memcpy(&f, &data[1], sizeof(float)); + ///memcpy(&f, &data[1], sizeof(float)); + memcpy(&f, &d[1], sizeof(float)); setDelayBeatRatio(f); if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_DELAYFEEDBACK: - memcpy(&f, &data[1], sizeof(float)); + ///memcpy(&f, &data[1], sizeof(float)); + memcpy(&f, &d[1], sizeof(float)); setDelayFeedback(f); if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_DELAYLFOFREQ: - memcpy(&f, &data[1], sizeof(float)); + ///memcpy(&f, &data[1], sizeof(float)); + memcpy(&f, &d[1], sizeof(float)); setDelayLFOFreq(f); if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; case SYSEX_DELAYLFODEPTH: - memcpy(&f, &data[1], sizeof(float)); + ///memcpy(&f, &data[1], sizeof(float)); + memcpy(&f, &d[1], sizeof(float)); setDelayLFODepth(f); if(!fromGui) { - MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + ///MidiPlayEvent evSysex(0, 0, ME_SYSEX, data, length); + MidiPlayEvent evSysex(0, 0, ME_SYSEX, d, l); _gui->writeEvent(evSysex); } break; @@ -3728,7 +3834,7 @@ const MidiPatch* DeicsOnze::getPatchInfo(int /*ch*/, const MidiPatch* p) const { */ //--------------------------------------------------------- int DeicsOnze::getControllerInfo(int index, const char** name, - int* controller, int* min, int* max) + int* controller, int* min, int* max, int* initval) const { if (index >= nbrCtrl) { return 0; @@ -3738,6 +3844,7 @@ int DeicsOnze::getControllerInfo(int index, const char** name, *controller = _ctrl[index].num; *min = _ctrl[index].min; *max = _ctrl[index].max; + *initval = 0; // p4.0.27 FIXME NOTE TODO return (index +1); } @@ -3975,10 +4082,32 @@ inline double plusMod(double x, double y) { //--------------------------------------------------------- +// processMessages +// Called from host always, even if output path is unconnected. +//--------------------------------------------------------- + +void DeicsOnze::processMessages() +{ + //Process messages from the gui + while (_gui->fifoSize()) { + MidiPlayEvent ev = _gui->readEvent(); + if (ev.type() == ME_SYSEX) { + sysex(ev.len(), ev.data(), true); + sendEvent(ev); + } + else if (ev.type() == ME_CONTROLLER) { + setController(ev.channel(), ev.dataA(), ev.dataB(), true); + sendEvent(ev); + } + } +} + +//--------------------------------------------------------- // write // synthesize n samples into buffer+offset //--------------------------------------------------------- void DeicsOnze::process(float** buffer, int offset, int n) { + /* //Process messages from the gui while (_gui->fifoSize()) { MidiPlayEvent ev = _gui->readEvent(); @@ -3991,6 +4120,8 @@ void DeicsOnze::process(float** buffer, int offset, int n) { sendEvent(ev); } } + */ + float* leftOutput = buffer[0] + offset; float* rightOutput = buffer[1] + offset; diff --git a/muse2/synti/deicsonze/deicsonze.h b/muse2/synti/deicsonze/deicsonze.h index dc7c533d..bd79b7fb 100644 --- a/muse2/synti/deicsonze/deicsonze.h +++ b/muse2/synti/deicsonze/deicsonze.h @@ -33,6 +33,7 @@ #include <list> +#include "common_defs.h" #include "deicsonzepreset.h" #include "deicsonzegui.h" #include "deicsonzeplugin.h" @@ -99,7 +100,8 @@ #define SYSEX_INIT_DATA 1 #define SYSEX_INIT_DATA_VERSION 1 -#define SAVEINITLENGTH 2 +///#define SAVEINITLENGTH 2 +#define SAVEINITLENGTH 4 // MFG ID, synth ID, init data command, init data version #define DEICSONZECONFIGURATIONSTR "deicsOnzeConfiguation" #define SYSEX_MASTERVOL 4 @@ -432,6 +434,9 @@ struct Global { class DeicsOnze : public Mess { DeicsOnzeGui* _gui; + + unsigned char* initBuffer; + int initLen; static int useCount; static float waveTable[NBRWAVES][RESOLUTION]; @@ -439,6 +444,7 @@ class DeicsOnze : public Mess { private: void parseInitData(int length, const unsigned char* data); void loadConfiguration(QString fileName); + void setupInitBuffer(int len); public: float** tempInputChorus; @@ -577,16 +583,20 @@ class DeicsOnze : public Mess { bool setController(int ch, int ctrl, int val, bool fromGui); virtual bool setController(int ch, int ctrl, int val); bool sysex(int length, const unsigned char* data, bool fromGui); - virtual bool sysex(int length, const unsigned char* data); + virtual bool sysex(int l, const unsigned char* d); virtual const char* getPatchName(int ch, int number, int) const; virtual const MidiPatch* getPatchInfo(int, const MidiPatch *) const; virtual int getControllerInfo(int arg1, const char** arg2, - int* arg3, int* arg4, int* arg5); - virtual void getInitData(int* length, const unsigned char** data) const; + int* arg3, int* arg4, int* arg5, int* arg6) const; + ///virtual void getInitData(int* length, const unsigned char** data) const; + virtual void getInitData(int* length, const unsigned char** data); + // This is only a kludge required to support old songs' midistates. Do not use in any new synth. + virtual int oldMidiStateHeader(const unsigned char** data) const; virtual bool playNote(int channel, int pitch, int velo); + virtual void processMessages(); virtual void process(float** buffer, int offset, int n); // GUI interface routines @@ -600,7 +610,7 @@ class DeicsOnze : public Mess { virtual void setNativeGeometry(int, int, int, int); DeicsOnze(); - ~DeicsOnze(); + virtual ~DeicsOnze(); }; diff --git a/muse2/synti/deicsonze/deicsonzegui.cpp b/muse2/synti/deicsonze/deicsonzegui.cpp index 3cae14f8..4cb78764 100644 --- a/muse2/synti/deicsonze/deicsonzegui.cpp +++ b/muse2/synti/deicsonze/deicsonzegui.cpp @@ -40,6 +40,7 @@ #include "muse/midictrl.h" #include "config.h" +#include "common_defs.h" #include "deicsonzegui.h" #include "plugin.h" @@ -483,9 +484,11 @@ void DeicsOnzeGui::setChangeChannel(int c) { // setPanic //----------------------------------------------------------- void DeicsOnzeGui::setPanic() { - unsigned char* message = new unsigned char[1]; - message[0]=SYSEX_PANIC; - sendSysex(message, 1); + unsigned char message[3]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_PANIC; + sendSysex(message, 3); } //----------------------------------------------------------- @@ -517,10 +520,12 @@ void DeicsOnzeGui::setNbrVoices(int nv) { // setMidiInCh //---------------------------------------------------------- //void DeicsOnzeGui::setMidiInCh(int m) { -// unsigned char* message = new unsigned char[2]; -// message[0]=SYSEX_CHANNELNUM; -// message[1]=(unsigned char)(m-1); -// sendSysex(message, 2); +// unsigned char message[4]; +// message[0]=MUSE_SYNTH_SYSEX_MFG_ID; +// message[1]=DEICSONZE_UNIQUE_ID; +// message[2]=SYSEX_CHANNELNUM; +// message[3]=(unsigned char)(m-1); +// sendSysex(message, 4); //} //----------------------------------------------------------- @@ -625,57 +630,69 @@ void DeicsOnzeGui::loadConfiguration() { // setQuality //----------------------------------------------------------- void DeicsOnzeGui::setQuality(const QString& q) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_QUALITY; - message[1]=(unsigned char)(q=="High"? + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_QUALITY; + message[3]=(unsigned char)(q=="High"? high:(q=="Middle"? middle:(q=="Low"?low:ultralow))); - sendSysex(message, 2); + sendSysex(message, 4); } //----------------------------------------------------------- // setFilter //----------------------------------------------------------- void DeicsOnzeGui::setFilter(bool f) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_FILTER; - message[1]=(unsigned char)f; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_FILTER; + message[3]=(unsigned char)f; + sendSysex(message, 4); } //----------------------------------------------------------- // setFontSize //----------------------------------------------------------- void DeicsOnzeGui::setFontSize(int fs) { applyFontSize(fs); - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_FONTSIZE; - message[1]=(unsigned char)fs; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_FONTSIZE; + message[3]=(unsigned char)fs; + sendSysex(message, 4); } //----------------------------------------------------------- // setSaveOnlyUsed //----------------------------------------------------------- void DeicsOnzeGui::setSaveOnlyUsed(bool sou) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_SAVEONLYUSED; - message[1]=(unsigned char)sou; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_SAVEONLYUSED; + message[3]=(unsigned char)sou; + sendSysex(message, 4); updateSaveOnlyUsed(sou); } void DeicsOnzeGui::setSaveOnlyUsedComp(bool souc) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_SAVEONLYUSED; - message[1]=(unsigned char)!souc; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_SAVEONLYUSED; + message[3]=(unsigned char)!souc; + sendSysex(message, 4); updateSaveOnlyUsed(!souc); } //----------------------------------------------------------- // setSaveConfig //----------------------------------------------------------- void DeicsOnzeGui::setSaveConfig(bool ssc) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_SAVECONFIG; - message[1]=(unsigned char)ssc; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_SAVECONFIG; + message[3]=(unsigned char)ssc; + sendSysex(message, 4); } //----------------------------------------------------------- // setColor @@ -1524,6 +1541,7 @@ void DeicsOnzeGui::processEvent(const MidiPlayEvent& ev) { else if (ev.type() == ME_SYSEX) { //printf("ME_SYSEX\n"); unsigned char* data = ev.data(); + int cmd = *data; float f; switch (cmd) { @@ -2489,16 +2507,20 @@ void DeicsOnzeGui::setProg(int pr) {//must be changed with SysEx void DeicsOnzeGui::setIsInitSet(bool b) { initSetPathLineEdit->setEnabled(b); initSetBrowsePushButton->setEnabled(b); - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_ISINITSET; - message[1]=(unsigned char)b; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_ISINITSET; + message[3]=(unsigned char)b; + sendSysex(message, 4); } void DeicsOnzeGui::setInitSetPath(const QString& s) { - unsigned char* message = new unsigned char[1+MAXSTRLENGTHINITSETPATH]; - message[0]=SYSEX_INITSETPATH; - strncpy((char*)&message[1], s.toAscii().data(), MAXSTRLENGTHINITSETPATH); - sendSysex(message, 1+MAXSTRLENGTHINITSETPATH); + unsigned char message[3+MAXSTRLENGTHINITSETPATH]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_INITSETPATH; + strncpy((char*)&message[3], s.toAscii().data(), MAXSTRLENGTHINITSETPATH); + sendSysex(message, 3+MAXSTRLENGTHINITSETPATH); } void DeicsOnzeGui::setBrowseInitSetPath() { QString fileName = @@ -2522,18 +2544,22 @@ void DeicsOnzeGui::setIsBackgroundPix(bool b) { else setBackgroundColor(reinterpret_cast<const QColor &>(*bColor)); imagePathLineEdit->setEnabled(b); imageBrowsePushButton->setEnabled(b); - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_ISBACKGROUNDPIX; - message[1]=(unsigned char)b; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_ISBACKGROUNDPIX; + message[3]=(unsigned char)b; + sendSysex(message, 4); } void DeicsOnzeGui::setBackgroundPixPath(const QString& s) { applyBackgroundPix(); - unsigned char* message = new unsigned char[1+MAXSTRLENGTHBACKGROUNDPIXPATH]; - message[0]=SYSEX_BACKGROUNDPIXPATH; - strncpy((char*)&message[1], s.toAscii().data(), + unsigned char message[3+MAXSTRLENGTHBACKGROUNDPIXPATH]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_BACKGROUNDPIXPATH; + strncpy((char*)&message[3], s.toAscii().data(), MAXSTRLENGTHBACKGROUNDPIXPATH); - sendSysex(message, 1+MAXSTRLENGTHBACKGROUNDPIXPATH); + sendSysex(message, 3+MAXSTRLENGTHBACKGROUNDPIXPATH); } void DeicsOnzeGui::setBrowseBackgroundPixPath() { QString fileName = @@ -2553,87 +2579,111 @@ void DeicsOnzeGui::setBrowseBackgroundPixPath() { // FX //----------------------------------------------------------- void DeicsOnzeGui::setChorusActiv(bool a) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_CHORUSACTIV; - message[1]=(unsigned char)a; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_CHORUSACTIV; + message[3]=(unsigned char)a; + sendSysex(message, 4); } void DeicsOnzeGui::setChannelChorus(int c) { sendController(_currentChannel, CTRL_CHORUS_SEND, c); } void DeicsOnzeGui::setChorusReturn(int val) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_CHORUSRETURN; - message[1]=(unsigned char)val; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_CHORUSRETURN; + message[3]=(unsigned char)val; + sendSysex(message, 4); } void DeicsOnzeGui::setSelectChorusPlugin() { Plugin* pluginChorus = PluginDialog::getPlugin(this); if(pluginChorus) { - unsigned char* message = new unsigned char[1+sizeof(Plugin*)]; - message[0]=SYSEX_SELECTCHORUS; - memcpy(&message[1], &pluginChorus, sizeof(Plugin*)); - sendSysex(message, 1+sizeof(Plugin*)); + unsigned char message[3+sizeof(Plugin*)]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_SELECTCHORUS; + memcpy(&message[3], &pluginChorus, sizeof(Plugin*)); + sendSysex(message, 3+sizeof(Plugin*)); } } /*void DeicsOnzeGui::setPanChorus1(double i) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_CHORUS1PAN; - message[1]=(unsigned char)(i*(double)MAXCHORUSPARAM); - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_CHORUS1PAN; + message[3]=(unsigned char)(i*(double)MAXCHORUSPARAM); + sendSysex(message, 4); } void DeicsOnzeGui::setLFOFreqChorus1(double i) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_CHORUS1LFOFREQ; - message[1]=(unsigned char)(i*(double)MAXCHORUSPARAM); - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_CHORUS1LFOFREQ; + message[3]=(unsigned char)(i*(double)MAXCHORUSPARAM); + sendSysex(message, 4); } void DeicsOnzeGui::setDepthChorus1(double i) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_CHORUS1DEPTH; - message[1]=(unsigned char)(i*(double)MAXCHORUSPARAM); - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_CHORUS1DEPTH; + message[3]=(unsigned char)(i*(double)MAXCHORUSPARAM); + sendSysex(message, 4); } void DeicsOnzeGui::setPanChorus2(double i) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_CHORUS2PAN; - message[1]=(unsigned char)(i*(double)MAXCHORUSPARAM); - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_CHORUS2PAN; + message[3]=(unsigned char)(i*(double)MAXCHORUSPARAM); + sendSysex(message, 4); } void DeicsOnzeGui::setLFOFreqChorus2(double i) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_CHORUS2LFOFREQ; - message[1]=(unsigned char)(i*(double)MAXCHORUSPARAM); - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_CHORUS2LFOFREQ; + message[3]=(unsigned char)(i*(double)MAXCHORUSPARAM); + sendSysex(message, 4); } void DeicsOnzeGui::setDepthChorus2(double i) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_CHORUS2DEPTH; - message[1]=(unsigned char)(i*(double)MAXCHORUSPARAM); - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_CHORUS2DEPTH; + message[3]=(unsigned char)(i*(double)MAXCHORUSPARAM); + sendSysex(message, 4); }*/ void DeicsOnzeGui::setReverbActiv(bool a) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_REVERBACTIV; - message[1]=(unsigned char)a; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_REVERBACTIV; + message[3]=(unsigned char)a; + sendSysex(message, 4); } void DeicsOnzeGui::setChannelReverb(int r) { sendController(_currentChannel, CTRL_REVERB_SEND, r); } void DeicsOnzeGui::setReverbReturn(int val) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_REVERBRETURN; - message[1]=(unsigned char)val; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_REVERBRETURN; + message[3]=(unsigned char)val; + sendSysex(message, 4); } void DeicsOnzeGui::setSelectReverbPlugin() { Plugin* pluginReverb = PluginDialog::getPlugin(this); if(pluginReverb) { - unsigned char* message = new unsigned char[1+sizeof(Plugin*)]; - message[0]=SYSEX_SELECTREVERB; - memcpy(&message[1], &pluginReverb, sizeof(Plugin*)); - sendSysex(message, 1+sizeof(Plugin*)); + unsigned char message[3+sizeof(Plugin*)]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_SELECTREVERB; + memcpy(&message[3], &pluginReverb, sizeof(Plugin*)); + sendSysex(message, 3+sizeof(Plugin*)); } } @@ -2674,10 +2724,12 @@ void DeicsOnzeGui::setMasterVolKnob(double mv) { setMasterVol((int)(mv*(double)MAXMASTERVOLUME)); } void DeicsOnzeGui::setMasterVol(int mv) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_MASTERVOL; - message[1]=(unsigned char)mv; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_MASTERVOL; + message[3]=(unsigned char)mv; + sendSysex(message, 4); } void DeicsOnzeGui::setFeedback(int f) {sendController(_currentChannel, CTRL_FEEDBACK, f);} @@ -3051,91 +3103,117 @@ void DeicsOnzeGui::setWaveForm4(int w) { // set delay //-------------------------------------------------------------- void DeicsOnzeGui::setActivDelay(bool a) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_DELAYACTIV; - message[1]=(unsigned char)a; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_DELAYACTIV; + message[3]=(unsigned char)a; + sendSysex(message, 4); } void DeicsOnzeGui::setDelayReturn(int r) { - unsigned char* message = new unsigned char[2]; - message[0]=SYSEX_DELAYRETURN; - message[1]=(unsigned char)r; - sendSysex(message, 2); + unsigned char message[4]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_DELAYRETURN; + message[3]=(unsigned char)r; + sendSysex(message, 4); } void DeicsOnzeGui::setChannelDelay(int d) { sendController(_currentChannel, CTRL_VARIATION_SEND, (unsigned char)d); } //void DeicsOnzeGui::setDelayTime(int t) { -// unsigned char* message = new unsigned char[2]; -// message[0]=SYSEX_DELAYTIME; -// message[1]=(unsigned char)t; -// sendSysex(message, 2); +// unsigned char message[4]; +// message[0]=MUSE_SYNTH_SYSEX_MFG_ID; +// message[1]=DEICSONZE_UNIQUE_ID; +// message[2]=SYSEX_DELAYTIME; +// message[3]=(unsigned char)t; +// sendSysex(message, 4); // updateDelayTime(t); //} void DeicsOnzeGui::setDelayBPM(double t) { //int it = (int)(((t - MINDELAYTIME) / (MAXDELAYTIME - MINDELAYTIME))*255.0); - unsigned char* message = new unsigned char[sizeof(float)+1]; - message[0]=SYSEX_DELAYBPM; + unsigned char message[sizeof(float)+3]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_DELAYBPM; float f = (float)t; - memcpy(&message[1], &f, sizeof(float)); - message[1]=(unsigned char)f; - sendSysex(message, sizeof(float)+1); + ///memcpy(&message[1], &f, sizeof(float)); + memcpy(&message[3], &f, sizeof(float)); + ///message[1]=(unsigned char)f; + message[3]=(unsigned char)f; + sendSysex(message, sizeof(float)+3); //updateDelayTime(it); } void DeicsOnzeGui::setDelayBeatRatio(double t) { - unsigned char* message = new unsigned char[sizeof(float)+1]; - message[0]=SYSEX_DELAYBEATRATIO; + unsigned char message[sizeof(float)+3]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_DELAYBEATRATIO; float f = (float)t; - memcpy(&message[1], &f, sizeof(float)); - message[1]=(unsigned char)f; - sendSysex(message, sizeof(float)+1); + ///memcpy(&message[1], &f, sizeof(float)); + memcpy(&message[3], &f, sizeof(float)); + ///message[1]=(unsigned char)f; + message[3]=(unsigned char)f; + sendSysex(message, sizeof(float)+3); } //void DeicsOnzeGui::setDelayFeedback(int f) { -// unsigned char* message = new unsigned char[2]; -// message[0]=SYSEX_DELAYFEEDBACK; -// message[1]=(unsigned char)f; -// sendSysex(message, 2); +// unsigned char message[4]; +// message[0]=MUSE_SYNTH_SYSEX_MFG_ID; +// message[1]=DEICSONZE_UNIQUE_ID; +// message[2]=SYSEX_DELAYFEEDBACK; +// message[3]=(unsigned char)f; +// sendSysex(message, 4); // updateDelayFeedback(f); //} void DeicsOnzeGui::setDelayFeedback(double t) { //int idf = (int)(f*128.0+128.0); - unsigned char* message = new unsigned char[sizeof(float)+1]; - message[0]=SYSEX_DELAYFEEDBACK; + unsigned char message[sizeof(float)+3]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_DELAYFEEDBACK; float f = (float)t; - memcpy(&message[1], &f, sizeof(float)); - sendSysex(message, sizeof(float)+1); + memcpy(&message[3], &f, sizeof(float)); + sendSysex(message, sizeof(float)+3); //updateDelayFeedback(idf); } //void DeicsOnzeGui::setDelayPanLFOFreq(int pf) { -// unsigned char* message = new unsigned char[2]; -// message[0]=SYSEX_DELAYLFOFREQ; -// message[1]=(unsigned char)pf; -// sendSysex(message, 2); +// unsigned char message[4]; +// message[0]=MUSE_SYNTH_SYSEX_MFG_ID; +// message[1]=DEICSONZE_UNIQUE_ID; +// message[2]=SYSEX_DELAYLFOFREQ; +// message[3]=(unsigned char)pf; +// sendSysex(message, 4); // updateDelayPanLFOFreq(pf); //} void DeicsOnzeGui::setDelayPanLFOFreq(double pf) { //int ipf = (int)(((pf - MINFREQ) / (MAXFREQ - MINFREQ))*255.0); - unsigned char* message = new unsigned char[sizeof(float)+1]; - message[0]=SYSEX_DELAYLFOFREQ; + unsigned char message[sizeof(float)+3]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_DELAYLFOFREQ; float f = (float)pf; - memcpy(&message[1], &f, sizeof(float)); - sendSysex(message, sizeof(float)+1); + memcpy(&message[3], &f, sizeof(float)); + sendSysex(message, sizeof(float)+3); //updateDelayPanLFOFreq(ipf); } //void DeicsOnzeGui::setDelayPanLFODepth(int pd) { -// unsigned char* message = new unsigned char[2]; -// message[0]=SYSEX_DELAYLFODEPTH; -// message[1]=(unsigned char)pd; -// sendSysex(message, 2); +// unsigned char message[4]; +// message[0]=MUSE_SYNTH_SYSEX_MFG_ID; +// message[1]=DEICSONZE_UNIQUE_ID; +// message[2]=SYSEX_DELAYLFODEPTH; +// message[3]=(unsigned char)pd; +// sendSysex(message, 4); // updateDelayPanLFODepth(pd); //} void DeicsOnzeGui::setDelayPanLFODepth(double pd) { //int ipd = (int)(pd*255.0); - unsigned char* message = new unsigned char[sizeof(float)+1]; - message[0]=SYSEX_DELAYLFODEPTH; + unsigned char message[sizeof(float)+3]; + message[0]=MUSE_SYNTH_SYSEX_MFG_ID; + message[1]=DEICSONZE_UNIQUE_ID; + message[2]=SYSEX_DELAYLFODEPTH; float f = (float)pd; - memcpy(&message[1], &f, sizeof(float)); - sendSysex(message, sizeof(float)+1); + memcpy(&message[3], &f, sizeof(float)); + sendSysex(message, sizeof(float)+3); //updateDelayPanLFODepth(ipd); } @@ -4339,7 +4417,9 @@ void DeicsOnzeGui::updateBackgroundPixPath(QString s) { imagePathLineEdit->blockSignals(false); } void DeicsOnzeGui::applyBackgroundPix() { + #ifdef DEICSONZE_DEBUG printf("applyBackgroundPix\n"); + #endif QPalette p = this->palette(); QPixmap pixmap = QPixmap(imagePathLineEdit->text()); p.setBrush((this)->backgroundRole(), QBrush(pixmap)); diff --git a/muse2/synti/fluid/common_defs.h b/muse2/synti/fluid/common_defs.h new file mode 100644 index 00000000..6aa62bc0 --- /dev/null +++ b/muse2/synti/fluid/common_defs.h @@ -0,0 +1,12 @@ +#ifndef __FLUID_UNIQUE_ID_H +#define __FLUID_UNIQUE_ID_H + +// Make sure this number is unique among all the MESS synths. +#define FLUID_UNIQUE_ID 0 + +//#define FLUID_DEBUG + +enum SfOp { SF_REPLACE = 1, SF_ADD, SF_REMOVE }; + +#endif + diff --git a/muse2/synti/fluid/fluid.cpp b/muse2/synti/fluid/fluid.cpp index ad3d06a6..c06e672e 100644 --- a/muse2/synti/fluid/fluid.cpp +++ b/muse2/synti/fluid/fluid.cpp @@ -28,6 +28,7 @@ #include "muse/midictrl.h" +//#include "common_defs.h" #include "muse/midi.h" #include "fluid.h" #include "fluidgui.h" @@ -186,7 +187,6 @@ bool ISynth::sysex(int len, const unsigned char* data) } } } - //--------------------------------------------- // Universal Realtime //--------------------------------------------- @@ -194,55 +194,68 @@ bool ISynth::sysex(int len, const unsigned char* data) else if (data[0] == 0x7f) { if (data[1] == 0x7f) { // device Id if ((data[2] == 0x4) && (data[3] == 0x1)) { + if(len == 6) + { float v = (data[5]*128 + data[4])/32767.0; fluid_synth_set_gain(_fluidsynth, v); return false; } + } } } - //--------------------------------------------- // MusE Soft Synth //--------------------------------------------- - else if (data[0] == 0x7c) { + else if (data[0] == MUSE_SYNTH_SYSEX_MFG_ID) { int n = len - 3; if (n < 1) { + #ifdef FS_DEBUG printf("fluid: bad sysEx:\n"); + #endif return false; } char buffer[n+1]; memcpy(buffer, (char*)data+3, n); buffer[n] = 0; - if (data[1] == 0) { // fluid - if (data[2] == 1) { // load sound font + if (data[1] == FLUID_UNIQUE_ID) { // fluid + //if (data[2] == 1) { // load sound font + if (data[2] == SF_REPLACE) { // load sound font sysexSoundFont(SF_REPLACE, buffer); return false; } - else if (data[2] == 2) { // load sound font + //else if (data[2] == 2) { // load sound font + else if (data[2] == SF_ADD) { // load sound font sysexSoundFont(SF_ADD, buffer); return false; } - else if (data[2] == 3) { // load sound font + //else if (data[2] == 3) { // load sound font + else if (data[2] == SF_REMOVE) { // load sound font sysexSoundFont(SF_REMOVE, buffer); return false; } } } + else if (data[0] == 0x41) { // roland - if (data[1] == 0x10 && data[2] == 0x42 && data[3] == 0x12 - && data[4] == 0x40 && data[5] == 00 && data[6] == 0x7f - && data[7] == 0x41) { - // gs on - gmOn(true); - return false; - } - } - } + if (data[1] == 0x10 && data[2] == 0x42 && data[3] == 0x12) + { + if (len == 8) { + if(data[4] == 0x40 && data[5] == 00 && data[6] == 0x7f && data[7] == 0x41) { + // gs on + gmOn(true); + return false; + } + } + } + } + } + #ifdef FS_DEBUG printf("fluid: unknown sysex received, len %d:\n", len); for (int i = 0; i < len; ++i) printf("%02x ", data[i]); printf("\n"); + #endif return false; } @@ -292,6 +305,8 @@ void ISynth::showNativeGui(bool flag) ISynth::~ISynth() { + if(gui) + delete gui; // p4.0.27 // TODO delete settings if (_fluidsynth) delete_fluid_synth(_fluidsynth); @@ -390,7 +405,9 @@ const char* ISynth::getPatchName(int /*ch*/, int val, int, bool /*drum*/) const const char* name = "<unknown>"; if (_busy) { + //#ifdef FS_DEBUG printf("fluid: getPatchName(): busy!\n"); + //#endif return name; } fluid_font = fluid_synth_get_sfont_by_id(_fluidsynth, hbank); @@ -399,8 +416,12 @@ const char* ISynth::getPatchName(int /*ch*/, int val, int, bool /*drum*/) const if (preset) name = (*preset->get_name)(preset); else + { + //#ifdef FS_DEBUG fprintf(stderr, "no fluid preset for bank %d prog %d\n", lbank, prog); + //#endif + } } else fprintf(stderr, "ISynth::getPatchName(): no fluid font id=%d found\n", hbank); @@ -414,7 +435,9 @@ const char* ISynth::getPatchName(int /*ch*/, int val, int, bool /*drum*/) const const MidiPatch* ISynth::getPatchInfo(int ch, const MidiPatch* p) const { if (_busy) { + //#ifdef FS_DEBUG printf("fluid: getPatchInfo(): busy!\n"); + //#endif return 0; } if (p == 0) { @@ -459,13 +482,14 @@ void ISynth::getInitData(int* len, const unsigned char** data) if (initBuffer) delete [] initBuffer; initBuffer = new unsigned char[n]; + initLen = n; // p4.0.27 Tim. } - initBuffer[0] = 0x7c; - initBuffer[1] = 0x00; + initBuffer[0] = MUSE_SYNTH_SYSEX_MFG_ID; + initBuffer[1] = FLUID_UNIQUE_ID; initBuffer[2] = SF_REPLACE; strcpy((char*)(initBuffer+3), sfont); *len = n; - *data = initBuffer; + *data = (unsigned char*)initBuffer; } //--------------------------------------------------------- @@ -482,11 +506,15 @@ void ISynth::sysexSoundFont(SfOp op, const char* data) case SF_REPLACE: case SF_ADD: if (sfont && (strcmp(sfont, data) == 0)) { + #ifdef FS_DEBUG fprintf(stderr, "fluid: font already loaded\n"); + #endif break; } if (_busy) { + //#ifdef FS_DEBUG fprintf(stderr, "fluid: busy!\n"); + //#endif break; } _busy = true; @@ -528,18 +556,35 @@ void ISynth::noRTHelper() } int id = getFontId(); if (id != -1) { + #ifdef FS_DEBUG fprintf(stderr, "ISynth: unload old font\n"); + #endif fluid_synth_sfunload(synth(), (unsigned)id, true); } - int rv = fluid_synth_sfload(synth(), getFont(), true); + const char* fontname = getFont(); + int rv = fluid_synth_sfload(synth(), fontname, true); if (rv == -1) { fprintf(stderr, "ISynth: sfload %s failed\n", fluid_synth_error(synth())); } else { setFontId(rv); + + // Inform the gui. p4.0.27 Tim + int slen = strlen(fontname); + int n = slen + 2; + unsigned char d[n]; + d[0] = FS_SEND_SOUNDFONT_NAME; + if(slen != 0) + memcpy(d + 1, fontname, slen); + d[1 + slen] = 0; + MidiPlayEvent ev(0,0, ME_SYSEX, d, n); + gui->writeEvent(ev); + + #ifdef FS_DEBUG fprintf(stderr, "ISynth: sfont %s loaded as %d\n ", getFont(), rv); + #endif } fluid_synth_set_gain(synth(), 1.0); //? _busy = false; diff --git a/muse2/synti/fluid/fluid.h b/muse2/synti/fluid/fluid.h index e80f1463..02b111e4 100644 --- a/muse2/synti/fluid/fluid.h +++ b/muse2/synti/fluid/fluid.h @@ -20,8 +20,9 @@ #include <list> #include <fluidsynth.h> #include "libsynti/mess.h" +#include "common_defs.h" -enum SfOp { SF_REPLACE = 1, SF_ADD, SF_REMOVE }; +//enum SfOp { SF_REPLACE = 1, SF_ADD, SF_REMOVE }; class FLUIDGui; //--------------------------------------------------------- @@ -73,8 +74,12 @@ class ISynth : public Mess { public: ISynth(); - ~ISynth(); + virtual ~ISynth(); + // This is only a kludge required to support old songs' midistates. Do not use in any new synth. + // Note for Fluid, do nothing because unlike other synths, Fluid already had correct sysex headers. + //virtual int oldMidiStateHeader(const unsigned char** data) const; + fluid_synth_t* synth() { return _fluidsynth; } const fluid_synth_t* synth() const { return _fluidsynth; } char* getFont() const { return sfont; } diff --git a/muse2/synti/fluid/fluidgui.cpp b/muse2/synti/fluid/fluidgui.cpp index af8d937c..1f948a7d 100644 --- a/muse2/synti/fluid/fluidgui.cpp +++ b/muse2/synti/fluid/fluidgui.cpp @@ -15,9 +15,12 @@ #include <QFileDialog> #include <QFileInfo> #include <QMessageBox> +#include <QSocketNotifier> +#include "common_defs.h" #include "fluidgui.h" #include "muse/midi.h" +#include "muse/mpevent.h" #include "muse/icons.h" //--------------------------------------------------------- @@ -28,6 +31,10 @@ FLUIDGui::FLUIDGui() : QDialog(0, Qt::Window), MessGui() { setupUi(this); + //Connect socketnotifier to fifo + QSocketNotifier* s = new QSocketNotifier(readFd, QSocketNotifier::Read); + connect(s, SIGNAL(activated(int)), SLOT(readMessage(int))); + fdialogButton->setIcon(QIcon(*openIcon)); connect(fdialogButton, SIGNAL(clicked()), SLOT(soundFontFileDialog())); connect(loadButton, SIGNAL(clicked()), SLOT(loadFont())); @@ -60,9 +67,9 @@ void FLUIDGui::loadFont() int len = strlen(path) + 1 + 3; unsigned char buffer[len]; int k = 0; - buffer[k++] = 0x7c; - buffer[k++] = 0x00; // fluid - buffer[k++] = 0x01; // load sound font + buffer[k++] = MUSE_SYNTH_SYSEX_MFG_ID; + buffer[k++] = FLUID_UNIQUE_ID; // fluid + buffer[k++] = SF_REPLACE; // load sound font strcpy((char*)(&buffer[k]), path); sendSysex(buffer, len); } @@ -80,3 +87,40 @@ void FLUIDGui::soundFontFileDialog() } } +void FLUIDGui::processEvent(const MidiPlayEvent& ev) +{ + // p4.0.27 + if (ev.type() == ME_SYSEX) { + const unsigned char* data = ev.data(); + switch (*data) { + case FS_SEND_SOUNDFONT_NAME: { + //const char* filename = data+1; + //pathEntry->setText(QString(filename)); + pathEntry->setText((const char*)(data+1)); + break; + } + default: + #ifdef FS_DEBUG + printf("FLUIDGui::processEvent() : Unknown Sysex received: %d\n", ev.type()); + #endif + break; + } + } + else + { + #ifdef FS_DEBUG + printf("FLUIDGui::processEvent - unknown event of type %dreceived from synth.\n", ev.type()); + #endif + } +} + +//--------------------------------------------------------- +// readMessage +//--------------------------------------------------------- + +void FLUIDGui::readMessage(int) + { + MessGui::readMessage(); // p4.0.27 + } + + diff --git a/muse2/synti/fluid/fluidgui.h b/muse2/synti/fluid/fluidgui.h index 3e564538..2752567f 100644 --- a/muse2/synti/fluid/fluidgui.h +++ b/muse2/synti/fluid/fluidgui.h @@ -12,6 +12,10 @@ #include "ui_fluidguibase.h" #include "libsynti/gui.h" +#define FS_SEND_SOUNDFONT_NAME 1 + +//#define FS_DEBUG + class QDialog; //--------------------------------------------------------- @@ -23,11 +27,13 @@ class FLUIDGui : public QDialog, public Ui::FLUIDGuiBase, public MessGui { Q_OBJECT private slots: + void readMessage(int); void soundFontFileDialog(); void loadFont(); public: FLUIDGui(); + virtual void processEvent(const MidiPlayEvent&); }; #endif diff --git a/muse2/synti/fluidsynth/common_defs.h b/muse2/synti/fluidsynth/common_defs.h new file mode 100644 index 00000000..f1f4007d --- /dev/null +++ b/muse2/synti/fluidsynth/common_defs.h @@ -0,0 +1,8 @@ +#ifndef __FLUIDSYNTH_UNIQUE_ID_H +#define __FLUIDSYNTH_UNIQUE_ID_H + +// Make sure this number is unique among all the MESS synths. +#define FLUIDSYNTH_UNIQUE_ID 3 + +#endif + diff --git a/muse2/synti/fluidsynth/fluidsynthgui.cpp b/muse2/synti/fluidsynth/fluidsynthgui.cpp index 2e91515f..6dda43bd 100644 --- a/muse2/synti/fluidsynth/fluidsynthgui.cpp +++ b/muse2/synti/fluidsynth/fluidsynthgui.cpp @@ -22,6 +22,7 @@ #include "muse/midi.h" #include "icons.h" +#include "common_defs.h" /* #include "muse/debug.h" @@ -183,10 +184,14 @@ void FluidSynthGui::loadClicked() void FluidSynthGui::sendLastdir(QString dir) { - int l = dir.length()+2; + //int l = dir.length()+2; + int l = dir.length()+4; byte data[l]; - data[0] = FS_LASTDIR_CHANGE; - memcpy(data+1, dir.toLatin1(), dir.length()+1); + data[0] = MUSE_SYNTH_SYSEX_MFG_ID; + data[1] = FLUIDSYNTH_UNIQUE_ID; + data[2] = FS_LASTDIR_CHANGE; + //memcpy(data+1, dir.toLatin1(), dir.length()+1); + memcpy(data+3, dir.toLatin1(), dir.length()+1); sendSysex(data,l); } @@ -197,11 +202,15 @@ void FluidSynthGui::sendLastdir(QString dir) void FluidSynthGui::sendLoadFont(QString filename) { - int l = filename.length()+3; + //int l = filename.length()+3; + int l = filename.length()+5; byte data[l]; - data[0] = FS_PUSH_FONT; - data[1] = FS_UNSPECIFIED_ID; - memcpy(data+2, filename.toLatin1(), filename.length()+1); + data[0] = MUSE_SYNTH_SYSEX_MFG_ID; + data[1] = FLUIDSYNTH_UNIQUE_ID; + data[2] = FS_PUSH_FONT; + data[3] = FS_UNSPECIFIED_ID; + //memcpy(data+2, filename.toLatin1(), filename.length()+1); + memcpy(data+4, filename.toLatin1(), filename.length()+1); sendSysex(data,l); } @@ -446,9 +455,13 @@ void FluidSynthGui::changeGain(int value) //--------------------------------------------------------- void FluidSynthGui::dumpInfo() { - byte data[1]; - data[0] = FS_DUMP_INFO; - sendSysex(data, 1); + //byte data[1]; + byte data[3]; + data[0] = MUSE_SYNTH_SYSEX_MFG_ID; + data[1] = FLUIDSYNTH_UNIQUE_ID; + data[2] = FS_DUMP_INFO; + //sendSysex(data, 1); + sendSysex(data, 3); } //--------------------------------------------------------- @@ -581,11 +594,15 @@ int FluidSynthGui::getSoundFontId(QString q) void FluidSynthGui::sendChannelChange(byte font_id, byte channel) { - byte data[3]; - data[0] = FS_SOUNDFONT_CHANNEL_SET; - data[1] = font_id; - data[2] = channel; - sendSysex(data, 3); + //byte data[3]; + byte data[5]; + data[0] = MUSE_SYNTH_SYSEX_MFG_ID; + data[1] = FLUIDSYNTH_UNIQUE_ID; + data[2] = FS_SOUNDFONT_CHANNEL_SET; + data[3] = font_id; + data[4] = channel; + //sendSysex(data, 3); + sendSysex(data, 5); } //--------------------------------------------------------- @@ -594,21 +611,29 @@ void FluidSynthGui::sendChannelChange(byte font_id, byte channel) //--------------------------------------------------------- void FluidSynthGui::sendDrumChannelChange(byte onoff, byte channel) { - byte data[3]; - data[0] = FS_DRUMCHANNEL_SET; - data[1] = onoff; - data[2] = channel; - sendSysex(data, 3); + //byte data[3]; + byte data[5]; + data[0] = MUSE_SYNTH_SYSEX_MFG_ID; + data[1] = FLUIDSYNTH_UNIQUE_ID; + data[2] = FS_DRUMCHANNEL_SET; + data[3] = onoff; + data[4] = channel; + //sendSysex(data, 3); + sendSysex(data, 5); if (FS_DEBUG) printf("Sent FS_DRUMCHANNEL_SET for channel %d, status: %d\n", channel, onoff); } void FluidSynthGui::popClicked() { - byte data[2]; - data[0] = FS_SOUNDFONT_POP; - data[1] = currentlySelectedFont; - sendSysex(data,2); + //byte data[2]; + byte data[4]; + data[0] = MUSE_SYNTH_SYSEX_MFG_ID; + data[1] = FLUIDSYNTH_UNIQUE_ID; + data[2] = FS_SOUNDFONT_POP; + data[3] = currentlySelectedFont; + //sendSysex(data,2); + sendSysex(data,4); } void FluidSynthGui::sfItemClicked(QTreeWidgetItem* item, int /*col*/) diff --git a/muse2/synti/fluidsynth/fluidsynthgui.h b/muse2/synti/fluidsynth/fluidsynthgui.h index 5b39723e..373a2343 100644 --- a/muse2/synti/fluidsynth/fluidsynthgui.h +++ b/muse2/synti/fluidsynth/fluidsynthgui.h @@ -46,7 +46,8 @@ struct FluidChannel; #define FS_SFDATALEN 1 #define FS_VERSION_MAJOR 0 #define FS_VERSION_MINOR 4 -#define FS_INIT_DATA_HEADER_SIZE 4 +//#define FS_INIT_DATA_HEADER_SIZE 4 +#define FS_INIT_DATA_HEADER_SIZE 6 // Including MFG + synth IDs #define FS_INIT_CHANNEL_SECTION 255 // Predefined init-values for fluidsynth diff --git a/muse2/synti/fluidsynth/fluidsynti.cpp b/muse2/synti/fluidsynth/fluidsynti.cpp index aadc92ef..35ee16df 100644 --- a/muse2/synti/fluidsynth/fluidsynti.cpp +++ b/muse2/synti/fluidsynth/fluidsynti.cpp @@ -12,6 +12,7 @@ #include <QFileInfo> +//#include "common_defs.h" #include "fluidsynti.h" #include "muse/midi.h" @@ -65,6 +66,7 @@ QString *projPathPtr; // FluidSynth::FluidSynth(int sr, pthread_mutex_t *_Globalsfloader_mutex) : Mess(2) { + gui = 0; setSampleRate(sr); fluid_settings_t* s = new_fluid_settings(); fluid_settings_setnum(s, (char*) "synth.sample-rate", float(sampleRate())); @@ -85,19 +87,18 @@ FluidSynth::FluidSynth(int sr, pthread_mutex_t *_Globalsfloader_mutex) : Mess(2) //pthread_mutex_init(&_sfloader_mutex,NULL); _sfloader_mutex = _Globalsfloader_mutex; -/* - buffer = 0; - bufferlen = 0; - */ + initBuffer = 0; + initLen = 0; } FluidSynth::~FluidSynth() { int err = delete_fluid_synth (fluidsynth); - delete gui; + if(gui) + delete gui; -/* if (buffer) - delete [] buffer;*/ + if (initBuffer) + delete [] initBuffer; if (err == -1) { std::cerr << DEBUG_ARGS << "error while destroying synth: " << fluid_synth_error(fluidsynth) << std::endl; return; @@ -141,6 +142,13 @@ bool FluidSynth::init(const char* name) return false; } +int FluidSynth::oldMidiStateHeader(const unsigned char** data) const +{ + unsigned char const d[2] = {MUSE_SYNTH_SYSEX_MFG_ID, FLUIDSYNTH_UNIQUE_ID}; + *data = &d[0]; + return 2; +} + //--------------------------------------------------------- // processMessages // Called from host always, even if output path is unconnected. @@ -207,7 +215,7 @@ void FluidSynth::process(float** ports, int offset, int len) // getInitData // Prepare data that will restore the synth's state on load //--------------------------------------------------------- -void FluidSynth::getInitData(int* n, const unsigned char** data) const +void FluidSynth::getInitData(int* n, const unsigned char** data) { //printf("projPathPtr "); @@ -250,16 +258,29 @@ void FluidSynth::getInitData(int* n, const unsigned char** data) const if (FS_DEBUG) printf("Total length of init sysex: %d\n", len); - byte* d = new byte[len]; + + //byte* d = new byte[len]; + if (len > initLen) { + if (initBuffer) + delete [] initBuffer; + initBuffer = new byte[len]; + initLen = len; + } // Header: - d[0] = FS_INIT_DATA; - d[1] = FS_VERSION_MAJOR; - d[2] = FS_VERSION_MINOR; - d[3] = stack.size(); + //d[0] = FS_INIT_DATA; + //d[1] = FS_VERSION_MAJOR; + //d[2] = FS_VERSION_MINOR; + //d[3] = stack.size(); + initBuffer[0] = MUSE_SYNTH_SYSEX_MFG_ID; + initBuffer[1] = FLUIDSYNTH_UNIQUE_ID; + initBuffer[2] = FS_INIT_DATA; + initBuffer[3] = FS_VERSION_MAJOR; + initBuffer[4] = FS_VERSION_MINOR; + initBuffer[5] = stack.size(); //Lastdir: - byte* chptr = d + FS_INIT_DATA_HEADER_SIZE; + byte* chptr = initBuffer + FS_INIT_DATA_HEADER_SIZE; memcpy(chptr, lastdir.c_str(), strlen(lastdir.c_str())+1); //For each font... @@ -298,14 +319,14 @@ void FluidSynth::getInitData(int* n, const unsigned char** data) const *chptr = cho_on; chptr++; if (FS_DEBUG) { for (int i=0; i<len; i++) - printf("%c ", d[i]); + printf("%c ", initBuffer[i]); printf("\n"); for (int i=0; i<len; i++) - printf("%x ", d[i]); + printf("%x ", initBuffer[i]); printf("\n"); } // Give values to host: - *data = d; + *data = (unsigned char*)initBuffer; *n = len; } @@ -313,7 +334,7 @@ void FluidSynth::getInitData(int* n, const unsigned char** data) const // parseInitData //----------------------------------- void FluidSynth::parseInitData(int n, const byte* d) - { +{ printf("projPathPtr "); std::cout << *projPathPtr->toAscii().data() << std::endl; @@ -329,6 +350,7 @@ void FluidSynth::parseInitData(int n, const byte* d) byte version_major, version_minor; version_major = d[1]; version_minor = d[2]; + //version_major = d[3]; version_minor = d[4]; // Check which version of the initdata we're using and if it's OK if (!(version_major == FS_VERSION_MAJOR && version_minor == FS_VERSION_MINOR)) { @@ -337,9 +359,9 @@ void FluidSynth::parseInitData(int n, const byte* d) } if (version_major == 0 && version_minor == 1) { - sendError("Initialization data created with different version of FluidSynth Mess, will be ignored."); - return; - } + sendError("Initialization data created with different version of FluidSynth Mess, will be ignored."); + return; + } if (version_major == 0 && version_minor <= 2) { load_drumchannels = false; @@ -351,8 +373,10 @@ void FluidSynth::parseInitData(int n, const byte* d) } byte nr_of_fonts = d[3]; + //byte nr_of_fonts = d[5]; nrOfSoundfonts = nr_of_fonts; //"Global" counter const byte* chptr = (d + 4); + //const byte* chptr = (d + FS_INIT_DATA_HEADER_SIZE); //Get lastdir: lastdir = std::string((char*)chptr); @@ -365,7 +389,7 @@ void FluidSynth::parseInitData(int n, const byte* d) for (int i=0; i<nr_of_fonts; i++) { fonts[i].filename = (char*)(chptr); chptr+=(strlen(fonts[i].filename.c_str())+1); - QByteArray ba = projPathPtr->toAscii(); + QByteArray ba = projPathPtr->toAscii(); if (QFileInfo(fonts[i].filename.c_str()).isRelative()) { printf("path is relative, we append full path!\n"); @@ -413,7 +437,7 @@ void FluidSynth::parseInitData(int n, const byte* d) for (int i=0; i<nrOfSoundfonts; i++) { pushSoundfont(fonts[i].filename.c_str(), fonts[i].extid); } - } +} //--------------------------------------------------------- @@ -464,19 +488,29 @@ bool FluidSynth::processEvent(const MidiPlayEvent& ev) bool FluidSynth::sysex(int n, const unsigned char* d) { - switch(*d) { + if(n < 3 || d[0] != MUSE_SYNTH_SYSEX_MFG_ID + || d[1] != FLUIDSYNTH_UNIQUE_ID) + { + if (FS_DEBUG) + printf("MusE FluidSynth: Unknown sysex header\n"); + return false; + } + + //switch(*d) { + const unsigned char* chrptr = d + 2; + switch(*chrptr) { case FS_LASTDIR_CHANGE: { - lastdir = std::string((char*)(d+1)); + lastdir = std::string((char*)(chrptr+1)); sendLastdir(lastdir.c_str()); break; } case FS_PUSH_FONT: { - int extid = d[1]; + int extid = chrptr[1]; if (FS_DEBUG) - printf("Client: Got push font %s, id: %d\n",(d+1), extid); + printf("Client: Got push font %s, id: %d\n",(chrptr+1), extid); - const char* filename = (const char*)(d+2); + const char* filename = (const char*)(chrptr+2); if (!pushSoundfont(filename, extid)) sendError("Could not load soundfont "); break; @@ -486,19 +520,19 @@ bool FluidSynth::sysex(int n, const unsigned char* d) break; } case FS_SOUNDFONT_CHANNEL_SET: { - sfChannelChange(*(d+1), *(d+2)); + sfChannelChange(*(chrptr+1), *(chrptr+2)); break; } case FS_INIT_DATA: { - parseInitData(n,d); + parseInitData(n - 2, chrptr); break; } case FS_SOUNDFONT_POP: - popSoundfont(*(d+1)); + popSoundfont(*(chrptr+1)); break; case FS_DRUMCHANNEL_SET: { - byte onoff = (*(d+1)); - byte channel = (*(d+2)); + byte onoff = (*(chrptr+1)); + byte channel = (*(chrptr+2)); channels[channel].drumchannel = onoff; if (FS_DEBUG) printf("Client: Set drumchannel on chan %d to %d\n",channel, onoff); @@ -506,7 +540,7 @@ bool FluidSynth::sysex(int n, const unsigned char* d) } default: if (FS_DEBUG) - printf("FluidSynth::sysex() : unknown sysex received: %d\n",*d); + printf("FluidSynth::sysex() : unknown sysex received: %d\n",*chrptr); break; } return false; @@ -647,6 +681,7 @@ bool FluidSynth::playNote(int channel, int pitch, int velo) void FluidSynth::sendSoundFontData() { int ndatalen = 2; //2 bytes for command and length + //int ndatalen = 4; // 4 bytes for header, command and length //Calculate length in chars of all strings in the soundfontstack in one string for (std::list<FluidSoundFont>::iterator it = stack.begin(); it != stack.end(); it++) { @@ -654,11 +689,16 @@ void FluidSynth::sendSoundFontData() ndatalen += FS_SFDATALEN; //unsigned char for ID } byte ndata[ndatalen]; - *ndata = FS_SEND_SOUNDFONTDATA; //The command + *(ndata) = FS_SEND_SOUNDFONTDATA; //The command *(ndata + 1) = (unsigned char)stack.size (); //Nr of Soundfonts + //*ndata = MUSE_SYNTH_SYSEX_MFG_ID; + //*(ndata + 1) = FLUIDSYNTH_UNIQUE_ID; + //*(ndata + 2) = FS_SEND_SOUNDFONTDATA; //The command + //*(ndata + 3) = (unsigned char)stack.size (); //Nr of Soundfonts // Copy the stuff to ndatalen: char* chunk_start = (char*)(ndata + 2); + //char* chunk_start = (char*)(ndata + 4); int chunk_len, name_len; for (std::list<FluidSoundFont>::iterator it = stack.begin(); it != stack.end(); ++it) { name_len = strlen(it->name.c_str()) + 1; @@ -675,12 +715,18 @@ void FluidSynth::sendSoundFontData() //--------------------------------------------------------- void FluidSynth::sendChannelData() { - int chunk_size = 2; + ///int chunk_size = 2; + int const chunk_size = 2; int chdata_length = (chunk_size * FS_MAX_NR_OF_CHANNELS) +1 ; //Command and the 2 channels * 16 + //int chdata_length = (chunk_size * FS_MAX_NR_OF_CHANNELS) +3 ; // Header, command and the 2 channels * 16 byte chdata[chdata_length]; byte* chdptr; chdata[0] = FS_SEND_CHANNELINFO; + //chdata[0] = MUSE_SYNTH_SYSEX_MFG_ID; + //chdata[1] = FLUIDSYNTH_UNIQUE_ID; + //chdata[2] = FS_SEND_CHANNELINFO; chdptr = (chdata + 1); + //chdptr = (chdata + 3); for (int i=0; i<FS_MAX_NR_OF_CHANNELS; i++) { *(chdptr) = channels[i].font_extid; //Font external id *(chdptr+1) = i; //Channel nr @@ -690,10 +736,16 @@ void FluidSynth::sendChannelData() // Send drum channel info afterwards (later addition, not very neat, but works...) int drumchdata_length = FS_MAX_NR_OF_CHANNELS + 1; //1 byte for the command, one byte for each channel - byte drumchdata[drumchdata_length ]; - byte* drumchdataptr = drumchdata; + //int drumchdata_length = FS_MAX_NR_OF_CHANNELS + 3; // 2 bytes for header, 1 byte for the command, one byte for each channel + byte drumchdata[drumchdata_length]; *drumchdata = FS_SEND_DRUMCHANNELINFO; - + //drumchdata[0] = MUSE_SYNTH_SYSEX_MFG_ID; + //drumchdata[1] = FLUIDSYNTH_UNIQUE_ID; + //drumchdata[2] = FS_SEND_DRUMCHANNELINFO; + + byte* drumchdataptr = drumchdata; + //byte* drumchdataptr = drumchdata + 3; + for (int i=0; i<FS_MAX_NR_OF_CHANNELS; i++) { drumchdataptr++; *drumchdataptr = channels[i].drumchannel; @@ -986,9 +1038,14 @@ int FluidSynth::getControllerInfo(int id, const char** name, int* controller, in void FluidSynth::sendError(const char *errorMessage) { int len = 2 + strlen(errorMessage); + //int len = 4 + strlen(errorMessage); unsigned char data[len]; *data = FS_ERROR; + //data[0] = MUSE_SYNTH_SYSEX_MFG_ID; + //data[1] = FLUIDSYNTH_UNIQUE_ID; + //data[2] = FS_ERROR; memcpy(data + 1, errorMessage, len - 1); + //memcpy(data + 3, errorMessage, len - 3); sendSysex(len, data); } @@ -1041,9 +1098,14 @@ byte FluidSynth::getFontInternalIdByExtId(byte ext_id) void FluidSynth::sendLastdir(const char* lastdir) { int n = strlen(lastdir) + 2; + //int n = strlen(lastdir) + 4; byte d[n]; d[0] = FS_LASTDIR_CHANGE; + //d[0] = MUSE_SYNTH_SYSEX_MFG_ID; + //d[1] = FLUIDSYNTH_UNIQUE_ID; + //d[2] = FS_LASTDIR_CHANGE; memcpy(d+1,lastdir, strlen(lastdir)+1); + //memcpy(d+3,lastdir, strlen(lastdir)+1); MidiPlayEvent ev(0,0, ME_SYSEX, d, n); gui->writeEvent(ev); @@ -1289,7 +1351,7 @@ static bool mutexEnabled = false; static Mess* instantiate(int sr, QWidget*, QString* projectPathPtr, const char* name) { -printf("fluidsynth sampleRate %d\n", sr); + printf("fluidsynth sampleRate %d\n", sr); projPathPtr=projectPathPtr; if (!mutexEnabled) { diff --git a/muse2/synti/fluidsynth/fluidsynti.h b/muse2/synti/fluidsynth/fluidsynti.h index a371de9e..fde42396 100644 --- a/muse2/synti/fluidsynth/fluidsynti.h +++ b/muse2/synti/fluidsynth/fluidsynti.h @@ -20,6 +20,7 @@ //#include "libsynti/mpevent.h" #include "muse/mpevent.h" #include "muse/midictrl.h" +#include "common_defs.h" #define FS_DEBUG_DATA 0 //Turn on/off debug print of midi data sent to fluidsynth @@ -83,6 +84,9 @@ class FluidSynth : public Mess { void sfChannelChange(unsigned char font_id, unsigned char channel); void parseInitData(int n, const byte* d); + byte* initBuffer; + int initLen; + byte getFontInternalIdByExtId (byte channel); void debug(const char* msg) { if (FS_DEBUG) printf("Debug: %s\n",msg); } @@ -101,15 +105,17 @@ class FluidSynth : public Mess { public: FluidSynth(int sr, pthread_mutex_t *_Globalsfloader_mutex); - ~FluidSynth(); + virtual ~FluidSynth(); bool init(const char*); + // This is only a kludge required to support old songs' midistates. Do not use in any new synth. + virtual int oldMidiStateHeader(const unsigned char** data) const; virtual void processMessages(); virtual void process(float**, int, int); virtual bool playNote(int channel, int pitch, int velo); virtual bool sysex(int, const unsigned char*); virtual bool setController(int, int, int); void setController(int, int , int, bool); - virtual void getInitData(int*, const unsigned char**) const; + virtual void getInitData(int*, const unsigned char**); virtual const char* getPatchName(int, int, int, bool) const; virtual const MidiPatch* getPatchInfo(int i, const MidiPatch* patch) const; virtual int getControllerInfo(int, const char**, int*, int*, int*, int*) const; diff --git a/muse2/synti/libsynti/evdata.h.OLD b/muse2/synti/libsynti/evdata.h.OLD index 4e529bec..8c8b77c9 100644 --- a/muse2/synti/libsynti/evdata.h.OLD +++ b/muse2/synti/libsynti/evdata.h.OLD @@ -57,6 +57,8 @@ class EvData { } } void setData(const unsigned char* p, int l) { + if(data) + delete[] data; // p4.0.27 data = new unsigned char[l]; memcpy(data, p, l); dataLen = l; diff --git a/muse2/synti/libsynti/mess.h b/muse2/synti/libsynti/mess.h index bf9ad0de..81a3fe96 100644 --- a/muse2/synti/libsynti/mess.h +++ b/muse2/synti/libsynti/mess.h @@ -37,6 +37,10 @@ struct MidiPatch { // Mess // MusE experimental software synth // Instance virtual interface class +// NOTICE: If implementing sysex support, be sure to make a unique ID and use +// it to filter out unrecognized sysexes. Headers should be constructed as: +// MUSE_SYNTH_SYSEX_MFG_ID The MusE SoftSynth Manufacturer ID byte (0x7C) found in midi.h +// 0xNN The synth's unique ID byte //--------------------------------------------------------- class Mess { @@ -49,6 +53,9 @@ class Mess { Mess(int channels); virtual ~Mess(); + // This is only a kludge required to support old songs' midistates. Do not use in any new synth. + virtual int oldMidiStateHeader(const unsigned char** /*data*/) const { return 0; } + int channels() const { return _channels; } int sampleRate() const { return _sampleRate; } void setSampleRate(int r) { _sampleRate = r; } @@ -62,9 +69,9 @@ class Mess { virtual bool processEvent(const MidiPlayEvent&); virtual bool setController(int, int, int) { return false; } virtual bool playNote(int, int, int) { return false; } - virtual bool sysex(int, const unsigned char*) { return false; } + virtual bool sysex(int, const unsigned char*) { return false; } - virtual void getInitData(int*, const unsigned char**) const {} + virtual void getInitData(int* n, const unsigned char**) /*const*/ { *n = 0; } // No const: Synths may need to allocate member pointers. p4.0.27 Tim virtual int getControllerInfo(int, const char**, int*, int*, int*, int*) const {return 0;} virtual const char* getPatchName(int, int, int, bool) const { return "?"; } virtual const MidiPatch* getPatchInfo(int, const MidiPatch*) const { return 0; } diff --git a/muse2/synti/organ/common_defs.h b/muse2/synti/organ/common_defs.h new file mode 100644 index 00000000..31d09081 --- /dev/null +++ b/muse2/synti/organ/common_defs.h @@ -0,0 +1,8 @@ +#ifndef __ORGAN_UNIQUE_ID_H +#define __ORGAN_UNIQUE_ID_H + +// Make sure this number is unique among all the MESS synths. +#define ORGAN_UNIQUE_ID 1 + +#endif + diff --git a/muse2/synti/organ/organ.cpp b/muse2/synti/organ/organ.cpp index 56fb4db1..f3bb3b9f 100644 --- a/muse2/synti/organ/organ.cpp +++ b/muse2/synti/organ/organ.cpp @@ -17,6 +17,7 @@ //#include "libsynti/mpevent.h" #include "muse/mpevent.h" +//#include "common_defs.h" #include "organ.h" #include "organgui.h" @@ -76,7 +77,8 @@ double Organ::cb2amp(int cb) Organ::Organ(int sr) : Mess(1) { - idata = new int[NUM_CONTROLLER]; + //idata = new int[NUM_CONTROLLER]; + idata = new unsigned char[3 + NUM_CONTROLLER * sizeof(int)]; setSampleRate(sr); gui = 0; @@ -131,7 +133,8 @@ Organ::~Organ() { if (gui) delete gui; - delete idata; + //delete idata; + delete [] idata; // p4.0.27 --useCount; if (useCount == 0) { delete[] g_pulse_table; @@ -170,6 +173,13 @@ bool Organ::init(const char* name) return false; } +int Organ::oldMidiStateHeader(const unsigned char** data) const +{ + unsigned char const d[3] = {MUSE_SYNTH_SYSEX_MFG_ID, ORGAN_UNIQUE_ID, INIT_DATA_CMD}; + *data = &d[0]; + return 3; +} + //--------------------------------------------------------- // processMessages // Called from host always, even if output path is unconnected. @@ -192,7 +202,11 @@ void Organ::processMessages() sendEvent(ev); } else + { + #ifdef ORGAN_DEBUG printf("Organ::process(): unknown event\n"); + #endif + } } } @@ -404,7 +418,9 @@ bool Organ::playNote(int channel, int pitch, int velo) voices[i].harm5_accum = 0; return false; } + #ifdef ORGAN_DEBUG printf("organ: voices overflow!\n"); + #endif return false; } @@ -424,7 +440,11 @@ void Organ::noteoff(int channel, int pitch) } } if (!found) + { + #ifdef ORGAN_DEBUG printf("Organ: noteoff %d:%d not found\n", channel, pitch); + #endif + } } //--------------------------------------------------------- @@ -515,7 +535,9 @@ void Organ::setController(int ctrl, int data) setController(0, synthCtrl[i].num, synthCtrl[i].val); break; default: + #ifdef ORGAN_DEBUG fprintf(stderr, "Organ:set unknown Ctrl 0x%x to 0x%x\n", ctrl, data); + #endif return; } for (int i = 0; i < NUM_CONTROLLER; ++i) { @@ -573,37 +595,59 @@ bool Organ::setController(int channel, int ctrl, int data) //--------------------------------------------------------- bool Organ::sysex(int n, const unsigned char* data) - { +{ #ifdef ORGAN_DEBUG printf("Organ: sysex\n"); #endif - if (unsigned(n) != (NUM_INIT_CONTROLLER * sizeof(int))) { - printf("Organ: unknown sysex\n"); - return false; - } - int* s = (int*) data; - for (int i = 0; i < NUM_INIT_CONTROLLER; ++i) { - int val = *s++; - #ifdef ORGAN_DEBUG - printf("Organ: sysex before setController num:%d val:%d\n", synthCtrl[i].num, val); - #endif - setController(0, synthCtrl[i].num, val); + + // p4.0.27 + if(unsigned(n) == (3 + NUM_INIT_CONTROLLER * sizeof(int))) + { + if (data[0] == MUSE_SYNTH_SYSEX_MFG_ID) // MusE Soft Synth + { + if (data[1] == ORGAN_UNIQUE_ID) // ORGAN + { + if (data[2] == INIT_DATA_CMD) // Initialization + { + int* s = (int*)(data + 3); + for (int i = 0; i < NUM_INIT_CONTROLLER; ++i) + { + int val = *s++; + #ifdef ORGAN_DEBUG + printf("Organ: sysex before setController num:%d val:%d\n", synthCtrl[i].num, val); + #endif + setController(0, synthCtrl[i].num, val); + } + return false; } - return false; + } + } } - + #ifdef ORGAN_DEBUG + printf("Organ: unknown sysex\n"); + #endif + return false; +} //--------------------------------------------------------- // getInitData //--------------------------------------------------------- -void Organ::getInitData(int* n, const unsigned char**p) const - { - int* d = idata; +//void Organ::getInitData(int* n, const unsigned char**p) const +void Organ::getInitData(int* n, const unsigned char**p) +{ + // p4.0.27 + *n = 3 + NUM_INIT_CONTROLLER * sizeof(int); + idata[0] = MUSE_SYNTH_SYSEX_MFG_ID; // MusE Soft Synth + idata[1] = ORGAN_UNIQUE_ID; // ORGAN + idata[2] = INIT_DATA_CMD; // Initialization + int* d = (int*)&idata[3]; + + //int* d = idata; for (int i = 0; i < NUM_INIT_CONTROLLER; ++i) *d++ = synthCtrl[i].val; - *n = NUM_INIT_CONTROLLER * sizeof(int); // sizeof(idata); + //*n = NUM_INIT_CONTROLLER * sizeof(int); // sizeof(idata); *p = (unsigned char*)idata; - } +} //--------------------------------------------------------- // MESS diff --git a/muse2/synti/organ/organ.h b/muse2/synti/organ/organ.h index 60fee98a..f859ea8c 100644 --- a/muse2/synti/organ/organ.h +++ b/muse2/synti/organ/organ.h @@ -15,9 +15,11 @@ #include "muse/midictrl.h" #include "libsynti/mess.h" +#include "common_defs.h" #define RESOLUTION (16384*2) #define VOICES 128 // max polyphony +#define INIT_DATA_CMD 1 class OrganGui; @@ -149,7 +151,8 @@ class Organ : public Mess { static unsigned freq256[128]; static double cb2amp(int cb); - int* idata; // buffer for init data + //int* idata; // buffer for init data + unsigned char* idata; // buffer for init data bool brass, flute, reed; int attack0, attack1; @@ -180,7 +183,10 @@ class Organ : public Mess { virtual bool setController(int channel, int ctrl, int val); virtual int getControllerInfo(int, const char**, int*, int*, int*, int*) const; - virtual void getInitData(int*, const unsigned char**) const; + //virtual void getInitData(int*, const unsigned char**) const; + virtual void getInitData(int*, const unsigned char**); + // This is only a kludge required to support old songs' midistates. Do not use in any new synth. + virtual int oldMidiStateHeader(const unsigned char** data) const; //virtual bool guiVisible() const; //virtual void showGui(bool); @@ -193,7 +199,7 @@ class Organ : public Mess { virtual bool sysex(int, const unsigned char*); static SynthCtrl synthCtrl[]; Organ(int sampleRate); - ~Organ(); + virtual ~Organ(); bool init(const char* name); }; diff --git a/muse2/synti/organ/organgui.cpp b/muse2/synti/organ/organgui.cpp index b10ab01d..a25a8de9 100644 --- a/muse2/synti/organ/organgui.cpp +++ b/muse2/synti/organ/organgui.cpp @@ -19,6 +19,7 @@ #include <QSocketNotifier> #include <QSpinBox> +#include "common_defs.h" #include "organgui.h" #include "muse/midi.h" #include "muse/midictrl.h" @@ -134,7 +135,9 @@ void OrganGui::setParam(int param, int val) param &= 0xfff; if (param >= int(sizeof(dctrl)/sizeof(*dctrl))) { + #ifdef ORGANGUI_DEBUG fprintf(stderr, "OrganGui: set unknown Ctrl 0x%x to 0x%x\n", param, val); + #endif return; } SynthGuiCtrl* ctrl = &dctrl[param]; @@ -172,7 +175,11 @@ void OrganGui::processEvent(const MidiPlayEvent& ev) if (ev.type() == ME_CONTROLLER) setParam(ev.dataA(), ev.dataB()); else + { + #ifdef ORGANGUI_DEBUG printf("OrganGui::illegal event type received\n"); + #endif + } } //--------------------------------------------------------- diff --git a/muse2/synti/s1/s1.cpp b/muse2/synti/s1/s1.cpp index c44676ce..9c466b4a 100644 --- a/muse2/synti/s1/s1.cpp +++ b/muse2/synti/s1/s1.cpp @@ -21,6 +21,9 @@ #include "libsynti/mono.h" #define RESOLUTION 16384 +// Make sure this number is unique among all the MESS synths. +#define S1_UNIQUE_ID 6 + //--------------------------------------------------------- // S1 - simple mono demo synthesizer @@ -53,7 +56,7 @@ class S1 : public MessMono { public: S1(); - ~S1(); + virtual ~S1(); }; float* S1::wave_table; diff --git a/muse2/synti/simpledrums2/common.h b/muse2/synti/simpledrums2/common.h index e4763540..f31ca7ce 100644 --- a/muse2/synti/simpledrums2/common.h +++ b/muse2/synti/simpledrums2/common.h @@ -16,11 +16,11 @@ #define SS_VERSIONSTRING "1.0" -#define SS_DEBUG 0 +#define SS_DEBUG 0 #define SS_DEBUG_INIT 0 #define SS_TRACE_FUNC 0 #define SS_DEBUG_MIDI 0 -#define SS_DEBUG_LADSPA 0 +#define SS_DEBUG_LADSPA 0 #define SS_DEBUG_STATE 0 #define SS_DBG(string) if (SS_DEBUG) fprintf(stderr, "%s:%d:%s: %s\n", __FILE__ , __LINE__ , __PRETTY_FUNCTION__, string); @@ -34,6 +34,7 @@ #define SS_DBG_LADSPA2(string1, string2) if (SS_DEBUG_LADSPA) fprintf(stderr, "%s:%d:%s: %s: %s\n", __FILE__ , __LINE__ , __PRETTY_FUNCTION__, string1, string2); #define SS_SYSEX_INIT_DATA_VERSION 1 +#define SS_SYSEX_EFFECT_INIT_DATA_VERSION 2 // Added Jun 15 2011. Original value was SS_SYSEX_INIT_DATA_VERSION (1). p4.0.27 Tim. #define SS_NR_OF_CHANNELS 16 #define SS_AUDIO_CHANNELS 2 diff --git a/muse2/synti/simpledrums2/common_defs.h b/muse2/synti/simpledrums2/common_defs.h new file mode 100644 index 00000000..b3745a1d --- /dev/null +++ b/muse2/synti/simpledrums2/common_defs.h @@ -0,0 +1,8 @@ +#ifndef __SIMPLEDRUMS_UNIQUE_ID_H +#define __SIMPLEDRUMS_UNIQUE_ID_H + +// Make sure this number is unique among all the MESS synths. +#define SIMPLEDRUMS_UNIQUE_ID 4 + +#endif + diff --git a/muse2/synti/simpledrums2/simpledrums.cpp b/muse2/synti/simpledrums2/simpledrums.cpp index f14a0627..80f61102 100644 --- a/muse2/synti/simpledrums2/simpledrums.cpp +++ b/muse2/synti/simpledrums2/simpledrums.cpp @@ -5,6 +5,7 @@ // // // Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004 +// Contributer: (C) Copyright 2011 Tim E. Real (terminator356 at users.sourceforge.net) // // Copyright: See COPYING file that comes with this distribution // @@ -14,6 +15,7 @@ #include "muse/midi.h" //#include "libsynti/mpevent.h" #include "muse/mpevent.h" +//#include "common_defs.h" #include "simpledrums.h" #include <samplerate.h> @@ -82,6 +84,9 @@ SimpleSynth::SimpleSynth(int sr) SS_samplerate = sr; SS_initPlugins(); + initBuffer = 0; + initLen = 0; + simplesynth_ptr = this; master_vol = 100.0 / SS_MASTER_VOLUME_QUOT; master_vol_ctrlval = 100; @@ -203,6 +208,9 @@ SimpleSynth::~SimpleSynth() { SS_TRACE_IN + if(gui) + delete gui; // p4.0.27 + // Cleanup channels and samples: SS_DBG("Cleaning up sample data"); for (int i=0; i<SS_NR_OF_CHANNELS; i++) { @@ -233,9 +241,21 @@ SimpleSynth::~SimpleSynth() SS_DBG("Deleting process buffer"); delete[] processBuffer[0]; delete[] processBuffer[1]; + if (initBuffer) + { + SS_DBG("Deleting init buffer"); + delete [] initBuffer; + } SS_TRACE_OUT } +int SimpleSynth::oldMidiStateHeader(const unsigned char** data) const +{ + unsigned char const d[2] = {MUSE_SYNTH_SYSEX_MFG_ID, SIMPLEDRUMS_UNIQUE_ID}; + *data = &d[0]; + return 2; +} + //--------------------------------------------------------- // nativeGuiVisible /*! @@ -299,7 +319,8 @@ bool SimpleSynth::playNote(int /*channel*/, int pitch, int velo) } else { //Note off: - if (channels[ch].noteoff_ignore) { + ///if (channels[ch].noteoff_ignore) { + if (!channels[ch].noteoff_ignore) { // p4.0.27 if (SS_DEBUG_MIDI) { printf("Note off on channel %d\n", ch); } @@ -497,8 +518,17 @@ bool SimpleSynth::setController(int channel, int id, int val, bool /*fromGui*/) \return false for ok, true for not ok */ //--------------------------------------------------------- -bool SimpleSynth::sysex(int /*len*/, const unsigned char* data) +bool SimpleSynth::sysex(int len, const unsigned char* d) + { + if(len < 3 || d[0] != MUSE_SYNTH_SYSEX_MFG_ID + || d[1] != SIMPLEDRUMS_UNIQUE_ID) { + if (SS_DEBUG_MIDI) + printf("MusE SimpleDrums: Unknown sysex header\n"); + return false; + } + + const unsigned char* data = d + 2; SS_TRACE_IN int cmd = data[0]; switch (cmd) { @@ -565,20 +595,23 @@ bool SimpleSynth::sysex(int /*len*/, const unsigned char* data) { int initdata_len = 0; const byte* tmp_initdata = NULL; - byte* event_data = NULL; + ///byte* event_data = NULL; getInitData(&initdata_len, &tmp_initdata); - int totlen = initdata_len + 1; - - event_data = new byte[initdata_len + 1]; - event_data[0] = SS_SYSEX_SEND_INIT_DATA; - memcpy(event_data + 1, tmp_initdata, initdata_len); - delete[] tmp_initdata; - tmp_initdata = NULL; - - MidiPlayEvent ev(0, 0, ME_SYSEX, event_data, totlen); + ///int totlen = initdata_len + 1; + + ///event_data = new byte[initdata_len + 1]; + ///event_data[0] = SS_SYSEX_SEND_INIT_DATA; + *((byte*)(tmp_initdata) + 1) = SS_SYSEX_SEND_INIT_DATA; // Re-use the synth ID byte as the command byte. + + ///memcpy(event_data + 1, tmp_initdata, initdata_len); + ///delete[] tmp_initdata; + ///tmp_initdata = NULL; + + ///MidiPlayEvent ev(0, 0, ME_SYSEX, event_data, totlen); + MidiPlayEvent ev(0, 0, ME_SYSEX, tmp_initdata + 1, initdata_len - 1); // Strip MFG ID. gui->writeEvent(ev); - delete[] event_data; + ///delete[] event_data; break; } @@ -639,7 +672,7 @@ const MidiPatch* SimpleSynth::getPatchInfo(int index, const MidiPatch* patch) co \return 0 when done, otherwise return next desired controller index */ //--------------------------------------------------------- -int SimpleSynth::getControllerInfo(int index, const char** name, int* controller, int* min, int* max) +int SimpleSynth::getControllerInfo(int index, const char** name, int* controller, int* min, int* max, int* initval) const { SS_TRACE_IN if (index >= SS_NR_OF_CONTROLLERS) { @@ -652,7 +685,9 @@ int SimpleSynth::getControllerInfo(int index, const char** name, int* controller *min = controllers[index].min; *max = controllers[index].max; - if (SS_DEBUG_MIDI) { + *initval = 0; // p4.0.27 FIXME NOTE TODO + + if (SS_DEBUG_MIDI) { printf("setting controller info: index %d name %s controller %d min %d max %d\n", index, *name, *controller, *min, *max); } SS_TRACE_OUT @@ -660,6 +695,31 @@ int SimpleSynth::getControllerInfo(int index, const char** name, int* controller } //--------------------------------------------------------- +// processMessages +// Called from host always, even if output path is unconnected. +//--------------------------------------------------------- + +void SimpleSynth::processMessages() +{ + //Process messages from the gui + while (gui->fifoSize()) { + MidiPlayEvent ev = gui->readEvent(); + if (ev.type() == ME_SYSEX) { + sysex(ev.len(), ev.data()); + sendEvent(ev); + } + else if (ev.type() == ME_CONTROLLER) { + setController(ev.channel(), ev.dataA(), ev.dataB(), true); + sendEvent(ev); + } + else { + if (SS_DEBUG) + printf("SimpleSynth::process(): unknown event, type: %d\n", ev.type()); + } + } +} + +//--------------------------------------------------------- // process /*! \fn SimpleSynth::process @@ -671,6 +731,7 @@ int SimpleSynth::getControllerInfo(int index, const char** name, int* controller //--------------------------------------------------------- void SimpleSynth::process(float** out, int offset, int len) { + /* //Process messages from the gui while (gui->fifoSize()) { MidiPlayEvent ev = gui->readEvent(); @@ -687,7 +748,8 @@ void SimpleSynth::process(float** out, int offset, int len) printf("SimpleSynth::process(): unknown event, type: %d\n", ev.type()); } } - + */ + if (synth_state == SS_RUNNING) { //Temporary mix-doubles @@ -843,6 +905,19 @@ bool SimpleSynth::init(const char* name) } //--------------------------------------------------------- +// getInitBuffer +//--------------------------------------------------------- +void SimpleSynth::setupInitBuffer(int len) +{ + if (len > initLen) { + if (initBuffer) + delete [] initBuffer; + initBuffer = new byte[len]; + initLen = len; + } +} + +//--------------------------------------------------------- /*! \fn SimpleSynth::getInitData \brief Data for reinitialization of SimpleSynth when loading project @@ -850,7 +925,8 @@ bool SimpleSynth::init(const char* name) \param data - data that is sent as a sysex to the synth on reload of project */ //--------------------------------------------------------- -void SimpleSynth::getInitData(int* n, const unsigned char** data) +//void SimpleSynth::getInitData(int* n, const unsigned char** data) const +void SimpleSynth::getInitData(int* n, const unsigned char** data) { SS_TRACE_IN // Calculate length of data @@ -877,7 +953,10 @@ void SimpleSynth::getInitData(int* n, const unsigned char** data) int labelnamelen = plugin->label().size() + 2; len+=(namelen + labelnamelen); - len+=3; //1 byte for nr of parameters, 1 byte for return gain, 1 byte for effect on/off + ///len+=3; //1 byte for nr of parameters, 1 byte for return gain, 1 byte for effect on/off + // p4.0.27 Tim. + len+=6; //4 bytes for nr of parameters, 1 byte for return gain, 1 byte for effect on/off + len+=sendEffects[i].nrofparameters; // 1 byte for each parameter value } else { @@ -885,17 +964,29 @@ void SimpleSynth::getInitData(int* n, const unsigned char** data) } } + len += 2; // For header. + // First, SS_SYSEX_INIT_DATA - byte* buffer = new byte[len]; - memset(buffer, 0, len); - buffer[0] = SS_SYSEX_INIT_DATA; - buffer[1] = SS_SYSEX_INIT_DATA_VERSION; + + ///byte* buffer = new byte[len]; + setupInitBuffer(len); + + memset(initBuffer, 0, len); + //initBuffer[0] = SS_SYSEX_INIT_DATA; + //initBuffer[1] = SS_SYSEX_INIT_DATA_VERSION; + initBuffer[0] = MUSE_SYNTH_SYSEX_MFG_ID; + initBuffer[1] = SIMPLEDRUMS_UNIQUE_ID; + initBuffer[2] = SS_SYSEX_INIT_DATA; + initBuffer[3] = SS_SYSEX_INIT_DATA_VERSION; if (SS_DEBUG_INIT) { printf("Length of init data: %d\n", len); - printf("buffer[0] - SS_SYSEX_INIT_DATA: %d\n", SS_SYSEX_INIT_DATA); - printf("buffer[1] - SS_SYSEX_INIT_DATA_VERSION: %d\n", SS_SYSEX_INIT_DATA_VERSION); + //printf("initBuffer[0] - SS_SYSEX_INIT_DATA: %d\n", SS_SYSEX_INIT_DATA); + //printf("initBuffer[1] - SS_SYSEX_INIT_DATA_VERSION: %d\n", SS_SYSEX_INIT_DATA_VERSION); + printf("initBuffer[2] - SS_SYSEX_INIT_DATA: %d\n", SS_SYSEX_INIT_DATA); + printf("initBuffer[3] - SS_SYSEX_INIT_DATA_VERSION: %d\n", SS_SYSEX_INIT_DATA_VERSION); } - int i = 2; + //int i = 2; + int i = 4; // All channels: // 0 - volume ctrlval (0-127) // 1 - pan (0-127) @@ -905,71 +996,75 @@ void SimpleSynth::getInitData(int* n, const unsigned char** data) // 8 - len of filename, n // 9 - 9+n - filename for (int ch=0; ch<SS_NR_OF_CHANNELS; ch++) { - buffer[i] = (byte) channels[ch].volume_ctrlval; - buffer[i+1] = (byte) channels[ch].pan; - buffer[i+2] = (byte) channels[ch].noteoff_ignore; - buffer[i+3] = (byte) channels[ch].channel_on; - buffer[i+4] = (byte) round(channels[ch].sendfxlevel[0] * 127.0); - buffer[i+5] = (byte) round(channels[ch].sendfxlevel[1] * 127.0); - buffer[i+6] = (byte) round(channels[ch].sendfxlevel[2] * 127.0); - buffer[i+7] = (byte) round(channels[ch].sendfxlevel[3] * 127.0); + initBuffer[i] = (byte) channels[ch].volume_ctrlval; + initBuffer[i+1] = (byte) channels[ch].pan; + initBuffer[i+2] = (byte) channels[ch].noteoff_ignore; + initBuffer[i+3] = (byte) channels[ch].channel_on; + initBuffer[i+4] = (byte) round(channels[ch].sendfxlevel[0] * 127.0); + initBuffer[i+5] = (byte) round(channels[ch].sendfxlevel[1] * 127.0); + initBuffer[i+6] = (byte) round(channels[ch].sendfxlevel[2] * 127.0); + initBuffer[i+7] = (byte) round(channels[ch].sendfxlevel[3] * 127.0); if (SS_DEBUG_INIT) { printf("Channel %d:\n", ch); - printf("buffer[%d] - channels[ch].volume_ctrlval = \t%d\n", i, channels[ch].volume_ctrlval); - printf("buffer[%d] - channels[ch].pan = \t\t%d\n", i+1, channels[ch].pan); - printf("buffer[%d] - channels[ch].noteoff_ignore = \t%d\n", i+2, channels[ch].noteoff_ignore ); - printf("buffer[%d] - channels[ch].channel_on = \t%d\n", i+3, channels[ch].channel_on); + printf("initBuffer[%d] - channels[ch].volume_ctrlval = \t%d\n", i, channels[ch].volume_ctrlval); + printf("initBuffer[%d] - channels[ch].pan = \t\t%d\n", i+1, channels[ch].pan); + printf("initBuffer[%d] - channels[ch].noteoff_ignore = \t%d\n", i+2, channels[ch].noteoff_ignore ); + printf("initBuffer[%d] - channels[ch].channel_on = \t%d\n", i+3, channels[ch].channel_on); for (int j= i+4; j < i+8; j++) { - printf("buffer[%d] - channels[ch].sendfxlevel[%d]= \t%d\n", j, j-i-4, (int)round(channels[ch].sendfxlevel[j-i-4] * 127.0)); + printf("initBuffer[%d] - channels[ch].sendfxlevel[%d]= \t%d\n", j, j-i-4, (int)round(channels[ch].sendfxlevel[j-i-4] * 127.0)); } } if (channels[ch].sample) { int filenamelen = strlen(channels[ch].sample->filename.c_str()) + 1; - buffer[i+8] = (byte) filenamelen; - memcpy((buffer+(i+9)), channels[ch].sample->filename.c_str(), filenamelen); + initBuffer[i+8] = (byte) filenamelen; + memcpy((initBuffer+(i+9)), channels[ch].sample->filename.c_str(), filenamelen); if (SS_DEBUG_INIT) { - printf("buffer[%d] - filenamelen: %d\n", i+8, filenamelen); - printf("buffer[%d] - buffer[%d] - filename: ", (i+9), (i+9) + filenamelen - 1); + printf("initBuffer[%d] - filenamelen: %d\n", i+8, filenamelen); + printf("initBuffer[%d] - initBuffer[%d] - filename: ", (i+9), (i+9) + filenamelen - 1); for (int j = i+9; j< i+9+filenamelen; j++) { - printf("%c",buffer[j]); + printf("%c",initBuffer[j]); } printf("\n"); } i+= (SS_NR_OF_CHANNEL_CONTROLLERS + 1 + filenamelen); } else { - buffer[i+8] = SS_NO_SAMPLE; + initBuffer[i+8] = SS_NO_SAMPLE; if (SS_DEBUG_INIT) { - printf("buffer[%d]: SS_NO_SAMPLE: - %d\n", i+8, SS_NO_SAMPLE); + printf("initBuffer[%d]: SS_NO_SAMPLE: - %d\n", i+8, SS_NO_SAMPLE); } i+= (SS_NR_OF_CHANNEL_CONTROLLERS + 1); } } if (SS_DEBUG_INIT) { - printf("buffer[%d]: Master vol: - %d\n", i, master_vol_ctrlval); + printf("initBuffer[%d]: Master vol: - %d\n", i, master_vol_ctrlval); } - buffer[i] = master_vol_ctrlval; - *(data) = buffer; *n = len; + initBuffer[i] = master_vol_ctrlval; + *(data) = initBuffer; *n = len; i++; //Send effects: - buffer[i] = SS_SYSEX_INIT_DATA_VERSION; //Just for check + + ///initBuffer[i] = SS_SYSEX_INIT_DATA_VERSION; //Just for check + // Jun 10 2011. Bumped version up from 1 (with its own ID). p4.0.27 Tim + initBuffer[i] = SS_SYSEX_EFFECT_INIT_DATA_VERSION; //Just for check + if (SS_DEBUG_INIT) { - printf("buffer[%d]: Control value, SS_SYSEX_INIT_DATA_VERSION\n", i); + printf("initBuffer[%d]: Control value, SS_SYSEX_EFFECT_INIT_DATA_VERSION = %d\n", i, SS_SYSEX_EFFECT_INIT_DATA_VERSION); } i++; for (int j=0; j<SS_NR_OF_SENDEFFECTS; j++) { if (sendEffects[j].plugin) { int labelnamelen = sendEffects[j].plugin->label().size() + 1; - buffer[i] = labelnamelen; - memcpy((buffer+i+1), sendEffects[j].plugin->label().toLatin1().constData(), labelnamelen); + initBuffer[i] = labelnamelen; + memcpy((initBuffer+i+1), sendEffects[j].plugin->label().toLatin1().constData(), labelnamelen); if (SS_DEBUG_INIT) { - printf("buffer[%d] - labelnamelen: %d\n", i, labelnamelen); - printf("buffer[%d] - buffer[%d] - filename: ", (i+1), (i+1) + labelnamelen - 1); + printf("initBuffer[%d] - labelnamelen: %d\n", i, labelnamelen); + printf("initBuffer[%d] - initBuffer[%d] - filename: ", (i+1), (i+1) + labelnamelen - 1); for (int k = i+1; k < i+1+labelnamelen; k++) { - printf("%c",buffer[k]); + printf("%c",initBuffer[k]); } printf("\n"); } @@ -977,45 +1072,55 @@ void SimpleSynth::getInitData(int* n, const unsigned char** data) i+=(labelnamelen + 1); int namelen = sendEffects[j].plugin->lib().size() + 1; - buffer[i] = namelen; - memcpy((buffer+i+1), sendEffects[j].plugin->lib().toLatin1().constData(), namelen); + initBuffer[i] = namelen; + memcpy((initBuffer+i+1), sendEffects[j].plugin->lib().toLatin1().constData(), namelen); if (SS_DEBUG_INIT) { - printf("buffer[%d] - libnamelen : %d\n", i, namelen); - printf("buffer[%d] - buffer[%d] - filename: ", (i+1), (i+1) + namelen - 1); + printf("initBuffer[%d] - libnamelen : %d\n", i, namelen); + printf("initBuffer[%d] - initBuffer[%d] - filename: ", (i+1), (i+1) + namelen - 1); for (int k = i+1; k < i+1+namelen; k++) { - printf("%c",buffer[k]); + printf("%c",initBuffer[k]); } printf("\n"); } i+=(namelen + 1); - buffer[i]=sendEffects[j].nrofparameters; + ///initBuffer[i]=sendEffects[j].nrofparameters; + // Jun 10 2011. Changed to 32 bit. p4.0.27 Tim. + *((unsigned*)&initBuffer[i]) = sendEffects[j].nrofparameters; if (SS_DEBUG_INIT) { - printf("buffer[%d]: sendEffects[%d].nrofparameters=%d\n", i, j, buffer[i]); + printf("initBuffer[%d]: sendEffects[%d].nrofparameters=%d\n", i, j, *((unsigned*)&initBuffer[i])); + } + ///i++; + i+=4; + + initBuffer[i]=sendEffects[j].retgain_ctrlval; + if (SS_DEBUG_INIT) { + printf("initBuffer[%d]: sendEffects[%d].retgain_ctrlval=%d\n", i, j, initBuffer[i]); } i++; - buffer[i]=sendEffects[j].retgain_ctrlval; + // Jun 10 2011. This one was missing. p4.0.27 Tim. + initBuffer[i] = sendEffects[j].state; if (SS_DEBUG_INIT) { - printf("buffer[%d]: sendEffects[%d].retgain_ctrlval=%d\n", i, j, buffer[i]); + printf("initBuffer[%d]: sendEffects[%d].state=%d\n", i, j, initBuffer[i]); } i++; for (int k=0; k<sendEffects[j].nrofparameters; k++) { //TODO: Convert to 127-scale - buffer[i] = sendEffects[j].plugin->getGuiControlValue(k); + initBuffer[i] = sendEffects[j].plugin->getGuiControlValue(k); if (SS_DEBUG_INIT) { - printf("buffer[%d]: sendEffects[%d].parameterval[%d]=%d\n", i, j, k, buffer[i]); + printf("initBuffer[%d]: sendEffects[%d].parameterval[%d]=%d\n", i, j, k, initBuffer[i]); } i++; } } // No plugin loaded: else { - buffer[i] = SS_NO_PLUGIN; + initBuffer[i] = SS_NO_PLUGIN; if (SS_DEBUG_INIT) { - printf("buffer[%d]: SS_NO_PLUGIN\n", i); + printf("initBuffer[%d]: SS_NO_PLUGIN\n", i); } i++; } @@ -1118,11 +1223,15 @@ void SimpleSynth::parseInitData(const unsigned char* data) ptr++; // Effects: - if (*(ptr) != SS_SYSEX_INIT_DATA_VERSION) { - fprintf(stderr, "Error loading init data - control byte not found. Skipping...\n"); + ///if (*(ptr) != SS_SYSEX_INIT_DATA_VERSION) { + int effver = *(ptr); + if (effver < 1 || effver > SS_SYSEX_EFFECT_INIT_DATA_VERSION) { + //if (SS_DEBUG_INIT) + fprintf(stderr, "Error loading init data - effect init version is from future or too old. Skipping...\n"); SS_TRACE_OUT return; } + ptr++; for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) { @@ -1149,9 +1258,14 @@ void SimpleSynth::parseInitData(const unsigned char* data) initSendEffect(i, libnametmp.c_str(), labelnametmp.c_str()); //initSendEffect(0, "cmt", "freeverb3"); - byte params = *(ptr); - byte retgain = *(ptr+1); - ptr+=2; + ///byte params = *(ptr); + unsigned params = (effver < 2) ? *(ptr) : *((unsigned*)ptr); // p4.0.27 + ptr+= (effver < 2) ? 1 : 4; + + ///byte retgain = *(ptr+1); + ///ptr+=2; + byte retgain = *(ptr); // p4.0.27 + ptr++; sendEffects[i].nrofparameters = params; @@ -1161,7 +1275,19 @@ void SimpleSynth::parseInitData(const unsigned char* data) MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_PLUGIN_RETURNLEVEL_CONTROLLER(i), retgain); gui->writeEvent(ev); - for (int j=0; j<params; j++) { + // Jun 10 2011. This one was missing. p4.0.27 Tim. + if(effver >= 2) + { + if (SS_DEBUG_INIT) + printf("buffer[%ld] - sendeffect[%d] state=%d\n", long(ptr-data), i, *(ptr)); + sendEffects[i].state = (SS_SendFXState) *(ptr); + MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_PLUGIN_ONOFF_CONTROLLER(i), sendEffects[i].state); + gui->writeEvent(ev); + ptr++; + } + + ///for (int j=0; j<params; j++) { + for (unsigned j=0; j<params; j++) { if (SS_DEBUG_INIT){ //wilyfoobar-2011-02-13 // arg2 :pointer diifference might be 64 bit (long long) on 64 bit machine, this requires cast to long @@ -1481,16 +1607,23 @@ void SimpleSynth::guiSendSampleLoaded(bool success, int ch, const char* filename { SS_TRACE_IN int len = strlen(filename) + 3; //2 + filenamelen + 1; + //int len = strlen(filename) + 3 + 2; //2 + filenamelen + 1, + 2 for header; byte out[len]; + //out[0] = MUSE_SYNTH_SYSEX_MFG_ID; + //out[1] = SIMPLEDRUMS_UNIQUE_ID; if (success) { out[0] = SS_SYSEX_LOAD_SAMPLE_OK; + //out[2] = SS_SYSEX_LOAD_SAMPLE_OK; } else { out[0] = SS_SYSEX_LOAD_SAMPLE_ERROR; + //out[2] = SS_SYSEX_LOAD_SAMPLE_ERROR; } out[1] = ch; + //out[3] = ch; memcpy(out+2, filename, strlen(filename)+1); + //memcpy(out+4, filename, strlen(filename)+1); MidiPlayEvent ev(0, 0, ME_SYSEX, out, len); gui->writeEvent(ev); SS_TRACE_OUT @@ -1504,8 +1637,13 @@ void SimpleSynth::guiSendError(const char* errorstring) { SS_TRACE_IN byte out[strlen(errorstring)+2]; + //byte out[strlen(errorstring)+4]; + //out[0] = MUSE_SYNTH_SYSEX_MFG_ID; + //out[1] = SIMPLEDRUMS_UNIQUE_ID; out[0] = SS_SYSEX_ERRORMSG; + //out[2] = SS_SYSEX_ERRORMSG; memcpy(out+1, errorstring, strlen(errorstring) +1); + //memcpy(out+3, errorstring, strlen(errorstring) +1); SS_TRACE_OUT } @@ -1590,15 +1728,24 @@ bool SimpleSynth::initSendEffect(int id, QString lib, QString name) //TODO: cleanup if failed } } + //Notify gui - int len = 3; + ///int len = 3; + int len = 2 + 4; // Char is not enough for many plugins. Was causing crash. Changed to 32 bits. p4.0.27 Tim. + //int len = 5; byte out[len]; out[0] = SS_SYSEX_LOAD_SENDEFFECT_OK; out[1] = id; + //out[0] = MUSE_SYNTH_SYSEX_MFG_ID; + //out[1] = SIMPLEDRUMS_UNIQUE_ID; + //out[2] = SS_SYSEX_LOAD_SENDEFFECT_OK; + //out[3] = id; int j=0; for (iPlugin i = plugins.begin(); i!=plugins.end(); i++, j++) { if ((*i)->lib() == plugin->lib() && (*i)->label() == plugin->label()) { - out[2] = j; + ///out[2] = j; + //out[4] = j; + *((unsigned*)(out + 2)) = j; MidiPlayEvent ev(0, 0, ME_SYSEX, out, len); gui->writeEvent(ev); } @@ -1638,9 +1785,15 @@ void SimpleSynth::cleanupPlugin(int id) sendEffects[id].plugin = 0; byte d[2]; + //byte d[4]; d[0] = SS_SYSEX_CLEAR_SENDEFFECT_OK; d[1] = id; + //d[0] = MUSE_SYNTH_SYSEX_MFG_ID; + //d[1] = SIMPLEDRUMS_UNIQUE_ID; + //d[2] = SS_SYSEX_CLEAR_SENDEFFECT_OK; + //d[3] = id; MidiPlayEvent ev(0, 0, ME_SYSEX, d, 2); + //MidiPlayEvent ev(0, 0, ME_SYSEX, d, 4); gui->writeEvent(ev); SS_TRACE_OUT } @@ -1694,11 +1847,19 @@ void SimpleSynth::guiUpdateFxParameter(int fxid, int param, float val) } byte d[4]; + //byte d[6]; d[0] = SS_SYSEX_SET_PLUGIN_PARAMETER_OK; d[1] = fxid; d[2] = param; d[3] = intval; + //d[0] = MUSE_SYNTH_SYSEX_MFG_ID; + //d[1] = SIMPLEDRUMS_UNIQUE_ID; + //d[2] = SS_SYSEX_SET_PLUGIN_PARAMETER_OK; + //d[3] = fxid; + //d[4] = param; + //d[5] = intval; MidiPlayEvent ev(0, 0, ME_SYSEX, d, 4); + //MidiPlayEvent ev(0, 0, ME_SYSEX, d, 6); gui->writeEvent(ev); SS_TRACE_OUT } @@ -1742,9 +1903,15 @@ void SimpleSynth::guiNotifySampleCleared(int ch) { SS_TRACE_IN byte d[2]; + //byte d[4]; d[0] = SS_SYSEX_CLEAR_SAMPLE_OK; d[1] = (byte) ch; + //d[0] = MUSE_SYNTH_SYSEX_MFG_ID; + //d[1] = SIMPLEDRUMS_UNIQUE_ID; + //d[2] = SS_SYSEX_CLEAR_SAMPLE_OK; + //d[3] = (byte) ch; MidiPlayEvent ev(0, 0, ME_SYSEX, d, 2); + //MidiPlayEvent ev(0, 0, ME_SYSEX, d, 4); gui->writeEvent(ev); SS_TRACE_OUT } diff --git a/muse2/synti/simpledrums2/simpledrums.h b/muse2/synti/simpledrums2/simpledrums.h index 58a5945e..f0339d6a 100644 --- a/muse2/synti/simpledrums2/simpledrums.h +++ b/muse2/synti/simpledrums2/simpledrums.h @@ -5,6 +5,7 @@ // // // Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004 +// Contributer: (C) Copyright 2011 Tim E. Real (terminator356 at users.sourceforge.net) // // Copyright: See COPYING file that comes with this distribution // @@ -15,6 +16,7 @@ #include <sndfile.h> #include "libsynti/mess.h" #include "common.h" +#include "common_defs.h" //#include "libsynti/mpevent.h" #include "muse/mpevent.h" #include "simpledrumsgui.h" @@ -124,11 +126,15 @@ class SimpleSynth : public Mess virtual bool sysex(int arg1, const unsigned char* arg2); virtual const char* getPatchName(int arg1, int arg2, int arg3) const; virtual const MidiPatch* getPatchInfo(int arg1, const MidiPatch* arg2) const; - virtual int getControllerInfo(int arg1, const char** arg2, int* arg3, int* arg4, int* arg5); + virtual int getControllerInfo(int arg1, const char** arg2, int* arg3, int* arg4, int* arg5, int* arg6) const; + virtual void processMessages(); virtual void process(float** data, int offset, int len); //virtual void showGui(bool arg1); virtual void showNativeGui(bool arg1); + ///virtual void getInitData(int*, const unsigned char**) const; virtual void getInitData(int*, const unsigned char**); + // This is only a kludge required to support old songs' midistates. Do not use in any new synth. + virtual int oldMidiStateHeader(const unsigned char** data) const; bool init(const char* name); void guiSendSampleLoaded(bool success, int ch, const char* filename); void guiSendError(const char* errorstring); @@ -139,6 +145,10 @@ class SimpleSynth : public Mess private: SimpleSynthGui* gui; + byte* initBuffer; + int initLen; + void setupInitBuffer(int len); + SS_Channel channels[SS_NR_OF_CHANNELS]; SS_Controller controllers[SS_NR_OF_CONTROLLERS]; bool setController(int channel, int id, int val, bool fromGui); diff --git a/muse2/synti/simpledrums2/simpledrumsgui.cpp b/muse2/synti/simpledrums2/simpledrumsgui.cpp index f90c1da8..7d314565 100644 --- a/muse2/synti/simpledrums2/simpledrumsgui.cpp +++ b/muse2/synti/simpledrums2/simpledrumsgui.cpp @@ -5,6 +5,7 @@ // // // Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004 +// Contributer: (C) Copyright 2011 Tim E. Real (terminator356 at users.sourceforge.net) // // Copyright: See COPYING file that comes with this distribution // @@ -19,6 +20,7 @@ #include <QLineEdit> #include <QMessageBox> +#include "common_defs.h" #include "simpledrumsgui.h" //#include "libsynti/mpevent.h" #include "muse/mpevent.h" @@ -85,10 +87,16 @@ SimpleSynthGui* simplesynthgui_ptr; */ QChannelSlider::QChannelSlider(Qt::Orientation orientation, int ch, QWidget* parent) : QSlider(orientation, parent) - { - channel = ch; - } +{ + channel = ch; +} +void QChannelSlider::sliderChange(SliderChange change) +{ + QSlider::sliderChange(change); + if(change == QAbstractSlider::SliderValueChange) + emit valueChanged(channel, value()); +} /*! \fn QChannelSlider::getChannel() @@ -110,6 +118,7 @@ void QChannelSlider::setChannel(int ch) /*! \fn QChannelSlider::setValue(int val) */ +/* void QChannelSlider::setValue(int val) { val = (val > 127 ? 127 : val); @@ -117,10 +126,32 @@ void QChannelSlider::setValue(int val) QSlider::setValue(val); emit valueChanged(channel, val); } +*/ + +QInvertedSlider::QInvertedSlider(Qt::Orientation o, QWidget* parent) + : QSlider(o, parent) +{ + setInvertedAppearance(true); // p4.0.27 +} + +void QInvertedSlider::sliderChange(SliderChange change) +{ + QSlider::sliderChange(change); + if(change == QAbstractSlider::SliderValueChange) + emit invertedValueChanged(value()); +} + +QInvertedChannelSlider::QInvertedChannelSlider(Qt::Orientation o, int channel, QWidget* parent) + : QChannelSlider(o, channel, parent) +{ + setInvertedAppearance(true); // p4.0.27 + //setInvertedControls(true); +} /*! \fn QInvertedChannelSlider::setValue(int val) */ +/* void QInvertedChannelSlider::setValue(int val) { int inverted = this->maximum() - val; @@ -129,10 +160,12 @@ void QInvertedChannelSlider::setValue(int val) QSlider::setValue(val); emit valueChanged(channel, inverted); } +*/ /*! \fn QInvertedSlider::setValue(int val) */ +/* void QInvertedSlider::setValue(int val) { int inverted = this->maximum() - val; @@ -141,7 +174,7 @@ void QInvertedSlider::setValue(int val) emit invertedValueChanged(inverted); QSlider::setValue(val); } - +*/ /*! \fn QChannelCheckbox::QChannelCheckbox(QWidget* parent, int ch) @@ -194,11 +227,20 @@ QChannelDial::QChannelDial(QWidget* parent, int ch, int fxid) /*! \fn QChannelSlider::setValue(int val) */ +/* void QChannelDial::setValue(int val) { QDial::setValue(val); emit valueChanged(channel, sendfxid, val); } +*/ + +void QChannelDial::sliderChange(SliderChange change) +{ + QDial::sliderChange(change); + if(change == QAbstractSlider::SliderValueChange) + emit valueChanged(channel, sendfxid, value()); +} /*! \fn SimpleSynthGui::SimpleSynthGui() @@ -236,10 +278,16 @@ SimpleSynthGui::SimpleSynthGui() inchnlLayout->addWidget(onOff[i]); connect(onOff[i], SIGNAL(channelState(int, bool)), SLOT(channelOnOff(int, bool))); - volumeSliders[i] = new QInvertedChannelSlider(Qt::Vertical, i, channelButtonGroups[i]); + ///volumeSliders[i] = new QInvertedChannelSlider(Qt::Vertical, i, channelButtonGroups[i]); + // By Tim. p4.0.27 Inverted was not correct type. Maybe was work in progress, rest of code was not converted yet? + volumeSliders[i] = new QChannelSlider(Qt::Vertical, i, channelButtonGroups[i]); + volumeSliders[i]->setMinimum(SS_VOLUME_MIN_VALUE); volumeSliders[i]->setMaximum(SS_VOLUME_MAX_VALUE); - volumeSliders[i]->setValue(SS_VOLUME_MAX_VALUE - SS_VOLUME_DEFAULT_VALUE); + + ///volumeSliders[i]->setValue(SS_VOLUME_MAX_VALUE - SS_VOLUME_DEFAULT_VALUE); + volumeSliders[i]->setValue(SS_VOLUME_DEFAULT_VALUE); // p4.0.27 + // volumeSliders[i]->setMinimumSize(SS_VOLSLDR_WIDTH, SS_VOLSLDR_LENGTH); volumeSliders[i]->setToolTip("Volume, channel " + QString::number(i + 1)); // setMinimumSize(SS_VOLSLDR_WIDTH, SS_VOLSLDR_LENGTH); @@ -310,13 +358,22 @@ SimpleSynthGui::SimpleSynthGui() QVBoxLayout* mbgLayout = new QVBoxLayout(masterButtonGroup); mbgLayout->setAlignment(Qt::AlignCenter); // masterButtonGroup->setMinimumSize(SS_BTNGRP_WIDTH, SS_BTNGRP_HEIGHT); - masterSlider = new QInvertedSlider(Qt::Vertical, masterButtonGroup); + + ///masterSlider = new QInvertedSlider(Qt::Vertical, masterButtonGroup); + // By Tim. p4.0.27 Inverted was not correct type. Maybe was work in progress, rest of code was not converted yet? + masterSlider = new QSlider(Qt::Vertical, masterButtonGroup); + masterSlider->setToolTip("Master volume"); mbgLayout->addWidget(masterSlider); masterSlider->setRange(0, 127); - masterSlider->setValue(SS_VOLUME_MAX_VALUE - (int)(SS_MASTERVOL_DEFAULT_VALUE*SS_VOLUME_MAX_VALUE)); + + ///masterSlider->setValue(SS_VOLUME_MAX_VALUE - (int)(SS_MASTERVOL_DEFAULT_VALUE*SS_VOLUME_MAX_VALUE)); + masterSlider->setValue((int)(SS_MASTERVOL_DEFAULT_VALUE*SS_VOLUME_MAX_VALUE)); // p4.0.27 + // masterSlider->setMinimumSize(SS_MASTERSLDR_WIDTH, SS_MASTERSLDR_HEIGHT); - connect(masterSlider, SIGNAL(invertedValueChanged(int)), SLOT(masterVolChanged(int))); + + ///connect(masterSlider, SIGNAL(invertedValueChanged(int)), SLOT(masterVolChanged(int))); + connect(masterSlider, SIGNAL(valueChanged(int)), SLOT(masterVolChanged(int))); // p4.0.27 //Main groupbox mainGroupBox = new QGroupBox(this); @@ -435,7 +492,10 @@ void SimpleSynthGui::processEvent(const MidiPlayEvent& ev) switch(id) { case SS_CHANNEL_CTRL_VOLUME: volumeSliders[ch]->blockSignals(true); - volumeSliders[ch]->setValue(SS_VOLUME_MAX_VALUE - val); + + ///volumeSliders[ch]->setValue(SS_VOLUME_MAX_VALUE - val); + volumeSliders[ch]->setValue(val); // p4.0.27 + volumeSliders[ch]->blockSignals(false); break; @@ -479,7 +539,10 @@ void SimpleSynthGui::processEvent(const MidiPlayEvent& ev) else if (id >= SS_FIRST_MASTER_CONTROLLER && id <= SS_LAST_MASTER_CONTROLLER) { if (id == SS_MASTER_CTRL_VOLUME) { masterSlider->blockSignals(true); - masterSlider->setValue(SS_MASTERVOL_MAX_VALUE - val); + + ///masterSlider->setValue(SS_MASTERVOL_MAX_VALUE - val); + masterSlider->setValue(val); // p4.0.27 + masterSlider->blockSignals(false); } } @@ -495,6 +558,13 @@ void SimpleSynthGui::processEvent(const MidiPlayEvent& ev) SS_PluginFront* pf = pluginGui->getPluginFront((unsigned)fxid); pf->setRetGain(val); } + // Plugin on/off: + else if (cmd == SS_PLUGIN_ONOFF) { // p4.0.27 + if (SS_DEBUG_MIDI) + printf("SimpleSynthGui::processEvent - fx onoff received: fxid: %d val: %d\n", fxid, val); + SS_PluginFront* pf = pluginGui->getPluginFront((unsigned)fxid); + pf->setOnOff(val); + } } } // @@ -502,6 +572,7 @@ void SimpleSynthGui::processEvent(const MidiPlayEvent& ev) // else if (ev.type() == ME_SYSEX) { byte* data = ev.data(); + //byte* data = d + 2; int cmd = *data; switch (cmd) { case SS_SYSEX_LOAD_SAMPLE_OK: { @@ -549,7 +620,8 @@ void SimpleSynthGui::processEvent(const MidiPlayEvent& ev) } int fxid = *(data+1); SS_PluginFront* pf = pluginGui->getPluginFront((unsigned)fxid); - pf->updatePluginValue(*(data+2)); + ///pf->updatePluginValue(*(data+2)); + pf->updatePluginValue( *((unsigned*)(data+2)) ); // p4.0.27 break; } @@ -711,13 +783,20 @@ void SimpleSynthGui::loadSampleDialogue(int channel) if (SS_DEBUG) printf("lastDir = %s\n", lastDir.toLatin1().constData()); - int l = filename.length() + 4; + //int l = filename.length() + 4; + int l = filename.length() + 6; byte d[l]; - d[0] = SS_SYSEX_LOAD_SAMPLE; - d[1] = (byte) channel; - d[2] = (byte) filename.length(); - memcpy(d+3, filename.toLatin1().constData(), filename.length()+1); + //d[0] = SS_SYSEX_LOAD_SAMPLE; + //d[1] = (byte) channel; + //d[2] = (byte) filename.length(); + d[0] = MUSE_SYNTH_SYSEX_MFG_ID; + d[1] = SIMPLEDRUMS_UNIQUE_ID; + d[2] = SS_SYSEX_LOAD_SAMPLE; + d[3] = (byte) channel; + d[4] = (byte) filename.length(); + //memcpy(d+3, filename.toLatin1().constData(), filename.length()+1); + memcpy(d+5, filename.toLatin1().constData(), filename.length()+1); sendSysex(d, l); } } @@ -730,10 +809,16 @@ void SimpleSynthGui::loadSampleDialogue(int channel) void SimpleSynthGui::clearSample(int ch) { if (sampleNameLineEdit[ch]->text().length() > 0) { //OK, we've got a live one here - byte d[2]; - d[0] = SS_SYSEX_CLEAR_SAMPLE; - d[1] = (byte) ch; - sendSysex(d, 2); + //byte d[2]; + byte d[4]; + //d[0] = SS_SYSEX_CLEAR_SAMPLE; + //d[1] = (byte) ch; + d[0] = MUSE_SYNTH_SYSEX_MFG_ID; + d[1] = SIMPLEDRUMS_UNIQUE_ID; + d[2] = SS_SYSEX_CLEAR_SAMPLE; + d[3] = (byte) ch; + //sendSysex(d, 2); + sendSysex(d, 4); sampleNameLineEdit[ch]->setText(""); } } @@ -751,12 +836,19 @@ void SimpleSynthGui::displayPluginGui() */ void SimpleSynthGui::loadEffectInvoked(int fxid, QString lib, QString label) { - int l = 4 + lib.length() + label.length(); + //int l = 4 + lib.length() + label.length(); + int l = 6 + lib.length() + label.length(); byte d[l]; - d[0] = SS_SYSEX_LOAD_SENDEFFECT; - d[1] = (byte) fxid; - memcpy (d+2, lib.toLatin1().constData(), lib.length()+1); - memcpy (d+3+lib.length(), label.toLatin1().constData(), label.length()+1); + //d[0] = SS_SYSEX_LOAD_SENDEFFECT; + //d[1] = (byte) fxid; + d[0] = MUSE_SYNTH_SYSEX_MFG_ID; + d[1] = SIMPLEDRUMS_UNIQUE_ID; + d[2] = SS_SYSEX_LOAD_SENDEFFECT; + d[3] = (byte) fxid; + //memcpy (d+2, lib.toLatin1().constData(), lib.length()+1); + //memcpy (d+3+lib.length(), label.toLatin1().constData(), label.length()+1); + memcpy (d+4, lib.toLatin1().constData(), lib.length()+1); + memcpy (d+5+lib.length(), label.toLatin1().constData(), label.length()+1); sendSysex(d, l); } @@ -784,10 +876,16 @@ void SimpleSynthGui::toggleEffectOnOff(int fxid, int state) */ void SimpleSynthGui::clearPlugin(int fxid) { - byte d[2]; - d[0] = SS_SYSEX_CLEAR_SENDEFFECT; - d[1] = fxid; - sendSysex(d, 2); + //byte d[2]; + byte d[4]; + //d[0] = SS_SYSEX_CLEAR_SENDEFFECT; + //d[1] = fxid; + d[0] = MUSE_SYNTH_SYSEX_MFG_ID; + d[1] = SIMPLEDRUMS_UNIQUE_ID; + d[2] = SS_SYSEX_CLEAR_SENDEFFECT; + d[3] = fxid; + //sendSysex(d, 2); + sendSysex(d, 4); } @@ -796,13 +894,19 @@ void SimpleSynthGui::clearPlugin(int fxid) */ void SimpleSynthGui::effectParameterChanged(int fxid, int parameter, int val) { - //printf("Gui: effectParameterChanged: %d %d %d\n", fxid, parameter, val); - int len = 4; + //int len = 4; + int len = 6; byte d[len]; - d[0] = SS_SYSEX_SET_PLUGIN_PARAMETER; - d[1] = (byte) fxid; - d[2] = (byte) parameter; - d[3] = (byte) val; + //d[0] = SS_SYSEX_SET_PLUGIN_PARAMETER; + //d[1] = (byte) fxid; + //d[2] = (byte) parameter; + //d[3] = (byte) val; + d[0] = MUSE_SYNTH_SYSEX_MFG_ID; + d[1] = SIMPLEDRUMS_UNIQUE_ID; + d[2] = SS_SYSEX_SET_PLUGIN_PARAMETER; + d[3] = (byte) fxid; + d[4] = (byte) parameter; + d[5] = (byte) val; sendSysex(d, len); } @@ -826,7 +930,9 @@ void SimpleSynthGui::aboutButtonClicked() { QString caption = "SimpleDrums ver"; caption+= SS_VERSIONSTRING; - QString text = caption + "\n\n(C) Copyright 2000-2004 Mathias Lundgren (lunar_shuttle@users.sf.net), Werner Schweer\nPublished under the GNU Public License"; + ///QString text = caption + "\n\n(C) Copyright 2000-2004 Mathias Lundgren (lunar_shuttle@users.sf.net), Werner Schweer\nPublished under the GNU Public License"; + QString text = caption + "\n\n(C) Copyright 2000-2004 Mathias Lundgren (lunar_shuttle@users.sf.net), Werner Schweer\n" + "Fixes/mods: (C) Copyright 2011 Tim E. Real (terminator356@users.sf.net)\nPublished under the GNU Public License"; QMessageBox* msgBox = new QMessageBox(caption, text, QMessageBox::NoIcon, QMessageBox::Ok, Qt::NoButton, Qt::NoButton, this); msgBox->exec(); @@ -851,8 +957,12 @@ void SimpleSynthGui::loadSetup() if (theFile.read((char*)&initdata_len, sizeof(initdata_len)) == -1) success = false; - byte* init_data = new byte[initdata_len]; - if (theFile.read((char*)(init_data), initdata_len) == -1) + ///byte* init_data = new byte[initdata_len]; + byte* init_data = new byte[initdata_len + 2]; // 2 for MFG ID and synth ID. + init_data[0] = MUSE_SYNTH_SYSEX_MFG_ID; + init_data[1] = SIMPLEDRUMS_UNIQUE_ID; + //if (theFile.read((char*)(init_data), initdata_len) == -1) + if (theFile.read((char*)(init_data + 2), initdata_len) == -1) success = false; if (!success) { @@ -862,7 +972,8 @@ void SimpleSynthGui::loadSetup() delete msgBox; } else { - sendSysex(init_data, initdata_len); + ///sendSysex(init_data, initdata_len); + sendSysex(init_data, initdata_len + 2); } delete[] init_data; @@ -883,9 +994,14 @@ void SimpleSynthGui::saveSetup() if (filename != QString::null) { lastSavedProject = filename; - byte d[1]; - d[0] = SS_SYSEX_GET_INIT_DATA; - sendSysex(d, 1); // Makes synth send gui initdata, where rest of the saving takes place + //byte d[1]; + byte d[3]; + //d[0] = SS_SYSEX_GET_INIT_DATA; + d[0] = MUSE_SYNTH_SYSEX_MFG_ID; + d[1] = SIMPLEDRUMS_UNIQUE_ID; + d[2] = SS_SYSEX_GET_INIT_DATA; + //sendSysex(d, 1); // Makes synth send gui initdata, where rest of the saving takes place + sendSysex(d, 3); // Makes synth send gui initdata, where rest of the saving takes place } } diff --git a/muse2/synti/simpledrums2/simpledrumsgui.h b/muse2/synti/simpledrums2/simpledrumsgui.h index be8c492d..af32e432 100644 --- a/muse2/synti/simpledrums2/simpledrumsgui.h +++ b/muse2/synti/simpledrums2/simpledrumsgui.h @@ -5,6 +5,7 @@ // // // Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004 +// Contributer: (C) Copyright 2011 Tim E. Real (terminator356 at users.sourceforge.net) // // Copyright: See COPYING file that comes with this distribution // @@ -37,18 +38,19 @@ class QChannelSlider: public QSlider Q_OBJECT public: - QChannelSlider(Qt::Orientation, int ch, QWidget* paren = 0); + QChannelSlider(Qt::Orientation, int ch, QWidget* parent = 0); int getChannel(); void setChannel(int ch); - public slots: - virtual void setValue(int val); + ///public slots: + /// virtual void setValue(int val); signals: void valueChanged(int channel, int value); - + protected: int channel; + virtual void sliderChange(SliderChange change); }; //-------------------------------------- @@ -58,14 +60,17 @@ class QInvertedSlider : public QSlider { Q_OBJECT public: - QInvertedSlider(Qt::Orientation o, QWidget* parent = 0) - : QSlider(o, parent) {} + QInvertedSlider(Qt::Orientation o, QWidget* parent = 0); + ///: QSlider(o, parent) {} - public slots: - virtual void setValue(int val); + ///public slots: + /// virtual void setValue(int val); signals: void invertedValueChanged(int value); + + protected: + virtual void sliderChange(SliderChange change); }; //-------------------------------------- @@ -75,11 +80,10 @@ class QInvertedChannelSlider : public QChannelSlider { Q_OBJECT public: - QInvertedChannelSlider(Qt::Orientation o, int channel, QWidget* parent = 0) - : QChannelSlider(o, channel, parent) {}; + QInvertedChannelSlider(Qt::Orientation o, int channel, QWidget* parent = 0); - public slots: - virtual void setValue(int val); + ///public slots: + /// virtual void setValue(int val); }; @@ -138,12 +142,13 @@ class QChannelDial : public QDial signals: void valueChanged(int channel, int fxid, int val); - public slots: - virtual void setValue(int val); + ///public slots: + /// virtual void setValue(int val); protected: int channel; int sendfxid; + virtual void sliderChange(SliderChange change); }; //-------------------------------------- @@ -160,7 +165,10 @@ class SimpleSynthGui : public QDialog, public Ui::SimpleDrumsGuiBase, public Mes QGroupBox* channelButtonGroups[SS_NR_OF_CHANNELS]; QGroupBox* masterButtonGroup; QGroupBox* mainGroupBox; - QInvertedChannelSlider* volumeSliders[SS_NR_OF_CHANNELS]; + + ///QInvertedChannelSlider* volumeSliders[SS_NR_OF_CHANNELS]; + QChannelSlider* volumeSliders[SS_NR_OF_CHANNELS]; // p4.0.27 Tim. Inverted not correct. Was WIP? + QChannelSlider* panSliders[SS_NR_OF_CHANNELS]; QChannelCheckbox* onOff[SS_NR_OF_CHANNELS]; QChannelCheckbox* nOffIgnore[SS_NR_OF_CHANNELS]; @@ -168,7 +176,10 @@ class SimpleSynthGui : public QDialog, public Ui::SimpleDrumsGuiBase, public Mes QChannelButton* clearSampleButton[SS_NR_OF_CHANNELS]; QLabel* nOffLabel[SS_NR_OF_CHANNELS]; QLineEdit* sampleNameLineEdit[SS_NR_OF_CHANNELS]; - QInvertedSlider* masterSlider; + + ///QInvertedSlider* masterSlider; + QSlider* masterSlider; // p4.0.27 Tim. Inverted not correct. Was WIP? + QChannelDial* sendFxDial[SS_NR_OF_CHANNELS][SS_NR_OF_SENDEFFECTS]; QPushButton* openPluginsButton; diff --git a/muse2/synti/simpledrums2/ssplugin.cpp b/muse2/synti/simpledrums2/ssplugin.cpp index 9d32b2c3..75559a8f 100644 --- a/muse2/synti/simpledrums2/ssplugin.cpp +++ b/muse2/synti/simpledrums2/ssplugin.cpp @@ -6,6 +6,7 @@ // // (C) Copyright 2000 Werner Schweer (ws@seh.de) // Additions/modifications: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004 +// (C) Copyright 2011 Tim E. Real (terminator356 at users.sourceforge.net) // Copyright: See COPYING file that comes with this distribution // // diff --git a/muse2/synti/simpledrums2/ssplugin.h b/muse2/synti/simpledrums2/ssplugin.h index 64e80921..8750753b 100644 --- a/muse2/synti/simpledrums2/ssplugin.h +++ b/muse2/synti/simpledrums2/ssplugin.h @@ -6,6 +6,7 @@ // // (C) Copyright 2000 Werner Schweer (ws@seh.de) // Additions/modifications: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004 +// (C) Copyright 2011 Tim E. Real (terminator356 at users.sourceforge.net) // Copyright: See COPYING file that comes with this distribution // // diff --git a/muse2/synti/simpledrums2/ssplugingui.cpp b/muse2/synti/simpledrums2/ssplugingui.cpp index d52d3a8f..31ac3ac4 100644 --- a/muse2/synti/simpledrums2/ssplugingui.cpp +++ b/muse2/synti/simpledrums2/ssplugingui.cpp @@ -5,6 +5,7 @@ // // // Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004 +// Contributer: (C) Copyright 2011 Tim E. Real (terminator356 at users.sourceforge.net) // // Copyright: See COPYING file that comes with this distribution // @@ -56,18 +57,24 @@ SS_PluginChooser::SS_PluginChooser(QWidget* parent) } connect(okButton, SIGNAL(pressed()), SLOT(okPressed())); connect(cancelButton, SIGNAL(pressed()), SLOT(cancelPressed())); - connect(effectsListView, SIGNAL(selectionChanged(QTreeWidgetItem*)), SLOT(selectionChanged(QTreeWidgetItem*))); - connect(effectsListView, SIGNAL(doubleClicked(QTreeWidgetItem*)), SLOT(doubleClicked(QTreeWidgetItem*))); + + //connect(effectsListView, SIGNAL(selectionChanged(QTreeWidgetItem*)), SLOT(selectionChanged(QTreeWidgetItem*))); + //connect(effectsListView, SIGNAL(doubleClicked(QTreeWidgetItem*)), SLOT(doubleClicked(QTreeWidgetItem*))); + connect(effectsListView, SIGNAL(itemSelectionChanged()), SLOT(selectionChanged())); // p4.0.27 + connect(effectsListView, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), SLOT(doubleClicked(QTreeWidgetItem*))); // + SS_TRACE_OUT } /*! \fn SS_PluginChooser::selectionChanged(QListViewItem* item) */ -void SS_PluginChooser::selectionChanged(QTreeWidgetItem* item) +//void SS_PluginChooser::selectionChanged(QTreeWidgetItem* item) +void SS_PluginChooser::selectionChanged() { SS_TRACE_IN - selectedItem = item; + //selectedItem = item; + selectedItem = effectsListView->currentItem(); SS_TRACE_OUT } @@ -95,9 +102,10 @@ void SS_PluginChooser::cancelPressed() /*! \fn SS_PluginChooser::doubleClicked(QListViewItem* item) */ -void SS_PluginChooser::doubleClicked(QTreeWidgetItem* /*item*/) +void SS_PluginChooser::doubleClicked(QTreeWidgetItem* item) { SS_TRACE_IN + selectedItem = item; // p4.0.27 Tim selectedPlugin = findSelectedPlugin(); SS_TRACE_OUT done(QDialog::Accepted); @@ -109,6 +117,8 @@ void SS_PluginChooser::doubleClicked(QTreeWidgetItem* /*item*/) LadspaPlugin* SS_PluginChooser::findSelectedPlugin() { SS_TRACE_IN + if(!selectedItem) // p4.0.27 Tim + return 0; LadspaPlugin* selected = 0; for (iPlugin i=plugins.begin(); i != plugins.end(); i++) { if ((*i)->name() == selectedItem->text(SS_PLUGINCHOOSER_NAMECOL)) @@ -299,7 +309,7 @@ void SS_PluginFront::updatePluginValue(unsigned k) } iPlugin i; - for (i = plugins.begin(); j != k; i++, j++); + for (i = plugins.begin(); j != k; i++, j++) ; plugin = (LadspaPlugin*) *(i); setPluginName(plugin->label()); outGainSlider->setEnabled(true); @@ -307,7 +317,7 @@ void SS_PluginFront::updatePluginValue(unsigned k) expandButton->setEnabled(true); pluginName->setEnabled(true); onOff->setEnabled(true); - onOff->setChecked(true); + ///onOff->setChecked(true); SS_TRACE_OUT } @@ -359,6 +369,15 @@ void SS_PluginFront::setRetGain(int val) } /*! + \fn SS_PluginFront::setOnOff(bool val) + */ +void SS_PluginFront::setOnOff(bool val) + { + onOff->blockSignals(true); + onOff->setChecked(val); + onOff->blockSignals(false); + } +/*! \fn SS_PluginFront::expandButtonPressed() */ void SS_PluginFront::expandButtonPressed() diff --git a/muse2/synti/simpledrums2/ssplugingui.h b/muse2/synti/simpledrums2/ssplugingui.h index 3d77ecf0..99951d01 100644 --- a/muse2/synti/simpledrums2/ssplugingui.h +++ b/muse2/synti/simpledrums2/ssplugingui.h @@ -5,6 +5,7 @@ // // // Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004 +// Contributer: (C) Copyright 2011 Tim E. Real (terminator356 at users.sourceforge.net) // // Copyright: See COPYING file that comes with this distribution // @@ -83,11 +84,21 @@ class SS_ParameterSlider : public QSlider, public SS_ParameterWidget virtual void setParamValue(int val) { SS_TRACE_IN setValue(val); SS_TRACE_OUT} - public slots: - virtual void setValue(int val) { SS_TRACE_IN QSlider::setValue(val); emit valueChanged(fxid, parameter, val); SS_TRACE_OUT } + ///public slots: + /// virtual void setValue(int val) { SS_TRACE_IN QSlider::setValue(val); emit valueChanged(fxid, parameter, val); SS_TRACE_OUT } signals: void valueChanged(int id, int param, int val); + + protected: + virtual void sliderChange(SliderChange change) // p4.0.27 Tim + { + SS_TRACE_IN + QSlider::sliderChange(change); + if(change == QAbstractSlider::SliderValueChange) + emit valueChanged(fxid, parameter, value()); + SS_TRACE_OUT + } }; typedef std::list<SS_ParameterWidget*> SS_ParameterWidgetList; @@ -110,7 +121,8 @@ class SS_PluginChooser : public QDialog, Ui::SS_PluginChooserBase private slots: void okPressed(); void cancelPressed(); - void selectionChanged(QTreeWidgetItem* item); + ///void selectionChanged(QTreeWidgetItem* item); + void selectionChanged(); void doubleClicked(QTreeWidgetItem* item); private: @@ -154,6 +166,7 @@ class SS_PluginFront : public QGroupBox void clearPluginDisplay(); void setParameterValue(int param, int val); void setRetGain(int val); + void setOnOff(bool val); protected: virtual QSize sizeHint() const; diff --git a/muse2/synti/vam/common_defs.h b/muse2/synti/vam/common_defs.h new file mode 100644 index 00000000..59821a70 --- /dev/null +++ b/muse2/synti/vam/common_defs.h @@ -0,0 +1,8 @@ +#ifndef __VAM_UNIQUE_ID_H +#define __VAM_UNIQUE_ID_H + +// Make sure this number is unique among all the MESS synths. +#define VAM_UNIQUE_ID 2 + +#endif + diff --git a/muse2/synti/vam/vam.cpp b/muse2/synti/vam/vam.cpp index fd71d9ea..14280651 100644 --- a/muse2/synti/vam/vam.cpp +++ b/muse2/synti/vam/vam.cpp @@ -35,6 +35,7 @@ #include "muse/midi.h" #include "muse/midictrl.h" +#include "common_defs.h" #include "vam.h" #include "vamgui.h" #include "libsynti/mono.h" @@ -165,7 +166,8 @@ class VAM : public MessMono { float velocity; //int idata[NUM_CONTROLLER]; // buffer for init data - int *idata; + //int *idata; + unsigned char* idata; EnvelopeGenerator dco1_env; EnvelopeGenerator dco2_env; @@ -192,7 +194,10 @@ class VAM : public MessMono { public: virtual int getControllerInfo(int, const char**, int*, int*, int*, int*) const; - virtual void getInitData(int* n, const unsigned char**p) const; + //virtual void getInitData(int* n, const unsigned char**p) const; + virtual void getInitData(int* n, const unsigned char**p); + // This is only a kludge required to support old songs' midistates. Do not use in any new synth. + virtual int oldMidiStateHeader(const unsigned char** data) const; //virtual bool guiVisible() const; //virtual void showGui(bool); //virtual bool hasGui() const { return true; } @@ -207,7 +212,7 @@ class VAM : public MessMono { virtual bool setController(int channel, int ctrl, int val); virtual bool sysex(int, const unsigned char*); VAM(int sr); - ~VAM(); + virtual ~VAM(); bool init(const char* name); }; @@ -227,7 +232,7 @@ float VAM::lin2exp[VAM::LIN2EXP_SIZE]; VAM::VAM(int sr) : MessMono() { - idata = new int[NUM_CONTROLLER]; + idata = new unsigned char[3 + NUM_CONTROLLER * sizeof(int)]; setSampleRate(sr); gui = 0; } @@ -238,6 +243,10 @@ VAM::VAM(int sr) VAM::~VAM() { + if (gui) + delete gui; + //delete idata; + delete [] idata; // p4.0.27 --useCount; if (useCount == 0) { delete[] sin_tbl; @@ -247,6 +256,13 @@ VAM::~VAM() } } +int VAM::oldMidiStateHeader(const unsigned char** data) const +{ + unsigned char const d[3] = {MUSE_SYNTH_SYSEX_MFG_ID, VAM_UNIQUE_ID, INIT_DATA_CMD}; + *data = &d[0]; + return 3; +} + //--------------------------------------------------------- // curTime //--------------------------------------------------------- @@ -438,11 +454,16 @@ void VAM::processMessages() if (ev.type() == ME_CONTROLLER) { // process local? - setController(ev.dataA() & 0xfff, ev.dataB()); + //setController(ev.dataA() & 0xfff, ev.dataB()); + setController(ev.dataA(), ev.dataB()); sendEvent(ev); } else + { + #ifdef VAM_DEBUG printf("VAM::process(): unknown event\n"); + #endif + } } } @@ -604,7 +625,17 @@ int VAM::getControllerInfo(int id, const char** name, int* controller, bool VAM::setController(int /*channel*/, int ctrl, int data) { - setController(ctrl & 0xfff, data); + //setController(ctrl & 0xfff, data); + // p4.0.27 + if(ctrl < VAM_FIRST_CTRL || ctrl > VAM_LAST_CTRL) + { + #ifdef VAM_DEBUG + printf("VAM::setController Invalid controller number 0x%x\n", ctrl); + #endif + return false; + } + setController(ctrl, data); + MidiPlayEvent ev(0, 0, channel, ME_CONTROLLER, ctrl, data); gui->writeEvent(ev); return false; @@ -612,6 +643,15 @@ bool VAM::setController(int /*channel*/, int ctrl, int data) void VAM::setController(int ctrl, int data) { + // p4.0.27 + if(ctrl < VAM_FIRST_CTRL || ctrl > VAM_LAST_CTRL) + { + #ifdef VAM_DEBUG + printf("VAM: Invalid controller number 0x%x\n", ctrl); + #endif + return; + } + // fprintf(stderr, "ctrl: %d data: %d\n", ctrl, data); int maxval = 128*128-1; double normval = double(data) / double(maxval); @@ -723,22 +763,34 @@ void VAM::setController(int ctrl, int data) if(dco2.pw == 1.0) dco2.pw = 0.99; break; default: - printf("VAM: set unknown Ctrl 0x%x to 0x%x\n", ctrl, data); - break; + //#ifdef VAM_DEBUG + //printf("VAM: set unknown Ctrl 0x%x to 0x%x\n", ctrl, data); + //#endif + //break; + return; // p4.0.27 } - controller[ctrl] = data; + //controller[ctrl] = data; + controller[ctrl - VAM_FIRST_CTRL] = data; // p4.0.27 } //--------------------------------------------------------- // getInitData //--------------------------------------------------------- -void VAM::getInitData(int* n, const unsigned char**p) const - { +//void VAM::getInitData(int* n, const unsigned char**p) const +void VAM::getInitData(int* n, const unsigned char**p) +{ + // p4.0.27 + *n = 3 + NUM_CONTROLLER * sizeof(int); + idata[0] = MUSE_SYNTH_SYSEX_MFG_ID; // Global MusE Soft Synth Manufacturer ID + idata[1] = VAM_UNIQUE_ID; // VAM + idata[2] = INIT_DATA_CMD; // Initialization command + int* d = (int*)&idata[3]; + //int i;//prevent of compiler warning: unused variable - int* d = idata; + //int* d = idata; //int maxval = 128*128-1; //prevent of compiler warning: unused variable - *n = NUM_CONTROLLER * sizeof(int); + // *n = NUM_CONTROLLER * sizeof(int); // // setController(0, DCO1_PITCHMOD, p++); // *d++ = int(dco1.pitchmod+8191*341.333); @@ -935,51 +987,68 @@ void VAM::getInitData(int* n, const unsigned char**p) const *d++ = gui->getController(DCO2_PW); *p = (unsigned char*)idata; - } +} //--------------------------------------------------------- // sysex //--------------------------------------------------------- bool VAM::sysex(int n, const unsigned char* data) +{ + // p4.0.27 + if(unsigned(n) == (3 + NUM_CONTROLLER * sizeof(int))) { - n=n; // remove warning of unused variable - int *p= (int*)data; - setController(0, DCO1_PITCHMOD, *p++); - setController(0, DCO2_PITCHMOD, *p++); - setController(0, DCO1_WAVEFORM, *p++); - setController(0, DCO2_WAVEFORM, *p++); - setController(0, DCO1_FM, *p++); - setController(0, DCO2_FM, *p++); - setController(0, DCO1_PWM, *p++); - setController(0, DCO2_PWM, *p++); - setController(0, DCO1_ATTACK, *p++); - setController(0, DCO2_ATTACK, *p++); - setController(0, DCO1_DECAY, *p++); - setController(0, DCO2_DECAY, *p++); - setController(0, DCO1_SUSTAIN, *p++ ); - setController(0, DCO2_SUSTAIN, *p++ ); - setController(0, DCO1_RELEASE, *p++); - setController(0, DCO2_RELEASE, *p++); - setController(0, LFO_FREQ, *p++); - setController(0, LFO_WAVEFORM, *p++); - setController(0, FILT_ENV_MOD, *p++); - setController(0, FILT_KEYTRACK, *p++); - setController(0, FILT_RES, *p++); - setController(0, FILT_ATTACK, *p++); - setController(0, FILT_DECAY, *p++); - setController(0, FILT_SUSTAIN, *p++); - setController(0, FILT_RELEASE, *p++); - setController(0, DCO2ON, *p++); - setController(0, FILT_INVERT, *p++); - setController(0, FILT_CUTOFF, *p++); - setController(0, DCO1_DETUNE, *p++); - setController(0, DCO2_DETUNE, *p++); - setController(0, DCO1_PW, *p++); - setController(0, DCO2_PW, *p++); - - return false; + if (data[0] == MUSE_SYNTH_SYSEX_MFG_ID) // Global MusE Soft Synth Manufacturer ID + { + if (data[1] == VAM_UNIQUE_ID) // VAM + { + if (data[2] == INIT_DATA_CMD) // Initialization command + { + int *p= (int*)(data + 3); + setController(0, DCO1_PITCHMOD, *p++); + setController(0, DCO2_PITCHMOD, *p++); + setController(0, DCO1_WAVEFORM, *p++); + setController(0, DCO2_WAVEFORM, *p++); + setController(0, DCO1_FM, *p++); + setController(0, DCO2_FM, *p++); + setController(0, DCO1_PWM, *p++); + setController(0, DCO2_PWM, *p++); + setController(0, DCO1_ATTACK, *p++); + setController(0, DCO2_ATTACK, *p++); + setController(0, DCO1_DECAY, *p++); + setController(0, DCO2_DECAY, *p++); + setController(0, DCO1_SUSTAIN, *p++ ); + setController(0, DCO2_SUSTAIN, *p++ ); + setController(0, DCO1_RELEASE, *p++); + setController(0, DCO2_RELEASE, *p++); + setController(0, LFO_FREQ, *p++); + setController(0, LFO_WAVEFORM, *p++); + setController(0, FILT_ENV_MOD, *p++); + setController(0, FILT_KEYTRACK, *p++); + setController(0, FILT_RES, *p++); + setController(0, FILT_ATTACK, *p++); + setController(0, FILT_DECAY, *p++); + setController(0, FILT_SUSTAIN, *p++); + setController(0, FILT_RELEASE, *p++); + setController(0, DCO2ON, *p++); + setController(0, FILT_INVERT, *p++); + setController(0, FILT_CUTOFF, *p++); + setController(0, DCO1_DETUNE, *p++); + setController(0, DCO2_DETUNE, *p++); + setController(0, DCO1_PW, *p++); + setController(0, DCO2_PW, *p++); + return false; + } + } + } } + + #ifdef VAM_DEBUG + printf("VAM: unknown sysex\n"); + #endif + + return false; +} //--------------------------------------------------------- // nativeGuiVisible diff --git a/muse2/synti/vam/vam.h b/muse2/synti/vam/vam.h index 3da27e79..72edd9f8 100644 --- a/muse2/synti/vam/vam.h +++ b/muse2/synti/vam/vam.h @@ -21,8 +21,12 @@ #ifndef __VAM_H #define __VAM_H +#include "muse/midictrl.h" + enum { - DCO1_PITCHMOD, DCO1_WAVEFORM, DCO1_FM, DCO1_PWM, + //DCO1_PITCHMOD, + DCO1_PITCHMOD = CTRL_RPN14_OFFSET, // p4.0.27 + DCO1_WAVEFORM, DCO1_FM, DCO1_PWM, DCO1_ATTACK, DCO1_DECAY, DCO1_SUSTAIN, DCO1_RELEASE, DCO2_PITCHMOD, DCO2_WAVEFORM, DCO2_FM, DCO2_PWM, DCO2_ATTACK, DCO2_DECAY, DCO2_SUSTAIN, DCO2_RELEASE, @@ -32,7 +36,11 @@ enum { DCO1_DETUNE, DCO2_DETUNE, DCO1_PW, DCO2_PW }; +#define VAM_FIRST_CTRL DCO1_PITCHMOD +#define VAM_LAST_CTRL DCO2_PW +#define NUM_CONTROLLER 32 +#define INIT_DATA_CMD 1 -#define NUM_CONTROLLER 32 +//#define VAM_DEBUG #endif /* __VAM_H */ diff --git a/muse2/synti/vam/vamgui.cpp b/muse2/synti/vam/vamgui.cpp index 50b6552c..34f8636c 100644 --- a/muse2/synti/vam/vamgui.cpp +++ b/muse2/synti/vam/vamgui.cpp @@ -32,6 +32,7 @@ #include <list> +#include "common_defs.h" #include "vamgui.h" #include "vam.h" @@ -187,38 +188,39 @@ VAMGui::VAMGui() savePresetsToFile->setIcon(QIcon(*saveasIcon)); deletePreset->setIcon(QIcon(*deleteIcon)); - dctrl[DCO1_PITCHMOD] = SynthGuiCtrl(PitchModS, LCDNumber1, SynthGuiCtrl::SLIDER); - dctrl[DCO1_WAVEFORM] = SynthGuiCtrl(Waveform, 0, SynthGuiCtrl::COMBOBOX); - dctrl[DCO1_FM] = SynthGuiCtrl(FMS, LCDNumber1_2, SynthGuiCtrl::SLIDER); - dctrl[DCO1_PWM] = SynthGuiCtrl(PWMS, LCDNumber1_3, SynthGuiCtrl::SLIDER); - dctrl[DCO1_ATTACK] = SynthGuiCtrl(AttackS, LCDNumber1_3_2, SynthGuiCtrl::SLIDER); - dctrl[DCO1_DECAY] = SynthGuiCtrl(DecayS, LCDNumber1_3_2_2, SynthGuiCtrl::SLIDER); - dctrl[DCO1_SUSTAIN] = SynthGuiCtrl(SustainS, LCDNumber1_3_2_3, SynthGuiCtrl::SLIDER); - dctrl[DCO1_RELEASE] = SynthGuiCtrl(ReleaseS, LCDNumber1_3_2_4, SynthGuiCtrl::SLIDER); - dctrl[DCO2_PITCHMOD] = SynthGuiCtrl(PitchModS2, LCDNumber1_4, SynthGuiCtrl::SLIDER); - dctrl[DCO2_WAVEFORM] = SynthGuiCtrl(Waveform2, 0, SynthGuiCtrl::COMBOBOX); - dctrl[DCO2_FM] = SynthGuiCtrl(FMS2, LCDNumber1_2_2, SynthGuiCtrl::SLIDER); - dctrl[DCO2_PWM] = SynthGuiCtrl(PWMS2, LCDNumber1_3_3, SynthGuiCtrl::SLIDER); - dctrl[DCO2_ATTACK] = SynthGuiCtrl(AttackS2, LCDNumber1_3_2_5, SynthGuiCtrl::SLIDER); - dctrl[DCO2_DECAY] = SynthGuiCtrl(DecayS2, LCDNumber1_3_2_2_2, SynthGuiCtrl::SLIDER); - dctrl[DCO2_SUSTAIN] = SynthGuiCtrl(SustainS2, LCDNumber1_3_2_3_2, SynthGuiCtrl::SLIDER); - dctrl[DCO2_RELEASE] = SynthGuiCtrl(ReleaseS2, LCDNumber1_3_2_4_2, SynthGuiCtrl::SLIDER); - dctrl[LFO_FREQ] = SynthGuiCtrl(FreqS, LCDNumber1_5, SynthGuiCtrl::SLIDER); - dctrl[LFO_WAVEFORM] = SynthGuiCtrl(Waveform2_2, 0, SynthGuiCtrl::COMBOBOX); - dctrl[FILT_ENV_MOD] = SynthGuiCtrl(EnvModS, LCDNumber1_5_3, SynthGuiCtrl::SLIDER); - dctrl[FILT_KEYTRACK] = SynthGuiCtrl(KeyTrack, 0, SynthGuiCtrl::SWITCH); - dctrl[FILT_RES] = SynthGuiCtrl(ResS, LCDNumber1_5_5, SynthGuiCtrl::SLIDER); - dctrl[FILT_ATTACK] = SynthGuiCtrl(AttackS3, LCDNumber1_3_2_5_2, SynthGuiCtrl::SLIDER); - dctrl[FILT_DECAY] = SynthGuiCtrl(DecayS3, LCDNumber1_3_2_2_2_2, SynthGuiCtrl::SLIDER); - dctrl[FILT_SUSTAIN] = SynthGuiCtrl(SustainS3, LCDNumber1_3_2_3_2_2, SynthGuiCtrl::SLIDER); - dctrl[FILT_RELEASE] = SynthGuiCtrl(ReleaseS3, LCDNumber1_3_2_4_2_2, SynthGuiCtrl::SLIDER); - dctrl[DCO2ON] = SynthGuiCtrl(DCO2On, 0, SynthGuiCtrl::SWITCH); - dctrl[FILT_INVERT] = SynthGuiCtrl(FilterInvert, 0, SynthGuiCtrl::SWITCH); - dctrl[FILT_CUTOFF] = SynthGuiCtrl(CutoffS, LCDNumber1_5_5_2, SynthGuiCtrl::SLIDER); - dctrl[DCO1_DETUNE] = SynthGuiCtrl(DetuneS, LCDNumber1_6, SynthGuiCtrl::SLIDER); - dctrl[DCO2_DETUNE] = SynthGuiCtrl(DetuneS2, LCDNumber1_6_2, SynthGuiCtrl::SLIDER); - dctrl[DCO1_PW] = SynthGuiCtrl(PWS, LCDNumber1_2_3, SynthGuiCtrl::SLIDER); - dctrl[DCO2_PW] = SynthGuiCtrl(PWS2, LCDNumber1_2_4, SynthGuiCtrl::SLIDER); + // p4.0.27 First ctrl offset. + dctrl[DCO1_PITCHMOD - VAM_FIRST_CTRL] = SynthGuiCtrl(PitchModS, LCDNumber1, SynthGuiCtrl::SLIDER); + dctrl[DCO1_WAVEFORM - VAM_FIRST_CTRL] = SynthGuiCtrl(Waveform, 0, SynthGuiCtrl::COMBOBOX); + dctrl[DCO1_FM - VAM_FIRST_CTRL] = SynthGuiCtrl(FMS, LCDNumber1_2, SynthGuiCtrl::SLIDER); + dctrl[DCO1_PWM - VAM_FIRST_CTRL] = SynthGuiCtrl(PWMS, LCDNumber1_3, SynthGuiCtrl::SLIDER); + dctrl[DCO1_ATTACK - VAM_FIRST_CTRL] = SynthGuiCtrl(AttackS, LCDNumber1_3_2, SynthGuiCtrl::SLIDER); + dctrl[DCO1_DECAY - VAM_FIRST_CTRL] = SynthGuiCtrl(DecayS, LCDNumber1_3_2_2, SynthGuiCtrl::SLIDER); + dctrl[DCO1_SUSTAIN - VAM_FIRST_CTRL] = SynthGuiCtrl(SustainS, LCDNumber1_3_2_3, SynthGuiCtrl::SLIDER); + dctrl[DCO1_RELEASE - VAM_FIRST_CTRL] = SynthGuiCtrl(ReleaseS, LCDNumber1_3_2_4, SynthGuiCtrl::SLIDER); + dctrl[DCO2_PITCHMOD - VAM_FIRST_CTRL] = SynthGuiCtrl(PitchModS2, LCDNumber1_4, SynthGuiCtrl::SLIDER); + dctrl[DCO2_WAVEFORM - VAM_FIRST_CTRL] = SynthGuiCtrl(Waveform2, 0, SynthGuiCtrl::COMBOBOX); + dctrl[DCO2_FM - VAM_FIRST_CTRL] = SynthGuiCtrl(FMS2, LCDNumber1_2_2, SynthGuiCtrl::SLIDER); + dctrl[DCO2_PWM - VAM_FIRST_CTRL] = SynthGuiCtrl(PWMS2, LCDNumber1_3_3, SynthGuiCtrl::SLIDER); + dctrl[DCO2_ATTACK - VAM_FIRST_CTRL] = SynthGuiCtrl(AttackS2, LCDNumber1_3_2_5, SynthGuiCtrl::SLIDER); + dctrl[DCO2_DECAY - VAM_FIRST_CTRL] = SynthGuiCtrl(DecayS2, LCDNumber1_3_2_2_2, SynthGuiCtrl::SLIDER); + dctrl[DCO2_SUSTAIN - VAM_FIRST_CTRL] = SynthGuiCtrl(SustainS2, LCDNumber1_3_2_3_2, SynthGuiCtrl::SLIDER); + dctrl[DCO2_RELEASE - VAM_FIRST_CTRL] = SynthGuiCtrl(ReleaseS2, LCDNumber1_3_2_4_2, SynthGuiCtrl::SLIDER); + dctrl[LFO_FREQ - VAM_FIRST_CTRL] = SynthGuiCtrl(FreqS, LCDNumber1_5, SynthGuiCtrl::SLIDER); + dctrl[LFO_WAVEFORM - VAM_FIRST_CTRL] = SynthGuiCtrl(Waveform2_2, 0, SynthGuiCtrl::COMBOBOX); + dctrl[FILT_ENV_MOD - VAM_FIRST_CTRL] = SynthGuiCtrl(EnvModS, LCDNumber1_5_3, SynthGuiCtrl::SLIDER); + dctrl[FILT_KEYTRACK - VAM_FIRST_CTRL] = SynthGuiCtrl(KeyTrack, 0, SynthGuiCtrl::SWITCH); + dctrl[FILT_RES - VAM_FIRST_CTRL] = SynthGuiCtrl(ResS, LCDNumber1_5_5, SynthGuiCtrl::SLIDER); + dctrl[FILT_ATTACK - VAM_FIRST_CTRL] = SynthGuiCtrl(AttackS3, LCDNumber1_3_2_5_2, SynthGuiCtrl::SLIDER); + dctrl[FILT_DECAY - VAM_FIRST_CTRL] = SynthGuiCtrl(DecayS3, LCDNumber1_3_2_2_2_2, SynthGuiCtrl::SLIDER); + dctrl[FILT_SUSTAIN - VAM_FIRST_CTRL] = SynthGuiCtrl(SustainS3, LCDNumber1_3_2_3_2_2, SynthGuiCtrl::SLIDER); + dctrl[FILT_RELEASE - VAM_FIRST_CTRL] = SynthGuiCtrl(ReleaseS3, LCDNumber1_3_2_4_2_2, SynthGuiCtrl::SLIDER); + dctrl[DCO2ON - VAM_FIRST_CTRL] = SynthGuiCtrl(DCO2On, 0, SynthGuiCtrl::SWITCH); + dctrl[FILT_INVERT - VAM_FIRST_CTRL] = SynthGuiCtrl(FilterInvert, 0, SynthGuiCtrl::SWITCH); + dctrl[FILT_CUTOFF - VAM_FIRST_CTRL] = SynthGuiCtrl(CutoffS, LCDNumber1_5_5_2, SynthGuiCtrl::SLIDER); + dctrl[DCO1_DETUNE - VAM_FIRST_CTRL] = SynthGuiCtrl(DetuneS, LCDNumber1_6, SynthGuiCtrl::SLIDER); + dctrl[DCO2_DETUNE - VAM_FIRST_CTRL] = SynthGuiCtrl(DetuneS2, LCDNumber1_6_2, SynthGuiCtrl::SLIDER); + dctrl[DCO1_PW - VAM_FIRST_CTRL] = SynthGuiCtrl(PWS, LCDNumber1_2_3, SynthGuiCtrl::SLIDER); + dctrl[DCO2_PW - VAM_FIRST_CTRL] = SynthGuiCtrl(PWS2, LCDNumber1_2_4, SynthGuiCtrl::SLIDER); map = new QSignalMapper(this); @@ -275,11 +277,22 @@ void VAMGui::ctrlChanged(int idx) else if (ctrl->type == SynthGuiCtrl::SWITCH) { val = ((QCheckBox*)(ctrl->editor))->isChecked(); } - sendController(0, idx + CTRL_RPN14_OFFSET, val); + //sendController(0, idx + CTRL_RPN14_OFFSET, val); + sendController(0, idx + VAM_FIRST_CTRL, val); // p4.0.27 } int VAMGui::getController(int idx) { + // p4.0.27 + if(idx < VAM_FIRST_CTRL || idx > VAM_LAST_CTRL) + { + //#ifdef VAM_DEBUG + printf("VAMGui:: invalid controller number %d\n", idx); + //#endif + return 0; + } + idx -= VAM_FIRST_CTRL; + SynthGuiCtrl* ctrl = &dctrl[idx]; int val = 0; if (ctrl->type == SynthGuiCtrl::SLIDER) { @@ -302,8 +315,9 @@ int VAMGui::getControllerInfo(int id, const char** name, int* controller, if (id >= NUM_CONTROLLER) return 0; + //*controller = id; + *controller = id + VAM_FIRST_CTRL; // p4.0.27 - *controller = id; *name = vam_ctrl_names[id]; const SynthGuiCtrl* ctrl = (const SynthGuiCtrl*)&dctrl[id]; //int val = 0; @@ -357,8 +371,9 @@ void VAMGui::activatePreset(Preset* preset) fprintf(stderr, "internal error 1\n"); exit(-1); } - for (unsigned int i = 0; i < sizeof(dctrl)/sizeof(*dctrl); ++i) { - setParam(i, preset->ctrl[i]); + //for (unsigned int i = 0; i < sizeof(dctrl)/sizeof(*dctrl); ++i) { + for (unsigned int i = 0; i < NUM_CONTROLLER; ++i) { // p4.0.27 + setParam(i, preset->ctrl[i]); ctrlChanged(i); } } @@ -443,9 +458,9 @@ void VAMGui::setPreset(Preset* preset) // #if 0 putchar(0xf0); - putchar(0x7c); // mess - putchar(0x2); // vam - putchar(0x3); // setPreset + putchar(MUSE_SYNTH_SYSEX_MFG_ID); // mess + putchar(VAM_UNIQUE_ID); // vam + putchar(0x3); // setPreset QByteArray ba = preset->name.toLatin1(); const char* name = ba.constData(); while (*name) @@ -467,8 +482,11 @@ void VAMGui::setPreset(Preset* preset) void VAMGui::setParam(int param, int val) { - if (param >= int(sizeof(dctrl)/sizeof(*dctrl))) { + //if (param >= int(sizeof(dctrl)/sizeof(*dctrl))) { + if (param >= NUM_CONTROLLER) { // p4.0.27 + #ifdef VAM_DEBUG fprintf(stderr, "vam: set unknown parameter 0x%x to 0x%x\n", param, val); + #endif return; } SynthGuiCtrl* ctrl = &dctrl[param]; @@ -496,15 +514,17 @@ void VAMGui::setParam(int param, int val) // sysexReceived //--------------------------------------------------------- -void VAMGui::sysexReceived(const unsigned char* data, int len) +void VAMGui::sysexReceived(const unsigned char* /*data*/, int /*len*/) { - if (len >= 4) { + // Removed, this is not used. p4.0.27 + /* + if (len >= 4) { //--------------------------------------------- // MusE Soft Synth //--------------------------------------------- - if (data[0] == 0x7c) { - if (data[1] == 2) { // vam + if (data[0] == MUSE_SYNTH_SYSEX_MFG_ID) { + if (data[1] == VAM_UNIQUE_ID) { // vam if (data[2] == 2) { // parameter response if (len != 6) { fprintf(stderr, "vam gui: bad sysEx len\n"); @@ -531,10 +551,15 @@ void VAMGui::sysexReceived(const unsigned char* data, int len) } } } - fprintf(stderr, "vam gui: unknown sysex received, len %d:\n", len); + + #ifdef VAM_DEBUG + fprintf(stderr, "vam gui: unknown sysex received, len %d:\n", len); for (int i = 0; i < len; ++i) fprintf(stderr, "%02x ", data[i]); fprintf(stderr, "\n"); + #endif + */ + } //--------------------------------------------------------- @@ -544,12 +569,28 @@ void VAMGui::sysexReceived(const unsigned char* data, int len) void VAMGui::processEvent(const MidiPlayEvent& ev) { if (ev.type() == ME_CONTROLLER) - setParam(ev.dataA() & 0xfff, ev.dataB()); + { + //setParam(ev.dataA() & 0xfff, ev.dataB()); + // p4.0.27 + int ctl = ev.dataA(); + if(ctl < VAM_FIRST_CTRL || ctl > VAM_LAST_CTRL) + { + //#ifdef VAM_DEBUG + printf("VAMGui:: invalid controller number %d\n", ctl); + //#endif + return; + } + setParam(ctl - VAM_FIRST_CTRL, ev.dataB()); + + } else if (ev.type() == ME_SYSEX) - sysexReceived(ev.data(), ev.len()) - ; + sysexReceived(ev.data(), ev.len()); else + { + #ifdef VAM_DEBUG printf("VAMGui::illegal event type received\n"); + #endif + } } //--------------------------------------------------------- |