summaryrefslogtreecommitdiff
path: root/muse2/muse/track.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'muse2/muse/track.cpp')
-rw-r--r--muse2/muse/track.cpp272
1 files changed, 267 insertions, 5 deletions
diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp
index e9aa0cf6..07a2dff0 100644
--- a/muse2/muse/track.cpp
+++ b/muse2/muse/track.cpp
@@ -33,6 +33,7 @@
#include "audio.h"
#include "globaldefs.h"
#include "route.h"
+#include "drummap.h"
namespace MusECore {
@@ -45,8 +46,8 @@ bool Track::_tmpSoloChainNoDec = false;
//int Track::_tmpIsAuxProcRefCount = 0;
const char* Track::_cname[] = {
- "Midi", "Drum", "Wave", "AudioOut", "AudioIn", "AudioGroup",
- "AudioAux", "AudioSynth"
+ "Midi", "Drum", "NewStyleDrum", "Wave",
+ "AudioOut", "AudioIn", "AudioGroup", "AudioAux", "AudioSynth"
};
@@ -352,6 +353,7 @@ void Track::setDefaultName()
switch(_type) {
case MIDI:
case DRUM:
+ case NEW_DRUM:
case WAVE:
base = QString("Track");
break;
@@ -536,6 +538,11 @@ MidiTrack::MidiTrack()
_events = new EventList;
_mpevents = new MPEventList;
clefType=trebleClef;
+
+ _drummap=new DrumMap[128];
+ _drummap_hidden=new bool[128];
+
+ init_drummap(true /* write drummap ordering information as well */);
}
//MidiTrack::MidiTrack(const MidiTrack& mt)
@@ -556,14 +563,41 @@ MidiTrack::MidiTrack(const MidiTrack& mt, bool cloneParts)
compression = mt.compression;
_recEcho = mt.recEcho();
clefType=trebleClef;
+
+ _drummap=new DrumMap[128];
+ _drummap_hidden=new bool[128];
+ memcpy(_drummap, mt._drummap, 128*sizeof(*_drummap));
+ memcpy(_drummap_hidden, mt._drummap_hidden, 128*sizeof(*_drummap_hidden));
+ update_drum_in_map();
+
+ for (MusEGlobal::global_drum_ordering_t::iterator it=MusEGlobal::global_drum_ordering.begin(); it!=MusEGlobal::global_drum_ordering.end(); it++)
+ if (it->first == &mt)
+ {
+ it=MusEGlobal::global_drum_ordering.insert(it, *it); // duplicates the entry at it, set it to the first entry of both
+ it++; // make it point to the second entry
+ it->first=this;
+ }
}
MidiTrack::~MidiTrack()
{
delete _events;
delete _mpevents;
+ delete [] _drummap;
+ delete [] _drummap_hidden;
+
+ remove_ourselves_from_drum_ordering();
}
+void MidiTrack::remove_ourselves_from_drum_ordering()
+{
+ for (MusEGlobal::global_drum_ordering_t::iterator it=MusEGlobal::global_drum_ordering.begin(); it!=MusEGlobal::global_drum_ordering.end();)
+ if (it->first == this)
+ it=MusEGlobal::global_drum_ordering.erase(it);
+ else
+ it++;
+}
+
//---------------------------------------------------------
// init
//---------------------------------------------------------
@@ -571,7 +605,7 @@ MidiTrack::~MidiTrack()
void MidiTrack::init()
{
_outPort = 0;
- _outChannel = 0;
+ _outChannel = (type()==NEW_DRUM) ? 9 : 0;
//_inPortMask = 0xffff;
///_inPortMask = 0xffffffff;
@@ -584,6 +618,32 @@ void MidiTrack::init()
_recEcho = true;
}
+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<MidiTrack*,int>(this,idx));
+ }
+
+ update_drum_in_map();
+
+ for (int i=0;i<128;i++)
+ _drummap_hidden[i]=false;
+}
+
+void MidiTrack::update_drum_in_map()
+{
+ for (int i=0;i<127;i++)
+ drum_in_map[(int)_drummap[i].enote]=i;
+}
+
//---------------------------------------------------------
// height
//---------------------------------------------------------
@@ -841,8 +901,13 @@ void MidiTrack::write(int level, Xml& xml) const
if (type() == DRUM)
tag = "drumtrack";
- else
+ else if (type() == MIDI)
tag = "miditrack";
+ else if (type() == NEW_DRUM)
+ tag = "newdrumtrack";
+ else
+ printf("THIS SHOULD NEVER HAPPEN: non-midi-type in MidiTrack::write()\n");
+
xml.tag(level++, tag);
Track::writeProperties(level, xml);
@@ -865,9 +930,77 @@ void MidiTrack::write(int level, Xml& xml) const
const PartList* pl = cparts();
for (ciPart p = pl->begin(); p != pl->end(); ++p)
p->second->write(level, xml);
+
+ writeOurDrumSettings(level, xml);
+
xml.etag(level, tag);
}
+void MidiTrack::writeOurDrumSettings(int level, Xml& xml) const
+{
+ xml.tag(level++, "our_drum_settings");
+
+ writeOurDrumMap(level, xml, false);
+
+ xml.intTag(level, "tied", _drummap_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");
+}
+
//---------------------------------------------------------
// MidiTrack::read
//---------------------------------------------------------
@@ -924,6 +1057,8 @@ void MidiTrack::read(Xml& xml)
setAutomationType(AutomationType(xml.parseInt()));
else if (tag == "clef")
clefType = (clefTypes)xml.parseInt();
+ else if (tag == "our_drum_settings")
+ readOurDrumSettings(xml);
else if (Track::readProperties(xml, tag)) {
// version 1.0 compatibility:
if (tag == "track" && xml.majorVersion() == 1 && xml.minorVersion() == 0)
@@ -934,7 +1069,7 @@ void MidiTrack::read(Xml& xml)
case Xml::Attribut:
break;
case Xml::TagEnd:
- if (tag == "miditrack" || tag == "drumtrack")
+ if (tag == "miditrack" || tag == "drumtrack" || tag == "newdrumtrack")
{
setInPortAndChannelMask(portmask, chanmask); // Support old files.
return;
@@ -945,6 +1080,133 @@ void MidiTrack::read(Xml& xml)
}
}
+void MidiTrack::readOurDrumSettings(Xml& xml)
+{
+ 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 == "tied")
+ _drummap_tied_to_patch = xml.parseInt();
+ else if (tag == "our_drummap")
+ readOurDrumMap(xml);
+ else
+ xml.unknown("MidiTrack::readOurDrumSettings");
+ break;
+
+ case Xml::TagEnd:
+ if (tag == "our_drum_settings")
+ return;
+
+ default:
+ break;
+ }
+ }
+}
+
+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 <entry> 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;
+ }
+ }
+}
+
//---------------------------------------------------------
// addPart