aboutsummaryrefslogtreecommitdiff
path: root/audio/softsynth
diff options
context:
space:
mode:
Diffstat (limited to 'audio/softsynth')
-rw-r--r--audio/softsynth/mt32/Part.cpp144
-rw-r--r--audio/softsynth/mt32/Part.h19
-rw-r--r--audio/softsynth/mt32/Poly.cpp9
-rw-r--r--audio/softsynth/mt32/Poly.h5
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);
};
}