diff options
author | Tim E. Real <termtech@rogers.com> | 2011-06-19 01:26:26 +0000 |
---|---|---|
committer | Tim E. Real <termtech@rogers.com> | 2011-06-19 01:26:26 +0000 |
commit | 02941424387a064301372c12bda3e8c3ab3fee45 (patch) | |
tree | e4cdea4400d8a34060a1c4d2b32da8e7ef46ab90 /muse2/synti/fluidsynth | |
parent | 448d81436ed8c2bc501506c2663a9bdb8c0dd023 (diff) |
Major work, all synthesizers. Other fixes. Please see ChangeLog.
Diffstat (limited to 'muse2/synti/fluidsynth')
-rw-r--r-- | muse2/synti/fluidsynth/common_defs.h | 8 | ||||
-rw-r--r-- | muse2/synti/fluidsynth/fluidsynthgui.cpp | 73 | ||||
-rw-r--r-- | muse2/synti/fluidsynth/fluidsynthgui.h | 3 | ||||
-rw-r--r-- | muse2/synti/fluidsynth/fluidsynti.cpp | 142 | ||||
-rw-r--r-- | muse2/synti/fluidsynth/fluidsynti.h | 10 |
5 files changed, 169 insertions, 67 deletions
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; |