From 6f35a1b2b84ab6cfc5d77fd46d5e31887a1590e1 Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Fri, 30 Dec 2011 17:55:58 +0000 Subject: instruments can load their patch'es drummaps automatic setting of drummap according to patch this is turned off when the user manually changes the drummap TODO: let him turn it on again moved MidiTrack::read/writeOurDrummap out to helper.cpp extended xg.idf and gs.idf to ship the drummaps still work in progress, but should be usable and stable, though incomplete --- muse2/muse/CMakeLists.txt | 2 + muse2/muse/app.cpp | 2 + muse2/muse/helper.cpp | 199 ++++++++++++- muse2/muse/helper.h | 12 +- muse2/muse/instruments/minstrument.cpp | 188 ++++++++++++- muse2/muse/instruments/minstrument.h | 47 ++++ muse2/muse/midiedit/dcanvas.cpp | 21 +- muse2/muse/midiedit/dlist.cpp | 2 + muse2/muse/midiedit/drumedit.cpp | 2 +- muse2/muse/midiedit/drummap.cpp | 73 ++++- muse2/muse/midiedit/drummap.h | 7 +- muse2/muse/midiedit/scoreedit.cpp | 4 +- muse2/muse/song.cpp | 1 + muse2/muse/track.cpp | 246 +++++++--------- muse2/muse/track.h | 10 + muse2/muse/trackdrummapupdater.cpp | 61 ++++ muse2/muse/trackdrummapupdater.h | 43 +++ muse2/share/instruments/gs.idf | 367 ++++++++++++++++++++++++ muse2/share/instruments/xg.idf | 501 +++++++++++++++++++++++++++++++++ 19 files changed, 1611 insertions(+), 177 deletions(-) create mode 100644 muse2/muse/trackdrummapupdater.cpp create mode 100644 muse2/muse/trackdrummapupdater.h diff --git a/muse2/muse/CMakeLists.txt b/muse2/muse/CMakeLists.txt index 187bd41e..36645db4 100644 --- a/muse2/muse/CMakeLists.txt +++ b/muse2/muse/CMakeLists.txt @@ -65,6 +65,7 @@ QT4_WRAP_CPP ( muse_moc_headers plugin.h song.h transport.h + trackdrummapupdater.h value.h steprec.h ) @@ -132,6 +133,7 @@ file (GLOB core_source_files thread.cpp ticksynth.cpp track.cpp + trackdrummapupdater.cpp transport.cpp undo.cpp value.cpp diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index f63eb6e2..6a4e7c06 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -81,6 +81,7 @@ #include "tools.h" #include "widgets/unusedwavefiles.h" #include "functions.h" +#include "trackdrummapupdater.h" namespace MusECore { extern void initMidiSynth(); @@ -346,6 +347,7 @@ MusE::MusE(int /*argc*/, char** /*argv*/) : QMainWindow() MusEGlobal::heartBeatTimer->setObjectName("timer"); connect(MusEGlobal::heartBeatTimer, SIGNAL(timeout()), MusEGlobal::song, SLOT(beat())); connect(this, SIGNAL(activeTopWinChanged(MusEGui::TopWin*)), SLOT(activeTopWinChangedSlot(MusEGui::TopWin*))); + new MusECore::TrackDrummapUpdater(); // no need for keeping the reference, the thing autoconnects on its own. #ifdef ENABLE_PYTHON //--------------------------------------------------- diff --git a/muse2/muse/helper.cpp b/muse2/muse/helper.cpp index 05cecc08..7d07a6ce 100644 --- a/muse2/muse/helper.cpp +++ b/muse2/muse/helper.cpp @@ -116,15 +116,12 @@ bool any_event_selected(const set& parts, bool in_range) return !get_events(parts, in_range ? 3 : 1).empty(); } -bool drummaps_almost_equal(DrumMap* one, DrumMap* two, int len) +bool drummaps_almost_equal(const DrumMap* one, const DrumMap* two, int len) { for (int i=0; i parts_at_tick(unsigned tick, const QSet& tracks) return result; } +bool parse_range(const QString& str, int* from, int* to) +{ + int idx = str.indexOf("-"); + if (idx<0) // no "-" in str + { + bool ok; + int i = str.toInt(&ok); + if (!ok) + { + *from=-1; *to=-1; + return false; + } + else + { + *from=i; *to=i; + return true; + } + } + else // there is a "-" in str + { + QString str1=str.mid(0,idx); + QString str2=str.mid(idx+1); + + bool ok; + int i = str1.toInt(&ok); + if (!ok) + { + *from=-1; *to=-1; + return false; + } + else + { + *from=i; + + i = str2.toInt(&ok); + if (!ok) + { + *from=-1; *to=-1; + return false; + } + else + { + *to=i; + return true; + } + } + } +} + +void write_new_style_drummap(int level, Xml& xml, const char* tagname, + DrumMap* drummap, bool* drummap_hidden, bool full) +{ + xml.tag(level++, tagname); + + for (int i=0;i<128;i++) + { + DrumMap* dm = &drummap[i]; + const DrumMap* idm = &iNewDrumMap[i]; + + if ( (dm->name != idm->name) || (dm->vol != idm->vol) || + (dm->quant != idm->quant) || (dm->len != idm->len) || + (dm->lv1 != idm->lv1) || (dm->lv2 != idm->lv2) || + (dm->lv3 != idm->lv3) || (dm->lv4 != idm->lv4) || + (dm->enote != idm->enote) || (dm->mute != idm->mute) || + (drummap_hidden && drummap_hidden[i]) || full) + { + xml.tag(level++, "entry pitch=\"%d\"", i); + + // when any of these "if"s changes, also update the large "if" + // above (this scope's parent) + if (full || dm->name != idm->name) xml.strTag(level, "name", dm->name); + if (full || dm->vol != idm->vol) xml.intTag(level, "vol", dm->vol); + if (full || dm->quant != idm->quant) xml.intTag(level, "quant", dm->quant); + if (full || dm->len != idm->len) xml.intTag(level, "len", dm->len); + if (full || dm->lv1 != idm->lv1) xml.intTag(level, "lv1", dm->lv1); + if (full || dm->lv2 != idm->lv2) xml.intTag(level, "lv2", dm->lv2); + if (full || dm->lv3 != idm->lv3) xml.intTag(level, "lv3", dm->lv3); + if (full || dm->lv4 != idm->lv4) xml.intTag(level, "lv4", dm->lv4); + if (full || dm->enote != idm->enote) xml.intTag(level, "enote", dm->enote); + if (full || dm->mute != idm->mute) xml.intTag(level, "mute", dm->mute); + if (drummap_hidden && + (full || drummap_hidden[i])) xml.intTag(level, "hide", drummap_hidden[i]); + + // anote is ignored anyway, as dm->anote == i, and this is + // already stored in the begin tag (pitch=...) + + // channel and port are ignored as well, as they're not used + // in new-style-drum-mode + + xml.tag(level--, "/entry"); + } + } + + xml.etag(level, tagname); +} + +void read_new_style_drummap(Xml& xml, const char* tagname, + DrumMap* drummap, bool* drummap_hidden) +{ + for (;;) + { + Xml::Token token = xml.parse(); + if (token == Xml::Error || token == Xml::End) + break; + const QString& tag = xml.s1(); + switch (token) + { + case Xml::TagStart: + if (tag == "entry") // then read that entry with a nested loop + { + DrumMap* dm=NULL; + bool* hidden=NULL; + for (;;) // nested loop + { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) + { + case Xml::Error: + case Xml::End: + goto end_of_nested_for; + + case Xml::Attribut: + if (tag == "pitch") + { + int pitch = xml.s2().toInt() & 0x7f; + if (pitch < 0 || pitch > 127) + printf("ERROR: THIS SHOULD NEVER HAPPEN: invalid pitch in read_new_style_drummap()!\n"); + else + { + dm = &drummap[pitch]; + hidden = drummap_hidden ? &drummap_hidden[pitch] : NULL; + } + } + break; + + case Xml::TagStart: + if (dm==NULL) + printf("ERROR: THIS SHOULD NEVER HAPPEN: no valid 'pitch' attribute in tag, but sub-tags follow in read_new_style_drummap()!\n"); + else if (tag == "name") + dm->name = xml.parse(QString("name")); + else if (tag == "vol") + dm->vol = (unsigned char)xml.parseInt(); + else if (tag == "quant") + dm->quant = xml.parseInt(); + else if (tag == "len") + dm->len = xml.parseInt(); + else if (tag == "lv1") + dm->lv1 = xml.parseInt(); + else if (tag == "lv2") + dm->lv2 = xml.parseInt(); + else if (tag == "lv3") + dm->lv3 = xml.parseInt(); + else if (tag == "lv4") + dm->lv4 = xml.parseInt(); + else if (tag == "enote") + dm->enote = xml.parseInt(); + else if (tag == "mute") + dm->mute = xml.parseInt(); + else if (tag == "hide") + { + if (hidden) *hidden = xml.parseInt(); + } + else + xml.unknown("read_new_style_drummap"); + break; + + case Xml::TagEnd: + if (tag == "entry") + goto end_of_nested_for; + + default: + break; + } + } // end of nested loop + end_of_nested_for: ; + } // end of 'if (tag == "entry")' + else + xml.unknown("read_new_style_drummap"); + break; + + case Xml::TagEnd: + if (tag == tagname) + return; + + default: + break; + } + } +} } // namespace MusECore diff --git a/muse2/muse/helper.h b/muse2/muse/helper.h index 8ef39346..2a26c08e 100644 --- a/muse2/muse/helper.h +++ b/muse2/muse/helper.h @@ -44,11 +44,21 @@ QString pitch2string(int v); Part* partFromSerialNumber(int serial); bool any_event_selected(const std::set&, bool in_range=false); -bool drummaps_almost_equal(DrumMap* one, DrumMap* two, int drummap_size=128); +bool drummaps_almost_equal(const DrumMap* one, const DrumMap* two, int drummap_size=128); + +// drummap_hidden may be NULL. +void write_new_style_drummap(int level, Xml& xml, const char* tagname, + DrumMap* drummap, bool* drummap_hidden=NULL, bool full=false); +void read_new_style_drummap(Xml& xml, const char* tagname, + DrumMap* drummap, bool* drummap_hidden=NULL); + QSet parts_at_tick(unsigned tick); QSet parts_at_tick(unsigned tick, const Track* track); QSet parts_at_tick(unsigned tick, const QSet& tracks); + +bool parse_range(const QString& str, int* from, int* to); // returns true if successful, false on error + } namespace MusEGui { diff --git a/muse2/muse/instruments/minstrument.cpp b/muse2/muse/instruments/minstrument.cpp index a01903ae..3876fb28 100644 --- a/muse2/muse/instruments/minstrument.cpp +++ b/muse2/muse/instruments/minstrument.cpp @@ -41,6 +41,8 @@ #include "midictrl.h" #include "gconfig.h" #include "popupmenu.h" +#include "drummap.h" +#include "helper.h" namespace MusECore { @@ -364,6 +366,7 @@ void MidiInstrument::init() MidiController* prog = new MidiController("Program", CTRL_PROGRAM, 0, 0xffffff, 0); _controller->add(prog); _dirty = false; + } MidiInstrument::MidiInstrument() @@ -408,8 +411,20 @@ MidiInstrument::~MidiInstrument() if (_initScript) delete _initScript; + + clear_delete_patch_drummap_mapping(); } +void MidiInstrument::clear_delete_patch_drummap_mapping() +{ + for (std::list::iterator it = patch_drummap_mapping.begin(); + it!=patch_drummap_mapping.end(); it++) + delete[] it->drummap; + + patch_drummap_mapping.clear(); +} + + /* //--------------------------------------------------------- // uniqueCopy @@ -515,7 +530,20 @@ MidiInstrument& MidiInstrument::assign(const MidiInstrument& ins) _name = ins._name; _filePath = ins._filePath; - + + clear_delete_patch_drummap_mapping(); + // do a deep copy + for (std::list::const_iterator it = ins.patch_drummap_mapping.begin(); + it!=ins.patch_drummap_mapping.end(); it++) + { + patch_drummap_mapping_t temp = *it; + temp.drummap=new DrumMap[128]; + for (int i=0;i<128;i++) + temp.drummap[i]=it->drummap[i]; + } + + + // Hmm, dirty, yes? But init sets it to false... //_dirty = ins._dirty; //_dirty = false; @@ -733,6 +761,123 @@ void MidiInstrument::readMidiState(Xml& xml) } } +void MidiInstrument::readDrummaps(Xml& xml) +{ + clear_delete_patch_drummap_mapping(); + + 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 == "entry") + patch_drummap_mapping.push_back(readDrummapsEntry(xml)); + else + xml.unknown("MidiInstrument::readDrummaps"); + break; + + case Xml::TagEnd: + if (tag == "Drummaps") + return; + + default: + break; + } + } + printf("ERROR: THIS CANNOT HAPPEN: exited infinite loop in MidiInstrument::readDrummaps()!\n" + " not returning anything. expect undefined behaviour or even crashes.\n"); +} + +patch_drummap_mapping_t MidiInstrument::readDrummapsEntry(Xml& xml) +{ + using std::list; + + list collection; + DrumMap* drummap=new DrumMap[128]; + for (int i=0;i<128;i++) + drummap[i]=iNewDrumMap[i]; + + for (;;) + { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) + { + case Xml::Error: + case Xml::End: + return patch_drummap_mapping_t(collection, drummap); + + case Xml::TagStart: + if (tag == "patch_collection") + collection.push_back(readDrummapsEntryPatchCollection(xml)); + else if (tag == "drummap") + read_new_style_drummap(xml, "drummap", drummap); + else + xml.unknown("MidiInstrument::readDrummapsEntry"); + break; + + case Xml::TagEnd: + if (tag == "entry") + return patch_drummap_mapping_t(collection, drummap); + + default: + break; + } + } + printf("ERROR: THIS CANNOT HAPPEN: exited infinite loop in MidiInstrument::readDrummapsEntry()!\n" + " not returning anything. expect undefined behaviour or even crashes.\n"); + return patch_drummap_mapping_t(); +} + +patch_collection_t MidiInstrument::readDrummapsEntryPatchCollection(Xml& xml) +{ + int first_prog=0, last_prog=256; // this means: + int first_lbank=0, last_lbank=256; // "does not matter" + int first_hbank=0, last_hbank=256; + + for (;;) + { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) + { + case Xml::Error: + case Xml::End: + return patch_collection_t(-1,-1,-1,-1,-1,-1); // an invalid collection + + case Xml::TagStart: + xml.unknown("MidiInstrument::readDrummapsEntryPatchCollection"); + break; + + case Xml::Attribut: + if (tag == "prog") + parse_range(xml.s2(), &first_prog, &last_prog); + else if (tag == "lbank") + parse_range(xml.s2(), &first_lbank, &last_lbank); + else if (tag == "hbank") + parse_range(xml.s2(), &first_hbank, &last_hbank); + break; + + case Xml::TagEnd: + if (tag == "patch_collection") + return patch_collection_t(first_prog, last_prog, first_lbank, last_lbank, first_hbank, last_hbank); + + default: + break; + } + } + + printf("ERROR: THIS CANNOT HAPPEN: exited infinite loop in MidiInstrument::readDrummapsEntryPatchCollection()!\n" + " not returning anything. expect undefined behaviour or even crashes.\n"); +} + + //--------------------------------------------------------- // read //--------------------------------------------------------- @@ -785,6 +930,9 @@ void MidiInstrument::read(Xml& xml) _controller->add(mc); } + else if (tag == "Drummaps") { + readDrummaps(xml); + } else if (tag == "Init") readEventList(xml, _midiInit, "Init"); else if (tag == "Reset") @@ -794,7 +942,7 @@ void MidiInstrument::read(Xml& xml) else if (tag == "InitScript") { if (_initScript) delete _initScript; - QByteArray ba = xml.parse1().toLatin1(); + QByteArray ba = xml.parse1().toLatin1(); const char* istr = ba.constData(); int len = strlen(istr) +1; if (len > 1) { @@ -998,4 +1146,40 @@ void MidiInstrument::populatePatchPopup(MusEGui::PopupMenu* menu, int chan, MTyp } +const DrumMap* MidiInstrument::drummap_for_patch(int patch) const +{ + using std::list; + + int program = (patch & 0x0000FF); + int lbank = (patch & 0x00FF00) >> 8; + int hbank = (patch & 0xFF0000) >> 16; + + for (list::const_iterator it=patch_drummap_mapping.begin(); + it!=patch_drummap_mapping.end(); it++) + { + for (list::const_iterator it2=it->affected_patches.begin(); + it2!=it->affected_patches.end(); it2++) + { + // if the entry matches our patch + if ( (program >= it2->first_program && program <= it2->last_program) && + (hbank >= it2->first_hbank && hbank <= it2->last_hbank) && + (lbank >= it2->first_lbank && lbank <= it2->last_lbank) ) + { + return it->drummap; + } + } + } + + // if nothing was found + return iNewDrumMap; +} + +patch_drummap_mapping_t::patch_drummap_mapping_t() +{ + drummap=new DrumMap[128]; + for (int i=0;i<128;i++) + drummap[i]=iNewDrumMap[i]; +} + + } // namespace MusECore diff --git a/muse2/muse/instruments/minstrument.h b/muse2/muse/instruments/minstrument.h index 385e67b4..9a65598b 100644 --- a/muse2/muse/instruments/minstrument.h +++ b/muse2/muse/instruments/minstrument.h @@ -40,6 +40,7 @@ class MidiControllerList; class MidiPort; class MidiPlayEvent; class Xml; +class DrumMap; //--------------------------------------------------------- @@ -80,6 +81,43 @@ struct SysEx { unsigned char* data; }; + + +struct patch_collection_t +{ + int first_program; + int last_program; + int first_hbank; + int last_hbank; + int first_lbank; + int last_lbank; + + patch_collection_t(int p1=0, int p2=127, int l1=0, int l2=127, int h1=0, int h2=127) + { + first_program=p1; + last_program=p2; + first_lbank=l1; + last_lbank=l2; + first_hbank=h1; + last_hbank=h2; + } + +}; + +struct patch_drummap_mapping_t +{ + std::list affected_patches; + DrumMap* drummap; + + patch_drummap_mapping_t(const std::list& a, DrumMap* d) + { + affected_patches=a; + drummap=d; + } + + patch_drummap_mapping_t(); +}; + //--------------------------------------------------------- // MidiInstrument //--------------------------------------------------------- @@ -88,6 +126,7 @@ class MidiInstrument { PatchGroupList pg; MidiControllerList* _controller; QList _sysex; + std::list patch_drummap_mapping; bool _dirty; int _nullvalue; @@ -103,6 +142,12 @@ class MidiInstrument { char* _initScript; QString _name; QString _filePath; + + void clear_delete_patch_drummap_mapping(); + + void readDrummaps(Xml& xml); + patch_drummap_mapping_t readDrummapsEntry(Xml& xml); + patch_collection_t readDrummapsEntryPatchCollection(Xml& xml); public: MidiInstrument(); @@ -123,6 +168,8 @@ class MidiInstrument { void removeSysex(SysEx* sysex) { _sysex.removeAll(sysex); } void addSysex(SysEx* sysex) { _sysex.append(sysex); } + const DrumMap* drummap_for_patch(int patch) const; + EventList* midiInit() const { return _midiInit; } EventList* midiReset() const { return _midiReset; } EventList* midiState() const { return _midiState; } diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp index 4c033946..ad0226da 100644 --- a/muse2/muse/midiedit/dcanvas.cpp +++ b/muse2/muse/midiedit/dcanvas.cpp @@ -1008,6 +1008,19 @@ void DrumCanvas::mapChanged(int spitch, int dpitch) using MusEGlobal::global_drum_ordering_t; using MusEGlobal::global_drum_ordering; + for (QSet::iterator it=instrument_map[spitch].tracks.begin(); + it!=instrument_map[spitch].tracks.end(); it++) + { + if (dynamic_cast(*it)) + dynamic_cast(*it)->set_drummap_ordering_tied_to_patch(false); + } + for (QSet::iterator it=instrument_map[dpitch].tracks.begin(); + it!=instrument_map[dpitch].tracks.end(); it++) + { + if (dynamic_cast(*it)) + dynamic_cast(*it)->set_drummap_ordering_tied_to_patch(false); + } + MusECore::DrumMap dm_temp = ourDrumMap[spitch]; instrument_number_mapping_t im_temp = instrument_map[spitch]; @@ -1450,9 +1463,13 @@ void DrumCanvas::propagate_drummap_change(int instr, bool update_druminmap) for (QSet::const_iterator it = tracks.begin(); it != tracks.end(); it++) { - dynamic_cast(*it)->drummap()[index] = ourDrumMap[instr]; + MusECore::MidiTrack* mt=dynamic_cast(*it); + // if we're not only changing "mute" state... + if (!mt->drummap()[index].almost_equals(ourDrumMap[instr])) + mt->set_drummap_tied_to_patch(false); + mt->drummap()[index] = ourDrumMap[instr]; if (update_druminmap) - dynamic_cast(*it)->update_drum_in_map(); + mt->update_drum_in_map(); } } diff --git a/muse2/muse/midiedit/dlist.cpp b/muse2/muse/midiedit/dlist.cpp index 2eb5e64a..fc6384f7 100644 --- a/muse2/muse/midiedit/dlist.cpp +++ b/muse2/muse/midiedit/dlist.cpp @@ -401,6 +401,7 @@ void DList::viewMousePressEvent(QMouseEvent* ev) { MusECore::MidiTrack* mt = dynamic_cast(*it); mt->drummap()[mt->map_drum_in(val)].enote=dm->enote; + mt->set_drummap_tied_to_patch(false); } // propagating this is unneccessary as it's already done. // updating the drumInmap is unneccessary, as the propagate call below @@ -900,6 +901,7 @@ void DList::pitchEdited() { MusECore::MidiTrack* mt = dynamic_cast(*it); mt->drummap()[mt->map_drum_in(val)].enote=editEntry->enote; + mt->set_drummap_tied_to_patch(false); } // propagating this is unneccessary as it's already done. // updating the drumInmap is unneccessary, as the propagate call below diff --git a/muse2/muse/midiedit/drumedit.cpp b/muse2/muse/midiedit/drumedit.cpp index 3bb48705..1f159d1a 100644 --- a/muse2/muse/midiedit/drumedit.cpp +++ b/muse2/muse/midiedit/drumedit.cpp @@ -644,7 +644,7 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un void DrumEdit::songChanged1(int bits) { - if(_isDeleting) // Ignore while while deleting to prevent crash. + if(_isDeleting) // Ignore while deleting to prevent crash. return; if (bits & SC_SOLO) diff --git a/muse2/muse/midiedit/drummap.cpp b/muse2/muse/midiedit/drummap.cpp index 2705a252..d86bcd65 100644 --- a/muse2/muse/midiedit/drummap.cpp +++ b/muse2/muse/midiedit/drummap.cpp @@ -43,15 +43,13 @@ namespace MusECore { const DrumMap blankdm = { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 127, 127, false }; -// this map must have 128 entries, as it's used for initalising new-style-drummaps as well. -// new-style-drummaps only have 128 entries. also, the every "out-note" ("anote") must be -// represented exactly once in that map, and there may be no duplicate or unused "out-notes". -// reason: the track's drummap are inited as follows: iterate through the full idrumMap[], -// tracks_drummap[ idrumMap[i].anote ] = idrumMap[i] -// if you ever want to change this, you will need to go through track.cpp/.h and -// {dlist,dcanvas,drumedit,drummap}{.cpp,.h} (and possibly some more) and find every usage -// of idrumMap by new style drummaps, and fix the problem. a possible fix would be duplicating -// idrumMap, change idrumMap, and use the duplicate for the new style stuff instead. +// this map should have 128 entries, as it's used for initalising iNewDrumMap as well. +// iNewDrumMap only has 128 entries. also, the every "out-note" ("anote") should be +// represented exactly once in idrumMap, and there shall be no duplicate or unused +// "out-notes". +// reason: iNewDrumMap is inited as follows: iterate through the full idrumMap[], +// iNewDrumMap[ idrumMap[i].anote ] = idrumMap[i] +// if you ever want to change this, you will need to fix the initNewDrumMap() function. const DrumMap idrumMap[DRUM_MAPSIZE] = { { QString("Acoustic Bass Drum"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 35, 35, false }, { QString("Bass Drum 1"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 36, 36, false }, @@ -261,6 +259,55 @@ const DrumMap idrumMap[DRUM_MAPSIZE] = { { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 34, 34, false } }; +DrumMap iNewDrumMap[128]; + +void initNewDrumMap() +{ + bool done[128]; + for (int i=0;i<128;i++) done[i]=false; + + for (int i=0;i= 128) + printf("ERROR: THIS SHOULD NEVER HAPPEN: idrumMap[%i].anote is not within 0..127!\n", idx); + else + { + if (done[idx]==true) + { + printf("ERROR: iNewDrumMap[%i] is already initalized!\n" + " this will be probably not a problem, but some programmer didn't read\n" + " flo's comment at drummap.cpp, above idrumMap[].\n", idx); + } + else + { + iNewDrumMap[idx]=idrumMap[i]; + done[idx]=true; + } + } + } + + for (int i=0;i<128;i++) + { + if (done[i]==false) + { + printf("ERROR: iNewDrumMap[%i] is uninitalized!\n" + " this will be probably not a problem, but some programmer didn't read\n" + " flo's comment at drummap.cpp, above idrumMap[].\n", i); + iNewDrumMap[i].name=""; + iNewDrumMap[i].vol=100; + iNewDrumMap[i].quant=16; + iNewDrumMap[i].len=32; + iNewDrumMap[i].lv1=70; + iNewDrumMap[i].lv2=90; + iNewDrumMap[i].lv3=127; + iNewDrumMap[i].lv4=110; + iNewDrumMap[i].enote=i; + iNewDrumMap[i].anote=i; + } + } +} + //--------------------------------------------------------- // initDrumMap @@ -332,6 +379,14 @@ bool DrumMap::operator==(const DrumMap& map) const && mute == map.mute; } +bool DrumMap::almost_equals(const DrumMap& map) const +{ + DrumMap tmp=map; + tmp.mute=this->mute; + return tmp==*this; +} + + //--------------------------------------------------------- // writeDrumMap //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/drummap.h b/muse2/muse/midiedit/drummap.h index 3b6ffaf3..7f28b068 100644 --- a/muse2/muse/midiedit/drummap.h +++ b/muse2/muse/midiedit/drummap.h @@ -49,12 +49,15 @@ struct DrumMap { bool operator==(const DrumMap& map) const; bool operator!=(const DrumMap& map) const { return !operator==(map); } + bool almost_equals(const DrumMap& map) const; }; -// please let this at "128". idrumMap must have length 128 (see drummap.cpp for details) +// please let this at "128". idrumMap should have length 128 (see drummap.cpp for details) #define DRUM_MAPSIZE 128 -extern const DrumMap idrumMap[DRUM_MAPSIZE]; //FINDMICH dummy! +extern DrumMap iNewDrumMap[128]; +extern void initNewDrumMap(); + extern void initDrumMap(); extern void writeDrumMap(int level, Xml& xml, bool external); extern void readDrumMap(Xml& xml, bool external); diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index c10adafd..055134e2 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -4686,8 +4686,8 @@ void ScoreCanvas::add_new_parts(const std::map< MusECore::Part*, std::set o my record flag handling - * o once, using super glue while a score editor displaying the glued + * x my record flag handling + * * once, using super glue while a score editor displaying the glued * parts is open let muse segfault. this may or may not be fixed * now. check! * state of revision #1337: no segfaults, but the score editors diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp index 484e2d42..69900bbc 100644 --- a/muse2/muse/song.cpp +++ b/muse2/muse/song.cpp @@ -2074,6 +2074,7 @@ void Song::clear(bool signal, bool clear_all) // _tempo = 500000; // default tempo 120 dirty = false; initDrumMap(); + initNewDrumMap(); if (signal) { emit loopChanged(false); recordChanged(false); diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp index 4dd2e0c5..595a25e7 100644 --- a/muse2/muse/track.cpp +++ b/muse2/muse/track.cpp @@ -34,6 +34,8 @@ #include "globaldefs.h" #include "route.h" #include "drummap.h" +#include "midictrl.h" +#include "helper.h" namespace MusECore { @@ -618,19 +620,28 @@ void MidiTrack::init() _recEcho = true; } +void MidiTrack::init_drum_ordering() +{ + // first display entries with non-empty names, then with empty names. + + remove_ourselves_from_drum_ordering(); + + for (int i=0;i<128;i++) + if (_drummap[i].name!="" && _drummap[i].name!="?") // non-empty name? + MusEGlobal::global_drum_ordering.push_back(std::pair(this,i)); + + for (int i=0;i<128;i++) + if (!(_drummap[i].name!="" && _drummap[i].name!="?")) // empty name? + MusEGlobal::global_drum_ordering.push_back(std::pair(this,i)); +} + void MidiTrack::init_drummap(bool write_ordering) { for (int i=0;i<128;i++) - { - int idx=idrumMap[i].anote; - if (idx < 0 || idx >= 128) - printf ("ERROR: THIS SHOULD NEVER HAPPEN: idrumMap[%i].anote is not within 0..127!\n", idx); - else - _drummap[idx]=idrumMap[i]; - - if (write_ordering) - MusEGlobal::global_drum_ordering.push_back(std::pair(this,idx)); - } + _drummap[i]=iNewDrumMap[i]; + + if (write_ordering) + init_drum_ordering(); update_drum_in_map(); @@ -638,6 +649,7 @@ void MidiTrack::init_drummap(bool write_ordering) _drummap_hidden[i]=false; _drummap_tied_to_patch=true; + _drummap_ordering_tied_to_patch=true; } void MidiTrack::update_drum_in_map() @@ -945,62 +957,14 @@ void MidiTrack::writeOurDrumSettings(int level, Xml& xml) const writeOurDrumMap(level, xml, false); xml.intTag(level, "tied", _drummap_tied_to_patch); + xml.intTag(level, "ordering_tied", _drummap_ordering_tied_to_patch); xml.etag(level, "our_drum_settings"); } void MidiTrack::writeOurDrumMap(int level, Xml& xml, bool full) const { - xml.tag(level++, "our_drummap"); - - for (int i=0;i<128;i++) - { - int j; - for (j=0;j<128;j++) - if (idrumMap[j].anote == i) break; - - if (j==128) - printf("THIS SHOULD NEVER HAPPEN: couldn't find initial drum map entry in MidiTrack::writeOurDrumMap()\n"); - else - { - DrumMap* dm = &_drummap[i]; - const DrumMap* idm = &idrumMap[j]; - - if ( (dm->name != idm->name) || (dm->vol != idm->vol) || - (dm->quant != idm->quant) || (dm->len != idm->len) || - (dm->lv1 != idm->lv1) || (dm->lv2 != idm->lv2) || - (dm->lv3 != idm->lv3) || (dm->lv4 != idm->lv4) || - (dm->enote != idm->enote) || (dm->mute != idm->mute) || - _drummap_hidden[i] || full) - { - xml.tag(level++, "entry pitch=\"%d\"", i); - - // when any of these "if"s changes, also update the large "if" - // above (this scope's parent) - if (full || dm->name != idm->name) xml.strTag(level, "name", dm->name); - if (full || dm->vol != idm->vol) xml.intTag(level, "vol", dm->vol); - if (full || dm->quant != idm->quant) xml.intTag(level, "quant", dm->quant); - if (full || dm->len != idm->len) xml.intTag(level, "len", dm->len); - if (full || dm->lv1 != idm->lv1) xml.intTag(level, "lv1", dm->lv1); - if (full || dm->lv2 != idm->lv2) xml.intTag(level, "lv2", dm->lv2); - if (full || dm->lv3 != idm->lv3) xml.intTag(level, "lv3", dm->lv3); - if (full || dm->lv4 != idm->lv4) xml.intTag(level, "lv4", dm->lv4); - if (full || dm->enote != idm->enote) xml.intTag(level, "enote", dm->enote); - if (full || dm->mute != idm->mute) xml.intTag(level, "mute", dm->mute); - if (full || _drummap_hidden[i]) xml.intTag(level, "hide", _drummap_hidden[i]); - - // anote is ignored anyway, as dm->anote == i, and this is - // already stored in the begin tag (pitch=...) - - // channel and port are ignored as well, as they're not used - // in new-style-drum-mode - - xml.tag(level--, "/entry"); - } - } - } - - xml.etag(level, "our_drummap"); + write_new_style_drummap(level, xml, "our_drummap", _drummap, _drummap_hidden, full); } //--------------------------------------------------------- @@ -1095,6 +1059,8 @@ void MidiTrack::readOurDrumSettings(Xml& xml) case Xml::TagStart: if (tag == "tied") _drummap_tied_to_patch = xml.parseInt(); + else if (tag == "ordering_tied") + _drummap_ordering_tied_to_patch = xml.parseInt(); else if (tag == "our_drummap") readOurDrumMap(xml); else @@ -1115,98 +1081,9 @@ void MidiTrack::readOurDrumMap(Xml& xml, bool dont_init) { if (!dont_init) init_drummap(false); _drummap_tied_to_patch=false; - - for (;;) - { - Xml::Token token = xml.parse(); - if (token == Xml::Error || token == Xml::End) - break; - const QString& tag = xml.s1(); - switch (token) - { - case Xml::TagStart: - if (tag == "entry") // then read that entry with a nested loop - { - DrumMap* dm=NULL; - bool* hidden=NULL; - for (;;) // nested loop - { - Xml::Token token = xml.parse(); - const QString& tag = xml.s1(); - switch (token) - { - case Xml::Error: - case Xml::End: - goto end_of_nested_for; - - case Xml::Attribut: - if (tag == "pitch") - { - int pitch = xml.s2().toInt() & 0x7f; - if (pitch < 0 || pitch > 127) - printf("ERROR: THIS SHOULD NEVER HAPPEN: invalid pitch in MidiTrack::readOurDrumMap()!\n"); - else - { - dm = &_drummap[pitch]; - hidden = &_drummap_hidden[pitch]; - } - } - break; - - case Xml::TagStart: - if (dm==NULL) - printf("ERROR: THIS SHOULD NEVER HAPPEN: no valid 'pitch' attribute in tag, but sub-tags follow in MidiTrack::readOurDrumMap()!\n"); - else if (tag == "name") - dm->name = xml.parse(QString("name")); - else if (tag == "vol") - dm->vol = (unsigned char)xml.parseInt(); - else if (tag == "quant") - dm->quant = xml.parseInt(); - else if (tag == "len") - dm->len = xml.parseInt(); - else if (tag == "lv1") - dm->lv1 = xml.parseInt(); - else if (tag == "lv2") - dm->lv2 = xml.parseInt(); - else if (tag == "lv3") - dm->lv3 = xml.parseInt(); - else if (tag == "lv4") - dm->lv4 = xml.parseInt(); - else if (tag == "enote") - dm->enote = xml.parseInt(); - else if (tag == "mute") - dm->mute = xml.parseInt(); - else if (tag == "hide") - *hidden = xml.parseInt(); - else - xml.unknown("MidiTrack::readOurDrumMap"); - break; - - case Xml::TagEnd: - if (tag == "entry") - goto end_of_nested_for; - - default: - break; - } - } // end of nested loop - end_of_nested_for: ; - } // end of 'if (tag == "entry")' - else - xml.unknown("MidiTrack::readOurDrumMap"); - break; - - case Xml::TagEnd: - if (tag == "our_drummap") - { - update_drum_in_map(); - return; - } - - default: - break; - } - } + _drummap_ordering_tied_to_patch=false; + read_new_style_drummap(xml, "our_drummap", _drummap, _drummap_hidden); + update_drum_in_map(); } @@ -1395,4 +1272,69 @@ void Track::writeRouting(int level, Xml& xml) const } } +int MidiTrack::getFirstControllerValue(int ctrl, int def) +{ + int val=def; + unsigned tick=-1; // maximum integer + + for (iPart pit=parts()->begin(); pit!=parts()->end(); pit++) + { + Part* part=pit->second; + if (part->tick() > tick) break; // ignore this and the rest. we won't find anything new. + for (iEvent eit=part->events()->begin(); eit!=part->events()->end(); eit++) + { + if (eit->first+part->tick() >= tick) break; + // else if (eit->first+part->tick() < tick) and + if (eit->second.type()==Controller && eit->second.dataA()==ctrl) + { + val = eit->second.dataB(); + tick = eit->first+part->tick(); + break; + } + } + } + + return val; +} + + +// returns true if the autoupdate changed something +bool MidiTrack::auto_update_drummap() +{ + if (_drummap_tied_to_patch) + { + int patch = getFirstControllerValue(CTRL_PROGRAM,0); + const DrumMap* new_drummap = MusEGlobal::midiPorts[_outPort].instrument()->drummap_for_patch(patch); + + if (!drummaps_almost_equal(new_drummap, this->drummap(), 128)) + { + for (int i=0;i<128;i++) + { + bool temp_mute=_drummap[i].mute; + _drummap[i]=new_drummap[i]; + _drummap[i].mute=temp_mute; + } + + if (_drummap_ordering_tied_to_patch) + init_drum_ordering(); + + return true; + } + } + + return false; +} + +void MidiTrack::set_drummap_tied_to_patch(bool val) +{ + _drummap_tied_to_patch=val; + if (val) auto_update_drummap(); +} + +void MidiTrack::set_drummap_ordering_tied_to_patch(bool val) +{ + _drummap_ordering_tied_to_patch=val; + if (val && _drummap_tied_to_patch) init_drum_ordering(); +} + } // namespace MusECore diff --git a/muse2/muse/track.h b/muse2/muse/track.h index f2e12e3a..1df8cad0 100644 --- a/muse2/muse/track.h +++ b/muse2/muse/track.h @@ -236,11 +236,13 @@ class MidiTrack : public Track { DrumMap* _drummap; // _drummap[foo].anote is always equal to foo bool* _drummap_hidden; // _drummap und _drummap_hidden will be an array[128] bool _drummap_tied_to_patch; //if true, changing patch also changes drummap + bool _drummap_ordering_tied_to_patch; //if true, changing patch also changes drummap-ordering int drum_in_map[128]; void init(); void init_drummap(bool write_ordering); // function without argument in public void remove_ourselves_from_drum_ordering(); + void init_drum_ordering(); void writeOurDrumSettings(int level, Xml& xml) const; void readOurDrumSettings(Xml& xml); @@ -310,6 +312,8 @@ class MidiTrack : public Track { virtual bool canRecord() const { return true; } static void setVisible(bool t) { _isVisible = t; } static bool visible() { return _isVisible; } + + int getFirstControllerValue(int ctrl, int def=-1); void setClef(clefTypes i) { clefType = i; } clefTypes getClef() { return clefType; } @@ -320,6 +324,12 @@ class MidiTrack : public Track { void update_drum_in_map(); void init_drummap() { init_drummap(false); } // function with argument in private + + bool auto_update_drummap(); + void set_drummap_tied_to_patch(bool); + bool drummap_tied_to_patch() { return _drummap_tied_to_patch; } + void set_drummap_ordering_tied_to_patch(bool); + bool drummap_ordering_tied_to_patch() { return _drummap_ordering_tied_to_patch; } //void writeOurDrumSettings(int level, Xml& xml) const; // above in private: //void readOurDrumSettings(Xml& xml); // above in private: diff --git a/muse2/muse/trackdrummapupdater.cpp b/muse2/muse/trackdrummapupdater.cpp new file mode 100644 index 00000000..35d5c056 --- /dev/null +++ b/muse2/muse/trackdrummapupdater.cpp @@ -0,0 +1,61 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: trackdrummapupdater.cpp,v 1.59.2.52 2011/12/27 20:25:58 flo93 Exp $ +// +// (C) Copyright 2011 Florian Jung (florian.a.jung (at) web.de) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +//========================================================= + +#include "trackdrummapupdater.h" +#include "song.h" +#include "globals.h" + +namespace MusECore { + +using MusEGlobal::song; + +TrackDrummapUpdater::TrackDrummapUpdater() +{ + connect(song,SIGNAL(songChanged(int)), this, SLOT(songChanged(int))); +} + +void TrackDrummapUpdater::songChanged(int flags) +{ + if (flags & (SC_TRACK_INSERTED | SC_TRACK_REMOVED | SC_TRACK_MODIFIED | + SC_PART_INSERTED | SC_PART_REMOVED | SC_PART_MODIFIED | + SC_EVENT_INSERTED | SC_EVENT_REMOVED | SC_EVENT_MODIFIED ) ) + { + bool changed=false; + for (iTrack t=song->tracks()->begin(); t!=song->tracks()->end(); t++) + { + MidiTrack* track=dynamic_cast(*t); + if (track && track->auto_update_drummap()) + changed=true; + } + + if (changed) + { + // allow recursion. there will be no more recursion, because this + // is only executed when something other than SC_DRUMMAP happens + song->update(SC_DRUMMAP, true); + } + + } +} + +} //namespace MusECore diff --git a/muse2/muse/trackdrummapupdater.h b/muse2/muse/trackdrummapupdater.h new file mode 100644 index 00000000..caa2ac28 --- /dev/null +++ b/muse2/muse/trackdrummapupdater.h @@ -0,0 +1,43 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: trackdrummapupdater.h,v 1.59.2.52 2011/12/27 20:25:58 flo93 Exp $ +// +// (C) Copyright 2011 Florian Jung (florian.a.jung (at) web.de) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +//========================================================= + +#ifndef __TRACKDRUMMAPUPDATER_H__ +#define __TRACKDRUMMAPUPDATER_H__ + +#include + +namespace MusECore { + +class TrackDrummapUpdater : public QObject +{ + Q_OBJECT + + public: + TrackDrummapUpdater(); + + private slots: + void songChanged(int flags); +}; + +} //namespace MusECore +#endif diff --git a/muse2/share/instruments/gs.idf b/muse2/share/instruments/gs.idf index 3368b7c9..1e8a54c0 100644 --- a/muse2/share/instruments/gs.idf +++ b/muse2/share/instruments/gs.idf @@ -214,5 +214,372 @@ + + + + + High Q + Slap + Scratch Push + Scratch Pull + Sticks + Square Click + Metronome Click + Metronome Bell + Kick Drum 2 + Kick Drum 1 + Snare Drum 1 + Snare Drum 2 + Low Tom 2 + Low Tom 1 + Mid Tom 2 + Mid Tom 1 + High Tom 2 + High Tom 1 + Shaker + Jingle Bell + Belltree + Castanets + Mute Surdo + Open Surdo + + + + + + + High Q + Slap + Scratch Push + Scratch Pull + Sticks + Square Click + Metronome Click + Metronome Bell + Kick Drum 2 + Kick Drum 1 + Snare Drum 1 + Snare Drum 2 + Room Low Tom 2 + Room Low Tom 1 + Room Mid Tom 2 + Room Mid Tom 1 + Room High Tom 2 + Room High Tom 1 + Shaker + Jingle Bell + Belltree + Castanets + Mute Surdo + Open Surdo + + + + + + + High Q + Slap + Scratch Push + Scratch Pull + Sticks + Square Click + Metronome Click + Metronome Bell + Kick Drum 2 + Mondo Kick + Gated Snare + Snare Drum 2 + Room Low Tom 2 + Room Low Tom 1 + Room Mid Tom 2 + Room Mid Tom 1 + Room High Tom 2 + Room High Tom 1 + Shaker + Jingle Bell + Belltree + Castanets + Mute Surdo + Open Surdo + + + + + + + High Q + Slap + Scratch Push + Scratch Pull + Sticks + Square Click + Metronome Click + Metronome Bell + Kick Drum 2 + Elec. Bass Drum + Elec. Snare + Gated Snare + Elec. Low Tom 2 + Elec. Low Tom 1 + Elec. Mid Tom 2 + Elec. Mid Tom 1 + Elec. High Tom 2 + Elec. High Tom 1 + Reverse Cymbal + Shaker + Jingle Bell + Belltree + Castanets + Mute Surdo + Open Surdo + + + + + + + High Q + Slap + Scratch Push + Scratch Pull + Sticks + Square Click + Metronome Click + Metronome Bell + Kick Drum 2 + 808 Bass Drum + 808 Rim Shot + 808 Snare Drum + Snare Drum 2 + 808 Low Tom 2 + 808 Closed Hi-Hat + 808 Low Tom 1 + 808 Pedal Hi-Hat + 808 Tom 2 + 808 Open Hi-Hat + 808 Mid Tom 1 + 808 High Tom 2 + 808 Cymbal + 808 High Tom 1 + Reverse Cymbal + 808 Cowbell + 808 High Conga + 808 Mid Conga + 808 Low Conga + 808 Maracas + Shaker + Jingle Bell + Belltree + Castanets + Mute Surdo + Open Surdo + + + + + + + High Q + Slap + Scratch Push + Scratch Pull + Sticks + Square Click + Metronome Click + Metronome Bell + Jazz Bass Drum 2 + Jazz Bass Drum 1 + Snare Drum 1 + Snare Drum 2 + Low Tom 2 + Low Tom 1 + Mid Tom 2 + Mid Tom 1 + High Tom 2 + High Tom 1 + Shaker + Jingle Bell + Belltree + Castanets + Mute Surdo + Open Surdo + + + + + + + High Q + Slap + Scratch Push + Scratch Pull + Sticks + Square Click + Metronome Click + Metronome Bell + Jazz Bass Drum 2 + Jazz Bass Drum 1 + Brush Tap + Brush Slap + Brush Swirl + Low Tom 2 + Low Tom 1 + Mid Tom 2 + Mid Tom 1 + High Tom 2 + High Tom 1 + Shaker + Jingle Bell + Belltree + Castanets + Mute Surdo + Open Surdo + + + + + + + Closed Hi-Hat + Pedal Hi-Hat + Open Hi-Hat + Ride Cymbal + Sticks + Square Click + Metronome Click + Metronome Bell + Concert Bass Drum 2 + Concert Bass Drum 1 + Concert Snare Drum + Castanets + Concert Snare Drum + Timpani F + Timpani F# + Timpani G + Timpani G# + Timpani A + Timpani A# + Timpani B + Timpani C + Timpani C# + Timpani D + Timpani D# + Timpani E + Timpani F + Concert Cymbal 2 + Concert Cymbal 1 + Shaker + Jingle Bell + Belltree + Castanets + Mute Surdo + Open Surdo + + + + + + + + + + + High Q + Slap + Scratch Push + Scratch Pull + Sticks + Square Click + Metronome Click + Metronome Bell + Guitar Fret Noise + Guitar Cut Noise Up + Guitar Cut Noise Down + Double Bass String Slap + Flute Key Click + Laughing + Screaming + Punch + Heartbeat + Footsteps 1 + Footsteps 2 + Applause + Door Creaking + Door Closing + Scratch + Wind Chimes + Car Engine + Car Brakes + Car Passing + Car Crash + Siren + Train + Jet Plane + Helicopter + Starship + Gun Shot + Machine Gun + Laser Gun + Explosion + Dog Bark + Horse Gallop + Birds Tweet + Rain + Thunder + Wind + Seashore + Stream + Bubble + + + + + + + + + + + + + Quijada + + Laughing + Screaming + Punch + Heartbeat + Footsteps 1 + Footsteps 2 + Applause + Door Creaking + Door Closing + Scratch + Wind Chimes + Car Engine + Car Brakes + Car Passing + Car Crash + Siren + Train + Jet Plane + Helicopter + Starship + Gun Shot + Machine Gun + Laser Gun + Explosion + Dog Bark + Horse Gallop + Birds Tweet + Rain + Thunder + Wind + Seashore + Stream + Bubble + + + diff --git a/muse2/share/instruments/xg.idf b/muse2/share/instruments/xg.idf index 4f5f586e..c281df66 100644 --- a/muse2/share/instruments/xg.idf +++ b/muse2/share/instruments/xg.idf @@ -602,5 +602,506 @@ + + + + + + Mute Surdo + Open Surdo + High Q + Whip Slap + Scratch Push + Scratch Pull + Finger Snap + Click Noise + Metronome Click + Metronome Bell + Seq Click L + Seq Click H + Brush Tap + Brush Swirl L + Brush Slap + Brush Swirl H + Snare Roll + Castanet + Snare L + Sticks + Bass Drum L + Open Rim Shot + Bass Drum M + Bass Drum H + Snare M + Snare H + Shaker + Jingle Bell + Belltree + + + + + + + Mute Surdo + Open Surdo + High Q + Whip Slap + Scratch Push + Scratch Pull + Finger Snap + Click Noise + Metronome Click + Metronome Bell + Seq Click L + Seq Click H + Brush Tap + Brush Swirl L + Brush Slap + Brush Swirl H + Snare Roll 2 + Castanet + Snare L 2 + Sticks + Bass Drum L + Open Rim Shot 2 + Bass Drum M 2 + Bass Drum H 2 + Snare M 2 + Snare H 2 + Shaker + Jingle Bell + Belltree + + + + + + + Mute Surdo + Open Surdo + High Q + Whip Slap + Scratch Push + Scratch Pull + Finger Snap + Click Noise + Metronome Click + Metronome Bell + Seq Click L + Seq Click H + Brush Tap + Brush Swirl L + Brush Slap + Brush Swirl H + Snare Roll + Castanet + Snare L + Sticks + Bass Drum L + Open Rim Shot + Bass Drum M + Room Bass Drum + Room Snare L + Room Snare H + Room Tom 1 + Room Tom 2 + Room Tom 3 + Room Tom 4 + Room Tom 5 + Room Tom 6 + Shaker + Jingle Bell + Belltree + + + + + + + Mute Surdo + Open Surdo + High Q + Whip Slap + Scratch Push + Scratch Pull + Finger Snap + Click Noise + Metronome Click + Metronome Bell + Seq Click L + Seq Click H + Brush Tap + Brush Swirl L + Brush Slap + Brush Swirl H + Snare Roll + Castanet + Rock Snare M + Sticks + Rock Bass Drum M + Open Rim Shot + Bass Drum H 3 + Rock Bass Drum + Rock Snare L + Rock Snare Rim + Rock Tom 1 + Rock Tom 2 + Rock Tom 3 + Rock Tom 4 + Rock Tom 5 + Rock Tom 6 + Shaker + Jingle Bell + Belltree + + + + + + + Mute Surdo + Open Surdo + High Q + Whip Slap + Scratch Push + Scratch Pull + Finger Snap + Click Noise + Metronome Click + Metronome Bell + Seq Click L + Seq Click H + Brush Tap + Brush Swirl L + Brush Slap + Reverse Cymbal + Snare Roll + High Q + Snare M + Sticks + Bass Drum H 4 + Open Rim Shot + Rock Bass Drum + Gated Bass Drum + Rock Snare L + Rock Snare H + Elec. Tom 1 + Elec. Tom 2 + Elec. Tom 3 + Elec. Tom 4 + Elec. Tom 5 + Elec. Tom 6 + Scratch Push + Scratch Pull + Shaker + Jingle Bell + Belltree + + + + + + + Mute Surdo + Open Surdo + High Q + Whip Slap + Scratch Push + Scratch Pull + Finger Snap + Click Noise + Metronome Click + Metronome Bell + Seq Click L + Seq Click H + Brush Tap + Brush Swirl L + Brush Slap + Reverse Cymbal + Snare Roll + High Q + Rock Snare H + Sticks + Bass Drum M + Open Rim Shot + Analog Bass Drum L + Analog Bass Drum H + Analog Side Stick + Analog Snare L + Analog Snare H + Analog Tom 1 + Analog Hi-Hat Closed 1 + Analog Tom 2 + Analog Hi-Hat Closed 2 + Analog Tom 3 + Analog Hi-Hat Open + Analog Tom 4 + Analog Tom 5 + Analog Cymbal + Analog Tom 6 + Analog Cowbell + Analog Conga H + Analog Conga M + Analog Conga L + Analog Maracas + Analog Claves + Scratch Push + Scratch Pull + Shaker + Jingle Bell + Belltree + + + + + + + Mute Surdo + Open Surdo + High Q + Whip Slap + Scratch Push + Scratch Pull + Finger Snap + Click Noise + Metronome Click + Metronome Bell + Seq Click L + Seq Click H + Brush Tap + Brush Swirl L + Brush Slap + Brush Swirl H + Snare Roll + Castanet + Snare L + Sticks + Bass Drum L + Open Rim Shot + Bass Drum M + Jazz Bass Drum + Snare M + Snare H + Jazz Tom 1 + Jazz Tom 2 + Jazz Tom 3 + Jazz Tom 4 + Jazz Tom 5 + Jazz Tom 6 + Shaker + Jingle Bell + Belltree + + + + + + + Mute Surdo + Open Surdo + High Q + Whip Slap + Scratch Push + Scratch Pull + Finger Snap + Click Noise + Metronome Click + Metronome Bell + Seq Click L + Seq Click H + Brush Tap + Brush Swirl L + Brush Slap + Brush Swirl H + Snare Roll + Castanet + Brush Slap L + Sticks + Bass Drum L + Open Rim Shot + Bass Drum M + Soft Bass Drum + Brush Slap + Brush Tap + Brush Tom 1 + Brush Tom 2 + Brush Tom 3 + Brush Tom 4 + Brush Tom 5 + Brush Tom 6 + Shaker + Jingle Bell + Belltree + + + + + + + Mute Surdo + Open Surdo + High Q + Whip Slap + Scratch Push + Scratch Pull + Finger Snap + Click Noise + Metronome Click + Metronome Bell + Seq Click L + Seq Click H + Brush Tap + Brush Swirl L + Brush Slap + Brush Swirl H + Snare Roll + Castanet + Snare L + Sticks + Bass Drum L 2 + Open Rim Shot + Gran Cassa + Gran Cassa Mute + Marching Snare H + Marching Snare M + Jazz Tom 1 + Jazz Tom 2 + Jazz Tom 3 + Jazz Tom 4 + Jazz Tom 5 + Hand Cym. Open L + Jazz Tom 6 + Hand Cym. Closed L + Hand Cym. Open H + Hand Cym. Closed H + Shaker + Jingle Bell + Belltree + + + + + + + + Guitar Cutting Noise + Guitar Cutting Noise 2 + Dist. Cut Noise + String Slap + Bass Slide + Pick Scrape + + + + + + + + + + + FL.Key Click + + + + + + + + + + + + + + + + Rain + Thunder + Wind + Stream + Bubble + Feed + + + + + + + + + + + Dog + Horse Gallop + Bird 2 + Kitty + Growl + Haunted + Ghost + Maou + + + + + + + + Dial Tone + Door Creaking + Door Slam + Scratch + Scratch 2 + Windchime + Telephone Ring 2 + + + + + + + + + + Engine Start + Tire Screech + Car Passing + Crash + Siren + Train + Jetplane + Starship + Burst Noise + Coaster + SbMarine + + + + + + Laughing + Screaming + Punch + Heartbeat + Footsteps + Applaus2 + + + + + + + + + + + Machine Gun + Laser Gun + Explosion + Firework + + + + -- cgit v1.2.3