diff options
-rw-r--r-- | audio/softsynth/mt32/Part.cpp | 144 | ||||
-rw-r--r-- | audio/softsynth/mt32/Part.h | 19 | ||||
-rw-r--r-- | audio/softsynth/mt32/Poly.cpp | 9 | ||||
-rw-r--r-- | audio/softsynth/mt32/Poly.h | 5 |
4 files changed, 143 insertions, 34 deletions
diff --git a/audio/softsynth/mt32/Part.cpp b/audio/softsynth/mt32/Part.cpp index 0c9e576100..cd385898e1 100644 --- a/audio/softsynth/mt32/Part.cpp +++ b/audio/softsynth/mt32/Part.cpp @@ -68,18 +68,16 @@ Part::Part(Synth *useSynth, unsigned int usePartNum) { activePartialCount = 0; memset(patchCache, 0, sizeof(patchCache)); for (int i = 0; i < MT32EMU_MAX_POLY; i++) { - freePolys.push_front(new Poly(this)); + freePolys.prepend(new Poly(this)); } } Part::~Part() { - while (!activePolys.empty()) { - delete activePolys.front(); - activePolys.pop_front(); + while (!activePolys.isEmpty()) { + delete activePolys.takeFirst(); } - while (!freePolys.empty()) { - delete freePolys.front(); - freePolys.pop_front(); + while (!freePolys.isEmpty()) { + delete freePolys.takeFirst(); } } @@ -246,8 +244,8 @@ void Part::backupCacheToPartials(PatchCache cache[4]) { // if so then duplicate the cached data from the part to the partial so that // we can change the part's cache without affecting the partial. // We delay this until now to avoid a copy operation with every note played - for (PolyList::iterator polyIt = activePolys.begin(); polyIt != activePolys.end(); polyIt++) { - (*polyIt)->backupCacheToPartials(cache); + for (Poly *poly = activePolys.getFirst(); poly != NULL; poly = poly->getNext()) { + poly->backupCacheToPartials(cache); } } @@ -446,8 +444,7 @@ void Part::abortPoly(Poly *poly) { } bool Part::abortFirstPoly(unsigned int key) { - for (PolyList::iterator polyIt = activePolys.begin(); polyIt != activePolys.end(); polyIt++) { - Poly *poly = *polyIt; + for (Poly *poly = activePolys.getFirst(); poly != NULL; poly = poly->getNext()) { if (poly->getKey() == key) { abortPoly(poly); return true; @@ -457,8 +454,7 @@ bool Part::abortFirstPoly(unsigned int key) { } bool Part::abortFirstPoly(PolyState polyState) { - for (PolyList::iterator polyIt = activePolys.begin(); polyIt != activePolys.end(); polyIt++) { - Poly *poly = *polyIt; + for (Poly *poly = activePolys.getFirst(); poly != NULL; poly = poly->getNext()) { if (poly->getState() == polyState) { abortPoly(poly); return true; @@ -475,10 +471,10 @@ bool Part::abortFirstPolyPreferHeld() { } bool Part::abortFirstPoly() { - if (activePolys.empty()) { + if (activePolys.isEmpty()) { return false; } - abortPoly(activePolys.front()); + abortPoly(activePolys.getFirst()); return true; } @@ -503,17 +499,16 @@ void Part::playPoly(const PatchCache cache[4], const MemParams::RhythmTemp *rhyt return; } - if (freePolys.empty()) { + if (freePolys.isEmpty()) { synth->printDebug("%s (%s): No free poly to play key %d (velocity %d)", name, currentInstr, midiKey, velocity); return; } - Poly *poly = freePolys.front(); - freePolys.pop_front(); + Poly *poly = freePolys.takeFirst(); if (patchTemp->patch.assignMode & 1) { // Priority to data first received - activePolys.push_front(poly); + activePolys.prepend(poly); } else { - activePolys.push_back(poly); + activePolys.append(poly); } Partial *partials[4]; @@ -545,8 +540,7 @@ void Part::playPoly(const PatchCache cache[4], const MemParams::RhythmTemp *rhyt void Part::allNotesOff() { // The MIDI specification states - and Mok confirms - that all notes off (0x7B) // should treat the hold pedal as usual. - for (PolyList::iterator polyIt = activePolys.begin(); polyIt != activePolys.end(); polyIt++) { - Poly *poly = *polyIt; + for (Poly *poly = activePolys.getFirst(); poly != NULL; poly = poly->getNext()) { // FIXME: This has special handling of key 0 in NoteOff that Mok has not yet confirmed applies to AllNotesOff. // if (poly->canSustain() || poly->getKey() == 0) { // FIXME: The real devices are found to be ignoring non-sustaining polys while processing AllNotesOff. Need to be confirmed. @@ -560,15 +554,13 @@ void Part::allSoundOff() { // MIDI "All sound off" (0x78) should release notes immediately regardless of the hold pedal. // This controller is not actually implemented by the synths, though (according to the docs and Mok) - // we're only using this method internally. - for (PolyList::iterator polyIt = activePolys.begin(); polyIt != activePolys.end(); polyIt++) { - Poly *poly = *polyIt; + for (Poly *poly = activePolys.getFirst(); poly != NULL; poly = poly->getNext()) { poly->startDecay(); } } void Part::stopPedalHold() { - for (PolyList::iterator polyIt = activePolys.begin(); polyIt != activePolys.end(); polyIt++) { - Poly *poly = *polyIt; + for (Poly *poly = activePolys.getFirst(); poly != NULL; poly = poly->getNext()) { poly->stopPedalHold(); } } @@ -586,8 +578,7 @@ void Part::stopNote(unsigned int key) { synth->printDebug("%s (%s): stopping key %d", name, currentInstr, key); #endif - for (PolyList::iterator polyIt = activePolys.begin(); polyIt != activePolys.end(); polyIt++) { - Poly *poly = *polyIt; + for (Poly *poly = activePolys.getFirst(); poly != NULL; poly = poly->getNext()) { // Generally, non-sustaining instruments ignore note off. They die away eventually anyway. // Key 0 (only used by special cases on rhythm part) reacts to note off even if non-sustaining or pedal held. if (poly->getKey() == key && (poly->canSustain() || key == 0)) { @@ -608,8 +599,7 @@ unsigned int Part::getActivePartialCount() const { unsigned int Part::getActiveNonReleasingPartialCount() const { unsigned int activeNonReleasingPartialCount = 0; - for (PolyList::const_iterator polyIt = activePolys.begin(); polyIt != activePolys.end(); polyIt++) { - Poly *poly = *polyIt; + for (Poly *poly = activePolys.getFirst(); poly != NULL; poly = poly->getNext()) { if (poly->getState() != POLY_Releasing) { activeNonReleasingPartialCount += poly->getActivePartialCount(); } @@ -621,7 +611,7 @@ void Part::partialDeactivated(Poly *poly) { activePartialCount--; if (!poly->isActive()) { activePolys.remove(poly); - freePolys.push_front(poly); + freePolys.prepend(poly); synth->polyStateChanged(partNum); } if (activePartialCount == 0) { @@ -629,4 +619,96 @@ void Part::partialDeactivated(Poly *poly) { } } +//#define POLY_LIST_DEBUG + +PolyList::PolyList() : firstPoly(NULL), lastPoly(NULL) {} + +bool PolyList::isEmpty() const { +#ifdef POLY_LIST_DEBUG + if ((firstPoly == NULL || lastPoly == NULL) && firstPoly != lastPoly) { + printf("PolyList: desynchronised firstPoly & lastPoly pointers\n"); + } +#endif + return firstPoly == NULL && lastPoly == NULL; +} + +Poly *PolyList::getFirst() const { + return firstPoly; +} + +Poly *PolyList::getLast() const { + return lastPoly; +} + +void PolyList::prepend(Poly *poly) { +#ifdef POLY_LIST_DEBUG + if (poly->getNext() != NULL) { + printf("PolyList: Non-NULL next field in a Poly being prepended is ignored\n"); + } +#endif + poly->setNext(firstPoly); + firstPoly = poly; + if (lastPoly == NULL) { + lastPoly = poly; + } +} + +void PolyList::append(Poly *poly) { +#ifdef POLY_LIST_DEBUG + if (poly->getNext() != NULL) { + printf("PolyList: Non-NULL next field in a Poly being appended is ignored\n"); + } +#endif + poly->setNext(NULL); + if (lastPoly != NULL) { +#ifdef POLY_LIST_DEBUG + if (lastPoly->getNext() != NULL) { + printf("PolyList: Non-NULL next field in the lastPoly\n"); + } +#endif + lastPoly->setNext(poly); + } + lastPoly = poly; + if (firstPoly == NULL) { + firstPoly = poly; + } +} + +Poly *PolyList::takeFirst() { + Poly *oldFirst = firstPoly; + firstPoly = oldFirst->getNext(); + if (firstPoly == NULL) { +#ifdef POLY_LIST_DEBUG + if (lastPoly != oldFirst) { + printf("PolyList: firstPoly != lastPoly in a list with a single Poly\n"); + } +#endif + lastPoly = NULL; + } + oldFirst->setNext(NULL); + return oldFirst; +} + +void PolyList::remove(Poly * const polyToRemove) { + if (polyToRemove == firstPoly) { + takeFirst(); + return; + } + for (Poly *poly = firstPoly; poly != NULL; poly = poly->getNext()) { + if (poly->getNext() == polyToRemove) { + if (polyToRemove == lastPoly) { +#ifdef POLY_LIST_DEBUG + if (lastPoly->getNext() != NULL) { + printf("PolyList: Non-NULL next field in the lastPoly\n"); + } +#endif + lastPoly = poly; + } + poly->setNext(polyToRemove->getNext()); + polyToRemove->setNext(NULL); + break; + } + } +} + } diff --git a/audio/softsynth/mt32/Part.h b/audio/softsynth/mt32/Part.h index 7ae73a818c..e5be41ff10 100644 --- a/audio/softsynth/mt32/Part.h +++ b/audio/softsynth/mt32/Part.h @@ -18,13 +18,26 @@ #ifndef MT32EMU_PART_H #define MT32EMU_PART_H -#include <common/list.h> - namespace MT32Emu { class PartialManager; class Synth; -typedef Common::List<Poly *> PolyList; + +class PolyList { +private: + Poly *firstPoly; + Poly *lastPoly; + +public: + PolyList(); + bool isEmpty() const; + Poly *getFirst() const; + Poly *getLast() const; + void prepend(Poly *poly); + void append(Poly *poly); + Poly *takeFirst(); + void remove(Poly * const poly); +}; class Part { private: diff --git a/audio/softsynth/mt32/Poly.cpp b/audio/softsynth/mt32/Poly.cpp index c45391f672..46e30c0f02 100644 --- a/audio/softsynth/mt32/Poly.cpp +++ b/audio/softsynth/mt32/Poly.cpp @@ -29,6 +29,7 @@ Poly::Poly(Part *usePart) { partials[i] = NULL; } state = POLY_Inactive; + next = NULL; } void Poly::reset(unsigned int newKey, unsigned int newVelocity, bool newSustain, Partial **newPartials) { @@ -174,4 +175,12 @@ void Poly::partialDeactivated(Partial *partial) { part->partialDeactivated(this); } +Poly *Poly::getNext() { + return next; +} + +void Poly::setNext(Poly *poly) { + next = poly; +} + } diff --git a/audio/softsynth/mt32/Poly.h b/audio/softsynth/mt32/Poly.h index cd15a776f5..e25b6d8993 100644 --- a/audio/softsynth/mt32/Poly.h +++ b/audio/softsynth/mt32/Poly.h @@ -41,6 +41,8 @@ private: Partial *partials[4]; + Poly *next; + public: Poly(Part *part); void reset(unsigned int key, unsigned int velocity, bool sustain, Partial **partials); @@ -60,6 +62,9 @@ public: bool isActive() const; void partialDeactivated(Partial *partial); + + Poly *getNext(); + void setNext(Poly *poly); }; } |