ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

dbopl.cpp

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2002-2011  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 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 General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 /*
00020     DOSBox implementation of a combined Yamaha YMF262 and Yamaha YM3812 emulator.
00021     Enabling the opl3 bit will switch the emulator to stereo opl3 output instead of regular mono opl2
00022     Except for the table generation it's all integer math
00023     Can choose different types of generators, using muls and bigger tables, try different ones for slower platforms
00024     The generation was based on the MAME implementation but tried to have it use less memory and be faster in general
00025     MAME uses much bigger envelope tables and this will be the biggest cause of it sounding different at times
00026 
00027     //TODO Don't delay first operator 1 sample in opl3 mode
00028     //TODO Maybe not use class method pointers but a regular function pointers with operator as first parameter
00029     //TODO Fix panning for the Percussion channels, would any opl3 player use it and actually really change it though?
00030     //TODO Check if having the same accuracy in all frequency multipliers sounds better or not
00031 
00032     //DUNNO Keyon in 4op, switch to 2op without keyoff.
00033 */
00034 
00035 // Last synch with DOSBox SVN trunk r3752
00036 
00037 #include "dbopl.h"
00038 
00039 #ifndef DISABLE_DOSBOX_OPL
00040 
00041 namespace OPL {
00042 namespace DOSBox {
00043 
00044 namespace DBOPL {
00045 
00046 #define OPLRATE     ((double)(14318180.0 / 288.0))
00047 #define TREMOLO_TABLE 52
00048 
00049 //Try to use most precision for frequencies
00050 //Else try to keep different waves in synch
00051 //#define WAVE_PRECISION    1
00052 #ifndef WAVE_PRECISION
00053 //Wave bits available in the top of the 32bit range
00054 //Original adlib uses 10.10, we use 10.22
00055 #define WAVE_BITS   10
00056 #else
00057 //Need some extra bits at the top to have room for octaves and frequency multiplier
00058 //We support to 8 times lower rate
00059 //128 * 15 * 8 = 15350, 2^13.9, so need 14 bits
00060 #define WAVE_BITS   14
00061 #endif
00062 #define WAVE_SH     ( 32 - WAVE_BITS )
00063 #define WAVE_MASK   ( ( 1 << WAVE_SH ) - 1 )
00064 
00065 //Use the same accuracy as the waves
00066 #define LFO_SH ( WAVE_SH - 10 )
00067 //LFO is controlled by our tremolo 256 sample limit
00068 #define LFO_MAX ( 256 << ( LFO_SH ) )
00069 
00070 
00071 //Maximum amount of attenuation bits
00072 //Envelope goes to 511, 9 bits
00073 #if (DBOPL_WAVE == WAVE_TABLEMUL )
00074 //Uses the value directly
00075 #define ENV_BITS    ( 9 )
00076 #else
00077 //Add 3 bits here for more accuracy and would have to be shifted up either way
00078 #define ENV_BITS    ( 9 )
00079 #endif
00080 //Limits of the envelope with those bits and when the envelope goes silent
00081 #define ENV_MIN     0
00082 #define ENV_EXTRA   ( ENV_BITS - 9 )
00083 #define ENV_MAX     ( 511 << ENV_EXTRA )
00084 #define ENV_LIMIT   ( ( 12 * 256) >> ( 3 - ENV_EXTRA ) )
00085 #define ENV_SILENT( _X_ ) ( (_X_) >= ENV_LIMIT )
00086 
00087 //Attack/decay/release rate counter shift
00088 #define RATE_SH     24
00089 #define RATE_MASK   ( ( 1 << RATE_SH ) - 1 )
00090 //Has to fit within 16bit lookuptable
00091 #define MUL_SH      16
00092 
00093 //Check some ranges
00094 #if ENV_EXTRA > 3
00095 #error Too many envelope bits
00096 #endif
00097 
00098 
00099 //How much to substract from the base value for the final attenuation
00100 static const Bit8u KslCreateTable[16] = {
00101     //0 will always be be lower than 7 * 8
00102     64, 32, 24, 19,
00103     16, 12, 11, 10,
00104      8,  6,  5,  4,
00105      3,  2,  1,  0,
00106 };
00107 
00108 #define M(_X_) ((Bit8u)( (_X_) * 2))
00109 static const Bit8u FreqCreateTable[16] = {
00110     M(0.5), M(1 ), M(2 ), M(3 ), M(4 ), M(5 ), M(6 ), M(7 ),
00111     M(8  ), M(9 ), M(10), M(10), M(12), M(12), M(15), M(15)
00112 };
00113 #undef M
00114 
00115 //We're not including the highest attack rate, that gets a special value
00116 static const Bit8u AttackSamplesTable[13] = {
00117     69, 55, 46, 40,
00118     35, 29, 23, 20,
00119     19, 15, 11, 10,
00120     9
00121 };
00122 //On a real opl these values take 8 samples to reach and are based upon larger tables
00123 static const Bit8u EnvelopeIncreaseTable[13] = {
00124     4,  5,  6,  7,
00125     8, 10, 12, 14,
00126     16, 20, 24, 28,
00127     32,
00128 };
00129 
00130 #if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
00131 static Bit16u ExpTable[ 256 ];
00132 #endif
00133 
00134 #if ( DBOPL_WAVE == WAVE_HANDLER )
00135 //PI table used by WAVEHANDLER
00136 static Bit16u SinTable[ 512 ];
00137 #endif
00138 
00139 #if ( DBOPL_WAVE > WAVE_HANDLER )
00140 //Layout of the waveform table in 512 entry intervals
00141 //With overlapping waves we reduce the table to half it's size
00142 
00143 //  |    |//\\|____|WAV7|//__|/\  |____|/\/\|
00144 //  |\\//|    |    |WAV7|    |  \/|    |    |
00145 //  |06  |0126|17  |7   |3   |4   |4 5 |5   |
00146 
00147 //6 is just 0 shifted and masked
00148 
00149 static Bit16s WaveTable[ 8 * 512 ];
00150 //Distance into WaveTable the wave starts
00151 static const Bit16u WaveBaseTable[8] = {
00152     0x000, 0x200, 0x200, 0x800,
00153     0xa00, 0xc00, 0x100, 0x400,
00154 
00155 };
00156 //Mask the counter with this
00157 static const Bit16u WaveMaskTable[8] = {
00158     1023, 1023, 511, 511,
00159     1023, 1023, 512, 1023,
00160 };
00161 
00162 //Where to start the counter on at keyon
00163 static const Bit16u WaveStartTable[8] = {
00164     512, 0, 0, 0,
00165     0, 512, 512, 256,
00166 };
00167 #endif
00168 
00169 #if ( DBOPL_WAVE == WAVE_TABLEMUL )
00170 static Bit16u MulTable[ 384 ];
00171 #endif
00172 
00173 static Bit8u KslTable[ 8 * 16 ];
00174 static Bit8u TremoloTable[ TREMOLO_TABLE ];
00175 //Start of a channel behind the chip struct start
00176 static Bit16u ChanOffsetTable[32];
00177 //Start of an operator behind the chip struct start
00178 static Bit16u OpOffsetTable[64];
00179 
00180 //The lower bits are the shift of the operator vibrato value
00181 //The highest bit is right shifted to generate -1 or 0 for negation
00182 //So taking the highest input value of 7 this gives 3, 7, 3, 0, -3, -7, -3, 0
00183 static const Bit8s VibratoTable[ 8 ] = {
00184     1 - 0x00, 0 - 0x00, 1 - 0x00, 30 - 0x00,
00185     1 - 0x80, 0 - 0x80, 1 - 0x80, 30 - 0x80
00186 };
00187 
00188 //Shift strength for the ksl value determined by ksl strength
00189 static const Bit8u KslShiftTable[4] = {
00190     31,1,2,0
00191 };
00192 
00193 //Generate a table index and table shift value using input value from a selected rate
00194 static void EnvelopeSelect( Bit8u val, Bit8u& index, Bit8u& shift ) {
00195     if ( val < 13 * 4 ) {               //Rate 0 - 12
00196         shift = 12 - ( val >> 2 );
00197         index = val & 3;
00198     } else if ( val < 15 * 4 ) {        //rate 13 - 14
00199         shift = 0;
00200         index = val - 12 * 4;
00201     } else {                            //rate 15 and up
00202         shift = 0;
00203         index = 12;
00204     }
00205 }
00206 
00207 #if ( DBOPL_WAVE == WAVE_HANDLER )
00208 /*
00209     Generate the different waveforms out of the sine/exponetial table using handlers
00210 */
00211 static inline Bits MakeVolume( Bitu wave, Bitu volume ) {
00212     Bitu total = wave + volume;
00213     Bitu index = total & 0xff;
00214     Bitu sig = ExpTable[ index ];
00215     Bitu exp = total >> 8;
00216 #if 0
00217     //Check if we overflow the 31 shift limit
00218     if ( exp >= 32 ) {
00219         LOG_MSG( "WTF %d %d", total, exp );
00220     }
00221 #endif
00222     return (sig >> exp);
00223 }
00224 
00225 static Bits DB_FASTCALL WaveForm0( Bitu i, Bitu volume ) {
00226     Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
00227     Bitu wave = SinTable[i & 511];
00228     return (MakeVolume( wave, volume ) ^ neg) - neg;
00229 }
00230 static Bits DB_FASTCALL WaveForm1( Bitu i, Bitu volume ) {
00231     Bit32u wave = SinTable[i & 511];
00232     wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
00233     return MakeVolume( wave, volume );
00234 }
00235 static Bits DB_FASTCALL WaveForm2( Bitu i, Bitu volume ) {
00236     Bitu wave = SinTable[i & 511];
00237     return MakeVolume( wave, volume );
00238 }
00239 static Bits DB_FASTCALL WaveForm3( Bitu i, Bitu volume ) {
00240     Bitu wave = SinTable[i & 255];
00241     wave |= ( ( (i ^ 256 ) & 256) - 1) >> ( 32 - 12 );
00242     return MakeVolume( wave, volume );
00243 }
00244 static Bits DB_FASTCALL WaveForm4( Bitu i, Bitu volume ) {
00245     //Twice as fast
00246     i <<= 1;
00247     Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
00248     Bitu wave = SinTable[i & 511];
00249     wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
00250     return (MakeVolume( wave, volume ) ^ neg) - neg;
00251 }
00252 static Bits DB_FASTCALL WaveForm5( Bitu i, Bitu volume ) {
00253     //Twice as fast
00254     i <<= 1;
00255     Bitu wave = SinTable[i & 511];
00256     wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
00257     return MakeVolume( wave, volume );
00258 }
00259 static Bits DB_FASTCALL WaveForm6( Bitu i, Bitu volume ) {
00260     Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
00261     return (MakeVolume( 0, volume ) ^ neg) - neg;
00262 }
00263 static Bits DB_FASTCALL WaveForm7( Bitu i, Bitu volume ) {
00264     //Negative is reversed here
00265     Bits neg = (( i >> 9) & 1) - 1;
00266     Bitu wave = (i << 3);
00267     //When negative the volume also runs backwards
00268     wave = ((wave ^ neg) - neg) & 4095;
00269     return (MakeVolume( wave, volume ) ^ neg) - neg;
00270 }
00271 
00272 static const WaveHandler WaveHandlerTable[8] = {
00273     WaveForm0, WaveForm1, WaveForm2, WaveForm3,
00274     WaveForm4, WaveForm5, WaveForm6, WaveForm7
00275 };
00276 
00277 #endif
00278 
00279 /*
00280     Operator
00281 */
00282 
00283 //We zero out when rate == 0
00284 inline void Operator::UpdateAttack( const Chip* chip ) {
00285     Bit8u rate = reg60 >> 4;
00286     if ( rate ) {
00287         Bit8u val = (rate << 2) + ksr;
00288         attackAdd = chip->attackRates[ val ];
00289         rateZero &= ~(1 << ATTACK);
00290     } else {
00291         attackAdd = 0;
00292         rateZero |= (1 << ATTACK);
00293     }
00294 }
00295 inline void Operator::UpdateDecay( const Chip* chip ) {
00296     Bit8u rate = reg60 & 0xf;
00297     if ( rate ) {
00298         Bit8u val = (rate << 2) + ksr;
00299         decayAdd = chip->linearRates[ val ];
00300         rateZero &= ~(1 << DECAY);
00301     } else {
00302         decayAdd = 0;
00303         rateZero |= (1 << DECAY);
00304     }
00305 }
00306 inline void Operator::UpdateRelease( const Chip* chip ) {
00307     Bit8u rate = reg80 & 0xf;
00308     if ( rate ) {
00309         Bit8u val = (rate << 2) + ksr;
00310         releaseAdd = chip->linearRates[ val ];
00311         rateZero &= ~(1 << RELEASE);
00312         if ( !(reg20 & MASK_SUSTAIN ) ) {
00313             rateZero &= ~( 1 << SUSTAIN );
00314         }
00315     } else {
00316         rateZero |= (1 << RELEASE);
00317         releaseAdd = 0;
00318         if ( !(reg20 & MASK_SUSTAIN ) ) {
00319             rateZero |= ( 1 << SUSTAIN );
00320         }
00321     }
00322 }
00323 
00324 inline void Operator::UpdateAttenuation( ) {
00325     Bit8u kslBase = (Bit8u)((chanData >> SHIFT_KSLBASE) & 0xff);
00326     Bit32u tl = reg40 & 0x3f;
00327     Bit8u kslShift = KslShiftTable[ reg40 >> 6 ];
00328     //Make sure the attenuation goes to the right bits
00329     totalLevel = tl << ( ENV_BITS - 7 );    //Total level goes 2 bits below max
00330     totalLevel += ( kslBase << ENV_EXTRA ) >> kslShift;
00331 }
00332 
00333 void Operator::UpdateFrequency(  ) {
00334     Bit32u freq = chanData & (( 1 << 10 ) - 1);
00335     Bit32u block = (chanData >> 10) & 0xff;
00336 #ifdef WAVE_PRECISION
00337     block = 7 - block;
00338     waveAdd = ( freq * freqMul ) >> block;
00339 #else
00340     waveAdd = ( freq << block ) * freqMul;
00341 #endif
00342     if ( reg20 & MASK_VIBRATO ) {
00343         vibStrength = (Bit8u)(freq >> 7);
00344 
00345 #ifdef WAVE_PRECISION
00346         vibrato = ( vibStrength * freqMul ) >> block;
00347 #else
00348         vibrato = ( vibStrength << block ) * freqMul;
00349 #endif
00350     } else {
00351         vibStrength = 0;
00352         vibrato = 0;
00353     }
00354 }
00355 
00356 void Operator::UpdateRates( const Chip* chip ) {
00357     //Mame seems to reverse this where enabling ksr actually lowers
00358     //the rate, but pdf manuals says otherwise?
00359     Bit8u newKsr = (Bit8u)((chanData >> SHIFT_KEYCODE) & 0xff);
00360     if ( !( reg20 & MASK_KSR ) ) {
00361         newKsr >>= 2;
00362     }
00363     if ( ksr == newKsr )
00364         return;
00365     ksr = newKsr;
00366     UpdateAttack( chip );
00367     UpdateDecay( chip );
00368     UpdateRelease( chip );
00369 }
00370 
00371 INLINE Bit32s Operator::RateForward( Bit32u add ) {
00372     rateIndex += add;
00373     Bit32s ret = rateIndex >> RATE_SH;
00374     rateIndex = rateIndex & RATE_MASK;
00375     return ret;
00376 }
00377 
00378 template< Operator::State yes>
00379 Bits Operator::TemplateVolume(  ) {
00380     Bit32s vol = volume;
00381     Bit32s change;
00382     switch ( yes ) {
00383     case OFF:
00384         return ENV_MAX;
00385     case ATTACK:
00386         change = RateForward( attackAdd );
00387         if ( !change )
00388             return vol;
00389         vol += ( (~vol) * change ) >> 3;
00390         if ( vol < ENV_MIN ) {
00391             volume = ENV_MIN;
00392             rateIndex = 0;
00393             SetState( DECAY );
00394             return ENV_MIN;
00395         }
00396         break;
00397     case DECAY:
00398         vol += RateForward( decayAdd );
00399         if ( GCC_UNLIKELY(vol >= sustainLevel) ) {
00400             //Check if we didn't overshoot max attenuation, then just go off
00401             if ( GCC_UNLIKELY(vol >= ENV_MAX) ) {
00402                 volume = ENV_MAX;
00403                 SetState( OFF );
00404                 return ENV_MAX;
00405             }
00406             //Continue as sustain
00407             rateIndex = 0;
00408             SetState( SUSTAIN );
00409         }
00410         break;
00411     case SUSTAIN:
00412         if ( reg20 & MASK_SUSTAIN ) {
00413             return vol;
00414         }
00415         //In sustain phase, but not sustaining, do regular release
00416         //fall through
00417     case RELEASE:
00418         vol += RateForward( releaseAdd );
00419         if ( GCC_UNLIKELY(vol >= ENV_MAX) ) {
00420             volume = ENV_MAX;
00421             SetState( OFF );
00422             return ENV_MAX;
00423         }
00424         break;
00425     }
00426     volume = vol;
00427     return vol;
00428 }
00429 
00430 static const VolumeHandler VolumeHandlerTable[5] = {
00431     &Operator::TemplateVolume< Operator::OFF >,
00432     &Operator::TemplateVolume< Operator::RELEASE >,
00433     &Operator::TemplateVolume< Operator::SUSTAIN >,
00434     &Operator::TemplateVolume< Operator::DECAY >,
00435     &Operator::TemplateVolume< Operator::ATTACK >
00436 };
00437 
00438 INLINE Bitu Operator::ForwardVolume() {
00439     return currentLevel + (this->*volHandler)();
00440 }
00441 
00442 
00443 INLINE Bitu Operator::ForwardWave() {
00444     waveIndex += waveCurrent;
00445     return waveIndex >> WAVE_SH;
00446 }
00447 
00448 void Operator::Write20( const Chip* chip, Bit8u val ) {
00449     Bit8u change = (reg20 ^ val );
00450     if ( !change )
00451         return;
00452     reg20 = val;
00453     //Shift the tremolo bit over the entire register, saved a branch, YES!
00454     tremoloMask = (Bit8s)(val) >> 7;
00455     tremoloMask &= ~(( 1 << ENV_EXTRA ) -1);
00456     //Update specific features based on changes
00457     if ( change & MASK_KSR ) {
00458         UpdateRates( chip );
00459     }
00460     //With sustain enable the volume doesn't change
00461     if ( reg20 & MASK_SUSTAIN || ( !releaseAdd ) ) {
00462         rateZero |= ( 1 << SUSTAIN );
00463     } else {
00464         rateZero &= ~( 1 << SUSTAIN );
00465     }
00466     //Frequency multiplier or vibrato changed
00467     if ( change & (0xf | MASK_VIBRATO) ) {
00468         freqMul = chip->freqMul[ val & 0xf ];
00469         UpdateFrequency();
00470     }
00471 }
00472 
00473 void Operator::Write40( const Chip* /*chip*/, Bit8u val ) {
00474     if (!(reg40 ^ val ))
00475         return;
00476     reg40 = val;
00477     UpdateAttenuation( );
00478 }
00479 
00480 void Operator::Write60( const Chip* chip, Bit8u val ) {
00481     Bit8u change = reg60 ^ val;
00482     reg60 = val;
00483     if ( change & 0x0f ) {
00484         UpdateDecay( chip );
00485     }
00486     if ( change & 0xf0 ) {
00487         UpdateAttack( chip );
00488     }
00489 }
00490 
00491 void Operator::Write80( const Chip* chip, Bit8u val ) {
00492     Bit8u change = (reg80 ^ val );
00493     if ( !change )
00494         return;
00495     reg80 = val;
00496     Bit8u sustain = val >> 4;
00497     //Turn 0xf into 0x1f
00498     sustain |= ( sustain + 1) & 0x10;
00499     sustainLevel = sustain << ( ENV_BITS - 5 );
00500     if ( change & 0x0f ) {
00501         UpdateRelease( chip );
00502     }
00503 }
00504 
00505 void Operator::WriteE0( const Chip* chip, Bit8u val ) {
00506     if ( !(regE0 ^ val) )
00507         return;
00508     //in opl3 mode you can always selet 7 waveforms regardless of waveformselect
00509     Bit8u waveForm = val & ( ( 0x3 & chip->waveFormMask ) | (0x7 & chip->opl3Active ) );
00510     regE0 = val;
00511 #if ( DBOPL_WAVE == WAVE_HANDLER )
00512     waveHandler = WaveHandlerTable[ waveForm ];
00513 #else
00514     waveBase = WaveTable + WaveBaseTable[ waveForm ];
00515     waveStart = WaveStartTable[ waveForm ] << WAVE_SH;
00516     waveMask = WaveMaskTable[ waveForm ];
00517 #endif
00518 }
00519 
00520 INLINE void Operator::SetState( Bit8u s ) {
00521     state = s;
00522     volHandler = VolumeHandlerTable[ s ];
00523 }
00524 
00525 INLINE bool Operator::Silent() const {
00526     if ( !ENV_SILENT( totalLevel + volume ) )
00527         return false;
00528     if ( !(rateZero & ( 1 << state ) ) )
00529         return false;
00530     return true;
00531 }
00532 
00533 INLINE void Operator::Prepare( const Chip* chip )  {
00534     currentLevel = totalLevel + (chip->tremoloValue & tremoloMask);
00535     waveCurrent = waveAdd;
00536     if ( vibStrength >> chip->vibratoShift ) {
00537         Bit32s add = vibrato >> chip->vibratoShift;
00538         //Sign extend over the shift value
00539         Bit32s neg = chip->vibratoSign;
00540         //Negate the add with -1 or 0
00541         add = ( add ^ neg ) - neg;
00542         waveCurrent += add;
00543     }
00544 }
00545 
00546 void Operator::KeyOn( Bit8u mask ) {
00547     if ( !keyOn ) {
00548         //Restart the frequency generator
00549 #if ( DBOPL_WAVE > WAVE_HANDLER )
00550         waveIndex = waveStart;
00551 #else
00552         waveIndex = 0;
00553 #endif
00554         rateIndex = 0;
00555         SetState( ATTACK );
00556     }
00557     keyOn |= mask;
00558 }
00559 
00560 void Operator::KeyOff( Bit8u mask ) {
00561     keyOn &= ~mask;
00562     if ( !keyOn ) {
00563         if ( state != OFF ) {
00564             SetState( RELEASE );
00565         }
00566     }
00567 }
00568 
00569 INLINE Bits Operator::GetWave( Bitu index, Bitu vol ) {
00570 #if ( DBOPL_WAVE == WAVE_HANDLER )
00571     return waveHandler( index, vol << ( 3 - ENV_EXTRA ) );
00572 #elif ( DBOPL_WAVE == WAVE_TABLEMUL )
00573     return (waveBase[ index & waveMask ] * MulTable[ vol >> ENV_EXTRA ]) >> MUL_SH;
00574 #elif ( DBOPL_WAVE == WAVE_TABLELOG )
00575     Bit32s wave = waveBase[ index & waveMask ];
00576     Bit32u total = ( wave & 0x7fff ) + vol << ( 3 - ENV_EXTRA );
00577     Bit32s sig = ExpTable[ total & 0xff ];
00578     Bit32u exp = total >> 8;
00579     Bit32s neg = wave >> 16;
00580     return ((sig ^ neg) - neg) >> exp;
00581 #else
00582 #error "No valid wave routine"
00583 #endif
00584 }
00585 
00586 INLINE Bits Operator::GetSample( Bits modulation ) {
00587     Bitu vol = ForwardVolume();
00588     if ( ENV_SILENT( vol ) ) {
00589         //Simply forward the wave
00590         waveIndex += waveCurrent;
00591         return 0;
00592     } else {
00593         Bitu index = ForwardWave();
00594         index += modulation;
00595         return GetWave( index, vol );
00596     }
00597 }
00598 
00599 Operator::Operator() {
00600     chanData = 0;
00601     freqMul = 0;
00602     waveIndex = 0;
00603     waveAdd = 0;
00604     waveCurrent = 0;
00605     keyOn = 0;
00606     ksr = 0;
00607     reg20 = 0;
00608     reg40 = 0;
00609     reg60 = 0;
00610     reg80 = 0;
00611     regE0 = 0;
00612     SetState( OFF );
00613     rateZero = (1 << OFF);
00614     sustainLevel = ENV_MAX;
00615     currentLevel = ENV_MAX;
00616     totalLevel = ENV_MAX;
00617     volume = ENV_MAX;
00618     releaseAdd = 0;
00619 }
00620 
00621 /*
00622     Channel
00623 */
00624 
00625 Channel::Channel() {
00626     old[0] = old[1] = 0;
00627     chanData = 0;
00628     regB0 = 0;
00629     regC0 = 0;
00630     maskLeft = -1;
00631     maskRight = -1;
00632     feedback = 31;
00633     fourMask = 0;
00634     synthHandler = &Channel::BlockTemplate< sm2FM >;
00635 }
00636 
00637 void Channel::SetChanData( const Chip* chip, Bit32u data ) {
00638     Bit32u change = chanData ^ data;
00639     chanData = data;
00640     Op( 0 )->chanData = data;
00641     Op( 1 )->chanData = data;
00642     //Since a frequency update triggered this, always update frequency
00643     Op( 0 )->UpdateFrequency();
00644     Op( 1 )->UpdateFrequency();
00645     if ( change & ( 0xff << SHIFT_KSLBASE ) ) {
00646         Op( 0 )->UpdateAttenuation();
00647         Op( 1 )->UpdateAttenuation();
00648     }
00649     if ( change & ( 0xff << SHIFT_KEYCODE ) ) {
00650         Op( 0 )->UpdateRates( chip );
00651         Op( 1 )->UpdateRates( chip );
00652     }
00653 }
00654 
00655 void Channel::UpdateFrequency( const Chip* chip, Bit8u fourOp ) {
00656     //Extrace the frequency bits
00657     Bit32u data = chanData & 0xffff;
00658     Bit32u kslBase = KslTable[ data >> 6 ];
00659     Bit32u keyCode = ( data & 0x1c00) >> 9;
00660     if ( chip->reg08 & 0x40 ) {
00661         keyCode |= ( data & 0x100)>>8;  /* notesel == 1 */
00662     } else {
00663         keyCode |= ( data & 0x200)>>9;  /* notesel == 0 */
00664     }
00665     //Add the keycode and ksl into the highest bits of chanData
00666     data |= (keyCode << SHIFT_KEYCODE) | ( kslBase << SHIFT_KSLBASE );
00667     ( this + 0 )->SetChanData( chip, data );
00668     if ( fourOp & 0x3f ) {
00669         ( this + 1 )->SetChanData( chip, data );
00670     }
00671 }
00672 
00673 void Channel::WriteA0( const Chip* chip, Bit8u val ) {
00674     Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask;
00675     //Don't handle writes to silent fourop channels
00676     if ( fourOp > 0x80 )
00677         return;
00678     Bit32u change = (chanData ^ val ) & 0xff;
00679     if ( change ) {
00680         chanData ^= change;
00681         UpdateFrequency( chip, fourOp );
00682     }
00683 }
00684 
00685 void Channel::WriteB0( const Chip* chip, Bit8u val ) {
00686     Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask;
00687     //Don't handle writes to silent fourop channels
00688     if ( fourOp > 0x80 )
00689         return;
00690     Bitu change = (chanData ^ ( val << 8 ) ) & 0x1f00;
00691     if ( change ) {
00692         chanData ^= change;
00693         UpdateFrequency( chip, fourOp );
00694     }
00695     //Check for a change in the keyon/off state
00696     if ( !(( val ^ regB0) & 0x20))
00697         return;
00698     regB0 = val;
00699     if ( val & 0x20 ) {
00700         Op(0)->KeyOn( 0x1 );
00701         Op(1)->KeyOn( 0x1 );
00702         if ( fourOp & 0x3f ) {
00703             ( this + 1 )->Op(0)->KeyOn( 1 );
00704             ( this + 1 )->Op(1)->KeyOn( 1 );
00705         }
00706     } else {
00707         Op(0)->KeyOff( 0x1 );
00708         Op(1)->KeyOff( 0x1 );
00709         if ( fourOp & 0x3f ) {
00710             ( this + 1 )->Op(0)->KeyOff( 1 );
00711             ( this + 1 )->Op(1)->KeyOff( 1 );
00712         }
00713     }
00714 }
00715 
00716 void Channel::WriteC0( const Chip* chip, Bit8u val ) {
00717     Bit8u change = val ^ regC0;
00718     if ( !change )
00719         return;
00720     regC0 = val;
00721     feedback = ( val >> 1 ) & 7;
00722     if ( feedback ) {
00723         //We shift the input to the right 10 bit wave index value
00724         feedback = 9 - feedback;
00725     } else {
00726         feedback = 31;
00727     }
00728     //Select the new synth mode
00729     if ( chip->opl3Active ) {
00730         //4-op mode enabled for this channel
00731         if ( (chip->reg104 & fourMask) & 0x3f ) {
00732             Channel* chan0, *chan1;
00733             //Check if it's the 2nd channel in a 4-op
00734             if ( !(fourMask & 0x80 ) ) {
00735                 chan0 = this;
00736                 chan1 = this + 1;
00737             } else {
00738                 chan0 = this - 1;
00739                 chan1 = this;
00740             }
00741 
00742             Bit8u synth = ( (chan0->regC0 & 1) << 0 )| (( chan1->regC0 & 1) << 1 );
00743             switch ( synth ) {
00744             case 0:
00745                 chan0->synthHandler = &Channel::BlockTemplate< sm3FMFM >;
00746                 break;
00747             case 1:
00748                 chan0->synthHandler = &Channel::BlockTemplate< sm3AMFM >;
00749                 break;
00750             case 2:
00751                 chan0->synthHandler = &Channel::BlockTemplate< sm3FMAM >;
00752                 break;
00753             case 3:
00754                 chan0->synthHandler = &Channel::BlockTemplate< sm3AMAM >;
00755                 break;
00756             }
00757         //Disable updating percussion channels
00758         } else if ((fourMask & 0x40) && ( chip->regBD & 0x20) ) {
00759 
00760         //Regular dual op, am or fm
00761         } else if ( val & 1 ) {
00762             synthHandler = &Channel::BlockTemplate< sm3AM >;
00763         } else {
00764             synthHandler = &Channel::BlockTemplate< sm3FM >;
00765         }
00766         maskLeft = ( val & 0x10 ) ? -1 : 0;
00767         maskRight = ( val & 0x20 ) ? -1 : 0;
00768     //opl2 active
00769     } else {
00770         //Disable updating percussion channels
00771         if ( (fourMask & 0x40) && ( chip->regBD & 0x20 ) ) {
00772 
00773         //Regular dual op, am or fm
00774         } else if ( val & 1 ) {
00775             synthHandler = &Channel::BlockTemplate< sm2AM >;
00776         } else {
00777             synthHandler = &Channel::BlockTemplate< sm2FM >;
00778         }
00779     }
00780 }
00781 
00782 void Channel::ResetC0( const Chip* chip ) {
00783     Bit8u val = regC0;
00784     regC0 ^= 0xff;
00785     WriteC0( chip, val );
00786 }
00787 
00788 template< bool opl3Mode>
00789 INLINE void Channel::GeneratePercussion( Chip* chip, Bit32s* output ) {
00790     Channel* chan = this;
00791 
00792     //BassDrum
00793     Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback;
00794     old[0] = old[1];
00795     old[1] = Op(0)->GetSample( mod );
00796 
00797     //When bassdrum is in AM mode first operator is ignoed
00798     if ( chan->regC0 & 1 ) {
00799         mod = 0;
00800     } else {
00801         mod = old[0];
00802     }
00803     Bit32s sample = Op(1)->GetSample( mod );
00804 
00805 
00806     //Precalculate stuff used by other outputs
00807     Bit32u noiseBit = chip->ForwardNoise() & 0x1;
00808     Bit32u c2 = Op(2)->ForwardWave();
00809     Bit32u c5 = Op(5)->ForwardWave();
00810     Bit32u phaseBit = (((c2 & 0x88) ^ ((c2<<5) & 0x80)) | ((c5 ^ (c5<<2)) & 0x20)) ? 0x02 : 0x00;
00811 
00812     //Hi-Hat
00813     Bit32u hhVol = Op(2)->ForwardVolume();
00814     if ( !ENV_SILENT( hhVol ) ) {
00815         Bit32u hhIndex = (phaseBit<<8) | (0x34 << ( phaseBit ^ (noiseBit << 1 )));
00816         sample += Op(2)->GetWave( hhIndex, hhVol );
00817     }
00818     //Snare Drum
00819     Bit32u sdVol = Op(3)->ForwardVolume();
00820     if ( !ENV_SILENT( sdVol ) ) {
00821         Bit32u sdIndex = ( 0x100 + (c2 & 0x100) ) ^ ( noiseBit << 8 );
00822         sample += Op(3)->GetWave( sdIndex, sdVol );
00823     }
00824     //Tom-tom
00825     sample += Op(4)->GetSample( 0 );
00826 
00827     //Top-Cymbal
00828     Bit32u tcVol = Op(5)->ForwardVolume();
00829     if ( !ENV_SILENT( tcVol ) ) {
00830         Bit32u tcIndex = (1 + phaseBit) << 8;
00831         sample += Op(5)->GetWave( tcIndex, tcVol );
00832     }
00833     sample <<= 1;
00834     if ( opl3Mode ) {
00835         output[0] += sample;
00836         output[1] += sample;
00837     } else {
00838         output[0] += sample;
00839     }
00840 }
00841 
00842 template<SynthMode mode>
00843 Channel* Channel::BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output ) {
00844     switch( mode ) {
00845     case sm2AM:
00846     case sm3AM:
00847         if ( Op(0)->Silent() && Op(1)->Silent() ) {
00848             old[0] = old[1] = 0;
00849             return (this + 1);
00850         }
00851         break;
00852     case sm2FM:
00853     case sm3FM:
00854         if ( Op(1)->Silent() ) {
00855             old[0] = old[1] = 0;
00856             return (this + 1);
00857         }
00858         break;
00859     case sm3FMFM:
00860         if ( Op(3)->Silent() ) {
00861             old[0] = old[1] = 0;
00862             return (this + 2);
00863         }
00864         break;
00865     case sm3AMFM:
00866         if ( Op(0)->Silent() && Op(3)->Silent() ) {
00867             old[0] = old[1] = 0;
00868             return (this + 2);
00869         }
00870         break;
00871     case sm3FMAM:
00872         if ( Op(1)->Silent() && Op(3)->Silent() ) {
00873             old[0] = old[1] = 0;
00874             return (this + 2);
00875         }
00876         break;
00877     case sm3AMAM:
00878         if ( Op(0)->Silent() && Op(2)->Silent() && Op(3)->Silent() ) {
00879             old[0] = old[1] = 0;
00880             return (this + 2);
00881         }
00882         break;
00883     case sm2Percussion:
00884         // This case was not handled in the DOSBox code either
00885         // thus we leave this blank.
00886         // TODO: Consider checking this.
00887         break;
00888     case sm3Percussion:
00889         // This case was not handled in the DOSBox code either
00890         // thus we leave this blank.
00891         // TODO: Consider checking this.
00892         break;
00893     case sm4Start:
00894         // This case was not handled in the DOSBox code either
00895         // thus we leave this blank.
00896         // TODO: Consider checking this.
00897         break;
00898     case sm6Start:
00899         // This case was not handled in the DOSBox code either
00900         // thus we leave this blank.
00901         // TODO: Consider checking this.
00902         break;
00903     }
00904     //Init the operators with the the current vibrato and tremolo values
00905     Op( 0 )->Prepare( chip );
00906     Op( 1 )->Prepare( chip );
00907     if ( mode > sm4Start ) {
00908         Op( 2 )->Prepare( chip );
00909         Op( 3 )->Prepare( chip );
00910     }
00911     if ( mode > sm6Start ) {
00912         Op( 4 )->Prepare( chip );
00913         Op( 5 )->Prepare( chip );
00914     }
00915     for ( Bitu i = 0; i < samples; i++ ) {
00916         //Early out for percussion handlers
00917         if ( mode == sm2Percussion ) {
00918             GeneratePercussion<false>( chip, output + i );
00919             continue;   //Prevent some unitialized value bitching
00920         } else if ( mode == sm3Percussion ) {
00921             GeneratePercussion<true>( chip, output + i * 2 );
00922             continue;   //Prevent some unitialized value bitching
00923         }
00924 
00925         //Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
00926         Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback;
00927         old[0] = old[1];
00928         old[1] = Op(0)->GetSample( mod );
00929         Bit32s sample;
00930         Bit32s out0 = old[0];
00931         if ( mode == sm2AM || mode == sm3AM ) {
00932             sample = out0 + Op(1)->GetSample( 0 );
00933         } else if ( mode == sm2FM || mode == sm3FM ) {
00934             sample = Op(1)->GetSample( out0 );
00935         } else if ( mode == sm3FMFM ) {
00936             Bits next = Op(1)->GetSample( out0 );
00937             next = Op(2)->GetSample( next );
00938             sample = Op(3)->GetSample( next );
00939         } else if ( mode == sm3AMFM ) {
00940             sample = out0;
00941             Bits next = Op(1)->GetSample( 0 );
00942             next = Op(2)->GetSample( next );
00943             sample += Op(3)->GetSample( next );
00944         } else if ( mode == sm3FMAM ) {
00945             sample = Op(1)->GetSample( out0 );
00946             Bits next = Op(2)->GetSample( 0 );
00947             sample += Op(3)->GetSample( next );
00948         } else if ( mode == sm3AMAM ) {
00949             sample = out0;
00950             Bits next = Op(1)->GetSample( 0 );
00951             sample += Op(2)->GetSample( next );
00952             sample += Op(3)->GetSample( 0 );
00953         }
00954         switch( mode ) {
00955         case sm2AM:
00956         case sm2FM:
00957             output[ i ] += sample;
00958             break;
00959         case sm3AM:
00960         case sm3FM:
00961         case sm3FMFM:
00962         case sm3AMFM:
00963         case sm3FMAM:
00964         case sm3AMAM:
00965             output[ i * 2 + 0 ] += sample & maskLeft;
00966             output[ i * 2 + 1 ] += sample & maskRight;
00967             break;
00968         case sm2Percussion:
00969             // This case was not handled in the DOSBox code either
00970             // thus we leave this blank.
00971             // TODO: Consider checking this.
00972             break;
00973         case sm3Percussion:
00974             // This case was not handled in the DOSBox code either
00975             // thus we leave this blank.
00976             // TODO: Consider checking this.
00977             break;
00978         case sm4Start:
00979             // This case was not handled in the DOSBox code either
00980             // thus we leave this blank.
00981             // TODO: Consider checking this.
00982             break;
00983         case sm6Start:
00984             // This case was not handled in the DOSBox code either
00985             // thus we leave this blank.
00986             // TODO: Consider checking this.
00987             break;
00988         }
00989     }
00990     switch( mode ) {
00991     case sm2AM:
00992     case sm2FM:
00993     case sm3AM:
00994     case sm3FM:
00995         return ( this + 1 );
00996     case sm3FMFM:
00997     case sm3AMFM:
00998     case sm3FMAM:
00999     case sm3AMAM:
01000         return( this + 2 );
01001     case sm2Percussion:
01002     case sm3Percussion:
01003         return( this + 3 );
01004     case sm4Start:
01005         // This case was not handled in the DOSBox code either
01006         // thus we leave this blank.
01007         // TODO: Consider checking this.
01008         break;
01009     case sm6Start:
01010         // This case was not handled in the DOSBox code either
01011         // thus we leave this blank.
01012         // TODO: Consider checking this.
01013         break;
01014     }
01015     return 0;
01016 }
01017 
01018 /*
01019     Chip
01020 */
01021 
01022 Chip::Chip() {
01023     reg08 = 0;
01024     reg04 = 0;
01025     regBD = 0;
01026     reg104 = 0;
01027     opl3Active = 0;
01028 }
01029 
01030 INLINE Bit32u Chip::ForwardNoise() {
01031     noiseCounter += noiseAdd;
01032     Bitu count = noiseCounter >> LFO_SH;
01033     noiseCounter &= WAVE_MASK;
01034     for ( ; count > 0; --count ) {
01035         //Noise calculation from mame
01036         noiseValue ^= ( 0x800302 ) & ( 0 - (noiseValue & 1 ) );
01037         noiseValue >>= 1;
01038     }
01039     return noiseValue;
01040 }
01041 
01042 INLINE Bit32u Chip::ForwardLFO( Bit32u samples ) {
01043     //Current vibrato value, runs 4x slower than tremolo
01044     vibratoSign = ( VibratoTable[ vibratoIndex >> 2] ) >> 7;
01045     vibratoShift = ( VibratoTable[ vibratoIndex >> 2] & 7) + vibratoStrength;
01046     tremoloValue = TremoloTable[ tremoloIndex ] >> tremoloStrength;
01047 
01048     //Check hom many samples there can be done before the value changes
01049     Bit32u todo = LFO_MAX - lfoCounter;
01050     Bit32u count = (todo + lfoAdd - 1) / lfoAdd;
01051     if ( count > samples ) {
01052         count = samples;
01053         lfoCounter += count * lfoAdd;
01054     } else {
01055         lfoCounter += count * lfoAdd;
01056         lfoCounter &= (LFO_MAX - 1);
01057         //Maximum of 7 vibrato value * 4
01058         vibratoIndex = ( vibratoIndex + 1 ) & 31;
01059         //Clip tremolo to the the table size
01060         if ( tremoloIndex + 1 < TREMOLO_TABLE  )
01061             ++tremoloIndex;
01062         else
01063             tremoloIndex = 0;
01064     }
01065     return count;
01066 }
01067 
01068 
01069 void Chip::WriteBD( Bit8u val ) {
01070     Bit8u change = regBD ^ val;
01071     if ( !change )
01072         return;
01073     regBD = val;
01074     //TODO could do this with shift and xor?
01075     vibratoStrength = (val & 0x40) ? 0x00 : 0x01;
01076     tremoloStrength = (val & 0x80) ? 0x00 : 0x02;
01077     if ( val & 0x20 ) {
01078         //Drum was just enabled, make sure channel 6 has the right synth
01079         if ( change & 0x20 ) {
01080             if ( opl3Active ) {
01081                 chan[6].synthHandler = &Channel::BlockTemplate< sm3Percussion >;
01082             } else {
01083                 chan[6].synthHandler = &Channel::BlockTemplate< sm2Percussion >;
01084             }
01085         }
01086         //Bass Drum
01087         if ( val & 0x10 ) {
01088             chan[6].op[0].KeyOn( 0x2 );
01089             chan[6].op[1].KeyOn( 0x2 );
01090         } else {
01091             chan[6].op[0].KeyOff( 0x2 );
01092             chan[6].op[1].KeyOff( 0x2 );
01093         }
01094         //Hi-Hat
01095         if ( val & 0x1 ) {
01096             chan[7].op[0].KeyOn( 0x2 );
01097         } else {
01098             chan[7].op[0].KeyOff( 0x2 );
01099         }
01100         //Snare
01101         if ( val & 0x8 ) {
01102             chan[7].op[1].KeyOn( 0x2 );
01103         } else {
01104             chan[7].op[1].KeyOff( 0x2 );
01105         }
01106         //Tom-Tom
01107         if ( val & 0x4 ) {
01108             chan[8].op[0].KeyOn( 0x2 );
01109         } else {
01110             chan[8].op[0].KeyOff( 0x2 );
01111         }
01112         //Top Cymbal
01113         if ( val & 0x2 ) {
01114             chan[8].op[1].KeyOn( 0x2 );
01115         } else {
01116             chan[8].op[1].KeyOff( 0x2 );
01117         }
01118     //Toggle keyoffs when we turn off the percussion
01119     } else if ( change & 0x20 ) {
01120         //Trigger a reset to setup the original synth handler
01121         chan[6].ResetC0( this );
01122         chan[6].op[0].KeyOff( 0x2 );
01123         chan[6].op[1].KeyOff( 0x2 );
01124         chan[7].op[0].KeyOff( 0x2 );
01125         chan[7].op[1].KeyOff( 0x2 );
01126         chan[8].op[0].KeyOff( 0x2 );
01127         chan[8].op[1].KeyOff( 0x2 );
01128     }
01129 }
01130 
01131 
01132 #define REGOP( _FUNC_ )                                                         \
01133     index = ( ( reg >> 3) & 0x20 ) | ( reg & 0x1f );                                \
01134     if ( OpOffsetTable[ index ] ) {                                                 \
01135         Operator* regOp = (Operator *)( ((char *)this ) + OpOffsetTable[ index ] ); \
01136         regOp->_FUNC_( this, val );                                                 \
01137     }
01138 
01139 #define REGCHAN( _FUNC_ )                                                               \
01140     index = ( ( reg >> 4) & 0x10 ) | ( reg & 0xf );                                     \
01141     if ( ChanOffsetTable[ index ] ) {                                                   \
01142         Channel* regChan = (Channel *)( ((char *)this ) + ChanOffsetTable[ index ] );   \
01143         regChan->_FUNC_( this, val );                                                   \
01144     }
01145 
01146 void Chip::WriteReg( Bit32u reg, Bit8u val ) {
01147     Bitu index;
01148     switch ( (reg & 0xf0) >> 4 ) {
01149     case 0x00 >> 4:
01150         if ( reg == 0x01 ) {
01151             waveFormMask = ( val & 0x20 ) ? 0x7 : 0x0;
01152         } else if ( reg == 0x104 ) {
01153             //Only detect changes in lowest 6 bits
01154             if ( !((reg104 ^ val) & 0x3f) )
01155                 return;
01156             //Always keep the highest bit enabled, for checking > 0x80
01157             reg104 = 0x80 | ( val & 0x3f );
01158         } else if ( reg == 0x105 ) {
01159             //MAME says the real opl3 doesn't reset anything on opl3 disable/enable till the next write in another register
01160             if ( !((opl3Active ^ val) & 1 ) )
01161                 return;
01162             opl3Active = ( val & 1 ) ? 0xff : 0;
01163             //Update the 0xc0 register for all channels to signal the switch to mono/stereo handlers
01164             for ( int i = 0; i < 18;i++ ) {
01165                 chan[i].ResetC0( this );
01166             }
01167         } else if ( reg == 0x08 ) {
01168             reg08 = val;
01169         }
01170     case 0x10 >> 4:
01171         break;
01172     case 0x20 >> 4:
01173     case 0x30 >> 4:
01174         REGOP( Write20 );
01175         break;
01176     case 0x40 >> 4:
01177     case 0x50 >> 4:
01178         REGOP( Write40 );
01179         break;
01180     case 0x60 >> 4:
01181     case 0x70 >> 4:
01182         REGOP( Write60 );
01183         break;
01184     case 0x80 >> 4:
01185     case 0x90 >> 4:
01186         REGOP( Write80 );
01187         break;
01188     case 0xa0 >> 4:
01189         REGCHAN( WriteA0 );
01190         break;
01191     case 0xb0 >> 4:
01192         if ( reg == 0xbd ) {
01193             WriteBD( val );
01194         } else {
01195             REGCHAN( WriteB0 );
01196         }
01197         break;
01198     case 0xc0 >> 4:
01199         REGCHAN( WriteC0 );
01200     case 0xd0 >> 4:
01201         break;
01202     case 0xe0 >> 4:
01203     case 0xf0 >> 4:
01204         REGOP( WriteE0 );
01205         break;
01206     }
01207 }
01208 
01209 
01210 Bit32u Chip::WriteAddr( Bit32u port, Bit8u val ) {
01211     switch ( port & 3 ) {
01212     case 0:
01213         return val;
01214     case 2:
01215         if ( opl3Active || (val == 0x05) )
01216             return 0x100 | val;
01217         else
01218             return val;
01219     }
01220     return 0;
01221 }
01222 
01223 void Chip::GenerateBlock2( Bitu total, Bit32s* output ) {
01224     while ( total > 0 ) {
01225         Bit32u samples = ForwardLFO( total );
01226         memset(output, 0, sizeof(Bit32s) * samples);
01227         int count = 0;
01228         for( Channel* ch = chan; ch < chan + 9; ) {
01229             count++;
01230             ch = (ch->*(ch->synthHandler))( this, samples, output );
01231         }
01232         total -= samples;
01233         output += samples;
01234     }
01235 }
01236 
01237 void Chip::GenerateBlock3( Bitu total, Bit32s* output  ) {
01238     while ( total > 0 ) {
01239         Bit32u samples = ForwardLFO( total );
01240         memset(output, 0, sizeof(Bit32s) * samples * 2);
01241         int count = 0;
01242         for( Channel* ch = chan; ch < chan + 18; ) {
01243             count++;
01244             ch = (ch->*(ch->synthHandler))( this, samples, output );
01245         }
01246         total -= samples;
01247         output += samples * 2;
01248     }
01249 }
01250 
01251 void Chip::Setup( Bit32u rate ) {
01252     double scale = OPLRATE / (double)rate;
01253 
01254     //Noise counter is run at the same precision as general waves
01255     noiseAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) );
01256     noiseCounter = 0;
01257     noiseValue = 1; //Make sure it triggers the noise xor the first time
01258     //The low frequency oscillation counter
01259     //Every time his overflows vibrato and tremoloindex are increased
01260     lfoAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) );
01261     lfoCounter = 0;
01262     vibratoIndex = 0;
01263     tremoloIndex = 0;
01264 
01265     //With higher octave this gets shifted up
01266     //-1 since the freqCreateTable = *2
01267 #ifdef WAVE_PRECISION
01268     double freqScale = ( 1 << 7 ) * scale * ( 1 << ( WAVE_SH - 1 - 10));
01269     for ( int i = 0; i < 16; i++ ) {
01270         freqMul[i] = (Bit32u)( 0.5 + freqScale * FreqCreateTable[ i ] );
01271     }
01272 #else
01273     Bit32u freqScale = (Bit32u)( 0.5 + scale * ( 1 << ( WAVE_SH - 1 - 10)));
01274     for ( int i = 0; i < 16; i++ ) {
01275         freqMul[i] = freqScale * FreqCreateTable[ i ];
01276     }
01277 #endif
01278 
01279     //-3 since the real envelope takes 8 steps to reach the single value we supply
01280     for ( Bit8u i = 0; i < 76; i++ ) {
01281         Bit8u index, shift;
01282         EnvelopeSelect( i, index, shift );
01283         linearRates[i] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 )));
01284     }
01285     //Generate the best matching attack rate
01286     for ( Bit8u i = 0; i < 62; i++ ) {
01287         Bit8u index, shift;
01288         EnvelopeSelect( i, index, shift );
01289         //Original amount of samples the attack would take
01290         Bit32s original = (Bit32u)( (AttackSamplesTable[ index ] << shift) / scale);
01291 
01292         Bit32s guessAdd = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH - shift - 3 )));
01293         Bit32s bestAdd = guessAdd;
01294         Bit32u bestDiff = 1 << 30;
01295         for( Bit32u passes = 0; passes < 16; passes ++ ) {
01296             Bit32s volume = ENV_MAX;
01297             Bit32s samples = 0;
01298             Bit32u count = 0;
01299             while ( volume > 0 && samples < original * 2 ) {
01300                 count += guessAdd;
01301                 Bit32s change = count >> RATE_SH;
01302                 count &= RATE_MASK;
01303                 if ( GCC_UNLIKELY(change) ) { // less than 1 %
01304                     volume += ( ~volume * change ) >> 3;
01305                 }
01306                 samples++;
01307 
01308             }
01309             Bit32s diff = original - samples;
01310             Bit32u lDiff = labs( diff );
01311             //Init last on first pass
01312             if ( lDiff < bestDiff ) {
01313                 bestDiff = lDiff;
01314                 bestAdd = guessAdd;
01315                 if ( !bestDiff )
01316                     break;
01317             }
01318             //Below our target
01319             if ( diff < 0 ) {
01320                 //Better than the last time
01321                 Bit32s mul = ((original - diff) << 12) / original;
01322                 guessAdd = ((guessAdd * mul) >> 12);
01323                 guessAdd++;
01324             } else if ( diff > 0 ) {
01325                 Bit32s mul = ((original - diff) << 12) / original;
01326                 guessAdd = (guessAdd * mul) >> 12;
01327                 guessAdd--;
01328             }
01329         }
01330         attackRates[i] = bestAdd;
01331     }
01332     for ( Bit8u i = 62; i < 76; i++ ) {
01333         //This should provide instant volume maximizing
01334         attackRates[i] = 8 << RATE_SH;
01335     }
01336     //Setup the channels with the correct four op flags
01337     //Channels are accessed through a table so they appear linear here
01338     chan[ 0].fourMask = 0x00 | ( 1 << 0 );
01339     chan[ 1].fourMask = 0x80 | ( 1 << 0 );
01340     chan[ 2].fourMask = 0x00 | ( 1 << 1 );
01341     chan[ 3].fourMask = 0x80 | ( 1 << 1 );
01342     chan[ 4].fourMask = 0x00 | ( 1 << 2 );
01343     chan[ 5].fourMask = 0x80 | ( 1 << 2 );
01344 
01345     chan[ 9].fourMask = 0x00 | ( 1 << 3 );
01346     chan[10].fourMask = 0x80 | ( 1 << 3 );
01347     chan[11].fourMask = 0x00 | ( 1 << 4 );
01348     chan[12].fourMask = 0x80 | ( 1 << 4 );
01349     chan[13].fourMask = 0x00 | ( 1 << 5 );
01350     chan[14].fourMask = 0x80 | ( 1 << 5 );
01351 
01352     //mark the percussion channels
01353     chan[ 6].fourMask = 0x40;
01354     chan[ 7].fourMask = 0x40;
01355     chan[ 8].fourMask = 0x40;
01356 
01357     //Clear Everything in opl3 mode
01358     WriteReg( 0x105, 0x1 );
01359     for ( int i = 0; i < 512; i++ ) {
01360         if ( i == 0x105 )
01361             continue;
01362         WriteReg( i, 0xff );
01363         WriteReg( i, 0x0 );
01364     }
01365     WriteReg( 0x105, 0x0 );
01366     //Clear everything in opl2 mode
01367     for ( int i = 0; i < 255; i++ ) {
01368         WriteReg( i, 0xff );
01369         WriteReg( i, 0x0 );
01370     }
01371 }
01372 
01373 static bool doneTables = false;
01374 void InitTables( void ) {
01375     if ( doneTables )
01376         return;
01377     doneTables = true;
01378 #if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
01379     //Exponential volume table, same as the real adlib
01380     for ( int i = 0; i < 256; i++ ) {
01381         //Save them in reverse
01382         ExpTable[i] = (int)( 0.5 + ( pow(2.0, ( 255 - i) * ( 1.0 /256 ) )-1) * 1024 );
01383         ExpTable[i] += 1024; //or remove the -1 oh well :)
01384         //Preshift to the left once so the final volume can shift to the right
01385         ExpTable[i] *= 2;
01386     }
01387 #endif
01388 #if ( DBOPL_WAVE == WAVE_HANDLER )
01389     //Add 0.5 for the trunc rounding of the integer cast
01390     //Do a PI sinetable instead of the original 0.5 PI
01391     for ( int i = 0; i < 512; i++ ) {
01392         SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (M_PI / 512.0) ) ) / log10(2.0)*256 );
01393     }
01394 #endif
01395 #if ( DBOPL_WAVE == WAVE_TABLEMUL )
01396     //Multiplication based tables
01397     for ( int i = 0; i < 384; i++ ) {
01398         int s = i * 8;
01399         //TODO maybe keep some of the precision errors of the original table?
01400         double val = ( 0.5 + ( pow(2.0, -1.0 + ( 255 - s) * ( 1.0 /256 ) )) * ( 1 << MUL_SH ));
01401         MulTable[i] = (Bit16u)(val);
01402     }
01403 
01404     //Sine Wave Base
01405     for ( int i = 0; i < 512; i++ ) {
01406         WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (M_PI / 512.0) ) * 4084);
01407         WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ];
01408     }
01409     //Exponential wave
01410     for ( int i = 0; i < 256; i++ ) {
01411         WaveTable[ 0x700 + i ] = (Bit16s)( 0.5 + ( pow(2.0, -1.0 + ( 255 - i * 8) * ( 1.0 /256 ) ) ) * 4085 );
01412         WaveTable[ 0x6ff - i ] = -WaveTable[ 0x700 + i ];
01413     }
01414 #endif
01415 #if ( DBOPL_WAVE == WAVE_TABLELOG )
01416     //Sine Wave Base
01417     for ( int i = 0; i < 512; i++ ) {
01418         WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (M_PI / 512.0) ) ) / log10(2.0)*256 );
01419         WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i];
01420     }
01421     //Exponential wave
01422     for ( int i = 0; i < 256; i++ ) {
01423         WaveTable[ 0x700 + i ] = i * 8;
01424         WaveTable[ 0x6ff - i ] = ((Bit16s)0x8000) | i * 8;
01425     }
01426 #endif
01427 
01428     //  |    |//\\|____|WAV7|//__|/\  |____|/\/\|
01429     //  |\\//|    |    |WAV7|    |  \/|    |    |
01430     //  |06  |0126|27  |7   |3   |4   |4 5 |5   |
01431 
01432 #if (( DBOPL_WAVE == WAVE_TABLELOG ) || ( DBOPL_WAVE == WAVE_TABLEMUL ))
01433     for ( int i = 0; i < 256; i++ ) {
01434         //Fill silence gaps
01435         WaveTable[ 0x400 + i ] = WaveTable[0];
01436         WaveTable[ 0x500 + i ] = WaveTable[0];
01437         WaveTable[ 0x900 + i ] = WaveTable[0];
01438         WaveTable[ 0xc00 + i ] = WaveTable[0];
01439         WaveTable[ 0xd00 + i ] = WaveTable[0];
01440         //Replicate sines in other pieces
01441         WaveTable[ 0x800 + i ] = WaveTable[ 0x200 + i ];
01442         //double speed sines
01443         WaveTable[ 0xa00 + i ] = WaveTable[ 0x200 + i * 2 ];
01444         WaveTable[ 0xb00 + i ] = WaveTable[ 0x000 + i * 2 ];
01445         WaveTable[ 0xe00 + i ] = WaveTable[ 0x200 + i * 2 ];
01446         WaveTable[ 0xf00 + i ] = WaveTable[ 0x200 + i * 2 ];
01447     }
01448 #endif
01449 
01450     //Create the ksl table
01451     for ( int oct = 0; oct < 8; oct++ ) {
01452         int base = oct * 8;
01453         for ( int i = 0; i < 16; i++ ) {
01454             int val = base - KslCreateTable[i];
01455             if ( val < 0 )
01456                 val = 0;
01457             //*4 for the final range to match attenuation range
01458             KslTable[ oct * 16 + i ] = val * 4;
01459         }
01460     }
01461     //Create the Tremolo table, just increase and decrease a triangle wave
01462     for ( Bit8u i = 0; i < TREMOLO_TABLE / 2; i++ ) {
01463         Bit8u val = i << ENV_EXTRA;
01464         TremoloTable[i] = val;
01465         TremoloTable[TREMOLO_TABLE - 1 - i] = val;
01466     }
01467     //Create a table with offsets of the channels from the start of the chip
01468     DBOPL::Chip* chip = 0;
01469     for ( Bitu i = 0; i < 32; i++ ) {
01470         Bitu index = i & 0xf;
01471         if ( index >= 9 ) {
01472             ChanOffsetTable[i] = 0;
01473             continue;
01474         }
01475         //Make sure the four op channels follow eachother
01476         if ( index < 6 ) {
01477             index = (index % 3) * 2 + ( index / 3 );
01478         }
01479         //Add back the bits for highest ones
01480         if ( i >= 16 )
01481             index += 9;
01482         Bitu blah = reinterpret_cast<size_t>( &(chip->chan[ index ]) );
01483         ChanOffsetTable[i] = blah;
01484     }
01485     //Same for operators
01486     for ( Bitu i = 0; i < 64; i++ ) {
01487         if ( i % 8 >= 6 || ( (i / 8) % 4 == 3 ) ) {
01488             OpOffsetTable[i] = 0;
01489             continue;
01490         }
01491         Bitu chNum = (i / 8) * 3 + (i % 8) % 3;
01492         //Make sure we use 16 and up for the 2nd range to match the chanoffset gap
01493         if ( chNum >= 12 )
01494             chNum += 16 - 12;
01495         Bitu opNum = ( i % 8 ) / 3;
01496         DBOPL::Channel* chan = 0;
01497         Bitu blah = reinterpret_cast<size_t>( &(chan->op[opNum]) );
01498         OpOffsetTable[i] = ChanOffsetTable[ chNum ] + blah;
01499     }
01500 #if 0
01501     //Stupid checks if table's are correct
01502     for ( Bitu i = 0; i < 18; i++ ) {
01503         Bit32u find = (Bit16u)( &(chip->chan[ i ]) );
01504         for ( Bitu c = 0; c < 32; c++ ) {
01505             if ( ChanOffsetTable[c] == find ) {
01506                 find = 0;
01507                 break;
01508             }
01509         }
01510         if ( find ) {
01511             find = find;
01512         }
01513     }
01514     for ( Bitu i = 0; i < 36; i++ ) {
01515         Bit32u find = (Bit16u)( &(chip->chan[ i / 2 ].op[i % 2]) );
01516         for ( Bitu c = 0; c < 64; c++ ) {
01517             if ( OpOffsetTable[c] == find ) {
01518                 find = 0;
01519                 break;
01520             }
01521         }
01522         if ( find ) {
01523             find = find;
01524         }
01525     }
01526 #endif
01527 }
01528 
01529 }       //Namespace DBOPL
01530 } // End of namespace DOSBox
01531 } // End of namespace OPL
01532 
01533 #endif // !DISABLE_DOSBOX_OPL


Generated on Sat Mar 16 2019 05:01:24 for ResidualVM by doxygen 1.7.1
curved edge   curved edge