DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/mt32/Poly.cpp
00001 /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
00002  * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
00003  *
00004  *  This program is free software: you can redistribute it and/or modify
00005  *  it under the terms of the GNU Lesser General Public License as published by
00006  *  the Free Software Foundation, either version 2.1 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU Lesser General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Lesser General Public License
00015  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 #include "mt32emu.h"
00019 #include "PartialManager.h"
00020 
00021 namespace MT32Emu {
00022 
00023 Poly::Poly(Synth *useSynth, Part *usePart) {
00024         synth = useSynth;
00025         part = usePart;
00026         key = 255;
00027         velocity = 255;
00028         sustain = false;
00029         activePartialCount = 0;
00030         for (int i = 0; i < 4; i++) {
00031                 partials[i] = NULL;
00032         }
00033         state = POLY_Inactive;
00034         next = NULL;
00035 }
00036 
00037 void Poly::reset(unsigned int newKey, unsigned int newVelocity, bool newSustain, Partial **newPartials) {
00038         if (isActive()) {
00039                 // FIXME: Throw out some big ugly debug output with a lot of exclamation marks - we should never get here
00040                 terminate();
00041         }
00042 
00043         key = newKey;
00044         velocity = newVelocity;
00045         sustain = newSustain;
00046 
00047         activePartialCount = 0;
00048         for (int i = 0; i < 4; i++) {
00049                 partials[i] = newPartials[i];
00050                 if (newPartials[i] != NULL) {
00051                         activePartialCount++;
00052                         state = POLY_Playing;
00053                 }
00054         }
00055 }
00056 
00057 bool Poly::noteOff(bool pedalHeld) {
00058         // Generally, non-sustaining instruments ignore note off. They die away eventually anyway.
00059         // Key 0 (only used by special cases on rhythm part) reacts to note off even if non-sustaining or pedal held.
00060         if (state == POLY_Inactive || state == POLY_Releasing) {
00061                 return false;
00062         }
00063         if (pedalHeld) {
00064                 if (state == POLY_Held) {
00065                         return false;
00066                 }
00067                 state = POLY_Held;
00068         } else {
00069                 startDecay();
00070         }
00071         return true;
00072 }
00073 
00074 bool Poly::stopPedalHold() {
00075         if (state != POLY_Held) {
00076                 return false;
00077         }
00078         return startDecay();
00079 }
00080 
00081 bool Poly::startDecay() {
00082         if (state == POLY_Inactive || state == POLY_Releasing) {
00083                 return false;
00084         }
00085         state = POLY_Releasing;
00086 
00087         for (int t = 0; t < 4; t++) {
00088                 Partial *partial = partials[t];
00089                 if (partial != NULL) {
00090                         partial->startDecayAll();
00091                 }
00092         }
00093         return true;
00094 }
00095 
00096 bool Poly::startAbort() {
00097         if (state == POLY_Inactive) {
00098                 return false;
00099         }
00100         for (int t = 0; t < 4; t++) {
00101                 Partial *partial = partials[t];
00102                 if (partial != NULL) {
00103                         partial->startAbort();
00104                 }
00105         }
00106         return true;
00107 }
00108 
00109 void Poly::terminate() {
00110         if (state == POLY_Inactive) {
00111                 return;
00112         }
00113         for (int t = 0; t < 4; t++) {
00114                 Partial *partial = partials[t];
00115                 if (partial != NULL) {
00116                         partial->deactivate();
00117                 }
00118         }
00119         if (state != POLY_Inactive) {
00120                 // FIXME: Throw out lots of debug output - this should never happen
00121                 // (Deactivating the partials above should've made them each call partialDeactivated(), ultimately changing the state to POLY_Inactive)
00122                 state = POLY_Inactive;
00123         }
00124 }
00125 
00126 void Poly::backupCacheToPartials(PatchCache cache[4]) {
00127         for (int partialNum = 0; partialNum < 4; partialNum++) {
00128                 Partial *partial = partials[partialNum];
00129                 if (partial != NULL && partial->patchCache == &cache[partialNum]) {
00130                         partial->cachebackup = cache[partialNum];
00131                         partial->patchCache = &partial->cachebackup;
00132                 }
00133         }
00134 }
00135 
00142 unsigned int Poly::getKey() const {
00143         return key;
00144 }
00145 
00146 unsigned int Poly::getVelocity() const {
00147         return velocity;
00148 }
00149 
00150 bool Poly::canSustain() const {
00151         return sustain;
00152 }
00153 
00154 PolyState Poly::getState() const {
00155         return state;
00156 }
00157 
00158 unsigned int Poly::getActivePartialCount() const {
00159         return activePartialCount;
00160 }
00161 
00162 bool Poly::isActive() const {
00163         return state != POLY_Inactive;
00164 }
00165 
00166 // This is called by Partial to inform the poly that the Partial has deactivated
00167 void Poly::partialDeactivated(Partial *partial) {
00168         for (int i = 0; i < 4; i++) {
00169                 if (partials[i] == partial) {
00170                         partials[i] = NULL;
00171                         activePartialCount--;
00172                 }
00173         }
00174         if (activePartialCount == 0) {
00175                 state = POLY_Inactive;
00176         }
00177         part->partialDeactivated(this);
00178 }
00179 
00180 Poly *Poly::getNext() {
00181         return next;
00182 }
00183 
00184 void Poly::setNext(Poly *poly) {
00185         next = poly;
00186 }
00187 
00188 
00189 #ifdef WIN32_DEBUG
00190 void Poly::rawVerifyState( char *name, Synth *useSynth )
00191 {
00192         Poly *ptr1, *ptr2;
00193         Poly poly_temp(synth, part);
00194 
00195 
00196 #ifndef WIN32_DUMP
00197         return;
00198 #endif
00199 
00200         ptr1 = this;
00201         ptr2 = &poly_temp;
00202         useSynth->rawLoadState( name, ptr2, sizeof(*this) );
00203 
00204 
00205         if( ptr1->synth != ptr2->synth ) __asm int 3
00206         if( ptr1->part != ptr2->part ) __asm int 3
00207         if( ptr1->key != ptr2->key ) __asm int 3
00208         if( ptr1->velocity != ptr2->velocity ) __asm int 3
00209         if( ptr1->activePartialCount != ptr2->activePartialCount ) __asm int 3
00210         if( ptr1->sustain != ptr2->sustain ) __asm int 3
00211         if( ptr1->state != ptr2->state ) __asm int 3
00212 
00213         for( int lcv=0; lcv<4; lcv++ ) {
00214                 if( ptr1->partials[lcv] != ptr2->partials[lcv] ) __asm int 3
00215         }
00216 
00217 
00218 
00219         // avoid destructor problems
00220         memset( ptr2, 0, sizeof(*ptr2) );
00221 }
00222 #endif
00223 
00224 
00225 void Poly::saveState( std::ostream &stream )
00226 {
00227         // - static fastptr
00228         //Synth *synth;
00229         //Part *part;
00230 
00231         stream.write(reinterpret_cast<const char*>(&key), sizeof(key) );
00232         stream.write(reinterpret_cast<const char*>(&velocity), sizeof(velocity) );
00233         stream.write(reinterpret_cast<const char*>(&activePartialCount), sizeof(activePartialCount) );
00234         stream.write(reinterpret_cast<const char*>(&sustain), sizeof(sustain) );
00235         stream.write(reinterpret_cast<const char*>(&state), sizeof(state) );
00236 
00237 
00238         // - reloc ptr (!!!)
00239         //Partial *partials[4];
00240         for( int lcv=0; lcv<4; lcv++ ) {
00241                 Bit8u partials_idx;
00242 
00243                 synth->findPartial( partials[lcv], &partials_idx );
00244                 
00245                 stream.write(reinterpret_cast<const char*>(&partials_idx), sizeof(partials_idx) );
00246         }
00247 
00248 
00249 #ifdef WIN32_DEBUG
00250         // DEBUG
00251         synth->rawDumpState( "temp-save", this, sizeof(*this) );
00252         synth->rawDumpNo++;
00253 #endif
00254 }
00255 
00256 
00257 void Poly::loadState( std::istream &stream )
00258 {
00259         // - static fastptr
00260         //Synth *synth;
00261         //Part *part;
00262 
00263         stream.read(reinterpret_cast<char*>(&key), sizeof(key) );
00264         stream.read(reinterpret_cast<char*>(&velocity), sizeof(velocity) );
00265         stream.read(reinterpret_cast<char*>(&activePartialCount), sizeof(activePartialCount) );
00266         stream.read(reinterpret_cast<char*>(&sustain), sizeof(sustain) );
00267         stream.read(reinterpret_cast<char*>(&state), sizeof(state) );
00268 
00269         
00270         // - reloc ptr (!!!)
00271         //Partial *partials[4];
00272         for( int lcv=0; lcv<4; lcv++ ) {
00273                 Bit8u partials_idx;
00274 
00275                 stream.read(reinterpret_cast<char*>(&partials_idx), sizeof(partials_idx) );
00276                 partials[lcv] = (Partial *) synth->indexPartial(partials_idx);
00277         }
00278 
00279 
00280 #ifdef WIN32_DEBUG
00281         // DEBUG
00282         synth->rawDumpState( "temp-load", this, sizeof(*this) );
00283         this->rawVerifyState( "temp-save", synth );
00284         synth->rawDumpNo++;
00285 #endif
00286 }
00287 
00288 }