DOSBox-X
|
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 // FIXME: Throw out lots of debug output - this should never happen 00120 // (Deactivating the partials above should've made them each call partialDeactivated(), ultimately changing the state to POLY_Inactive) 00121 state = POLY_Inactive; 00122 } 00123 00124 void Poly::backupCacheToPartials(PatchCache cache[4]) { 00125 for (int partialNum = 0; partialNum < 4; partialNum++) { 00126 Partial *partial = partials[partialNum]; 00127 if (partial != NULL && partial->patchCache == &cache[partialNum]) { 00128 partial->cachebackup = cache[partialNum]; 00129 partial->patchCache = &partial->cachebackup; 00130 } 00131 } 00132 } 00133 00140 unsigned int Poly::getKey() const { 00141 return key; 00142 } 00143 00144 unsigned int Poly::getVelocity() const { 00145 return velocity; 00146 } 00147 00148 bool Poly::canSustain() const { 00149 return sustain; 00150 } 00151 00152 PolyState Poly::getState() const { 00153 return state; 00154 } 00155 00156 unsigned int Poly::getActivePartialCount() const { 00157 return activePartialCount; 00158 } 00159 00160 bool Poly::isActive() const { 00161 return state != POLY_Inactive; 00162 } 00163 00164 // This is called by Partial to inform the poly that the Partial has deactivated 00165 void Poly::partialDeactivated(Partial *partial) { 00166 for (int i = 0; i < 4; i++) { 00167 if (partials[i] == partial) { 00168 partials[i] = NULL; 00169 activePartialCount--; 00170 } 00171 } 00172 if (activePartialCount == 0) { 00173 state = POLY_Inactive; 00174 } 00175 part->partialDeactivated(this); 00176 } 00177 00178 Poly *Poly::getNext() { 00179 return next; 00180 } 00181 00182 void Poly::setNext(Poly *poly) { 00183 next = poly; 00184 } 00185 00186 00187 #ifdef WIN32_DEBUG 00188 void Poly::rawVerifyState( char *name, Synth *useSynth ) 00189 { 00190 Poly *ptr1, *ptr2; 00191 Poly poly_temp(synth, part); 00192 00193 00194 #ifndef WIN32_DUMP 00195 return; 00196 #endif 00197 00198 ptr1 = this; 00199 ptr2 = &poly_temp; 00200 useSynth->rawLoadState( name, ptr2, sizeof(*this) ); 00201 00202 00203 if( ptr1->synth != ptr2->synth ) __asm int 3 00204 if( ptr1->part != ptr2->part ) __asm int 3 00205 if( ptr1->key != ptr2->key ) __asm int 3 00206 if( ptr1->velocity != ptr2->velocity ) __asm int 3 00207 if( ptr1->activePartialCount != ptr2->activePartialCount ) __asm int 3 00208 if( ptr1->sustain != ptr2->sustain ) __asm int 3 00209 if( ptr1->state != ptr2->state ) __asm int 3 00210 00211 for( int lcv=0; lcv<4; lcv++ ) { 00212 if( ptr1->partials[lcv] != ptr2->partials[lcv] ) __asm int 3 00213 } 00214 00215 00216 00217 // avoid destructor problems 00218 memset( ptr2, 0, sizeof(*ptr2) ); 00219 } 00220 #endif 00221 00222 00223 void Poly::saveState( std::ostream &stream ) 00224 { 00225 // - static fastptr 00226 //Synth *synth; 00227 //Part *part; 00228 00229 stream.write(reinterpret_cast<const char*>(&key), sizeof(key) ); 00230 stream.write(reinterpret_cast<const char*>(&velocity), sizeof(velocity) ); 00231 stream.write(reinterpret_cast<const char*>(&activePartialCount), sizeof(activePartialCount) ); 00232 stream.write(reinterpret_cast<const char*>(&sustain), sizeof(sustain) ); 00233 stream.write(reinterpret_cast<const char*>(&state), sizeof(state) ); 00234 00235 00236 // - reloc ptr (!!!) 00237 //Partial *partials[4]; 00238 for( int lcv=0; lcv<4; lcv++ ) { 00239 Bit8u partials_idx; 00240 00241 synth->findPartial( partials[lcv], &partials_idx ); 00242 00243 stream.write(reinterpret_cast<const char*>(&partials_idx), sizeof(partials_idx) ); 00244 } 00245 00246 00247 #ifdef WIN32_DEBUG 00248 // DEBUG 00249 synth->rawDumpState( "temp-save", this, sizeof(*this) ); 00250 synth->rawDumpNo++; 00251 #endif 00252 } 00253 00254 00255 void Poly::loadState( std::istream &stream ) 00256 { 00257 // - static fastptr 00258 //Synth *synth; 00259 //Part *part; 00260 00261 stream.read(reinterpret_cast<char*>(&key), sizeof(key) ); 00262 stream.read(reinterpret_cast<char*>(&velocity), sizeof(velocity) ); 00263 stream.read(reinterpret_cast<char*>(&activePartialCount), sizeof(activePartialCount) ); 00264 stream.read(reinterpret_cast<char*>(&sustain), sizeof(sustain) ); 00265 stream.read(reinterpret_cast<char*>(&state), sizeof(state) ); 00266 00267 00268 // - reloc ptr (!!!) 00269 //Partial *partials[4]; 00270 for( int lcv=0; lcv<4; lcv++ ) { 00271 Bit8u partials_idx; 00272 00273 stream.read(reinterpret_cast<char*>(&partials_idx), sizeof(partials_idx) ); 00274 partials[lcv] = (Partial *) synth->indexPartial(partials_idx); 00275 } 00276 00277 00278 #ifdef WIN32_DEBUG 00279 // DEBUG 00280 synth->rawDumpState( "temp-load", this, sizeof(*this) ); 00281 this->rawVerifyState( "temp-save", synth ); 00282 synth->rawDumpNo++; 00283 #endif 00284 } 00285 00286 }