Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

eeconfig.cpp

Go to the documentation of this file.
00001 //
00002 // /home/ms/sidplay/libsidplay/RCS/eeconfig.cpp,v
00003 //
00004 // SID Emulator Engine configuration interface class.
00005 // Quick documentation in header file ``include/sidemu.h''.
00006 
00007 #include "eeconfig.h"
00008 #include "mixing.h"
00009 
00010 // ------------------------------------------------------------- constructors
00011 //static float filterTable[0x800]; TODO
00012 
00013 EXPORT_C emuEngine::emuEngine() //ALFRED
00014         :bufferScale(0)
00015         {
00016     CTOR(emuEngine);
00017  
00018         // Set the defaults.
00019         config.frequency = 22050;
00020         config.bitsPerSample = SIDEMU_8BIT;
00021         config.sampleFormat = SIDEMU_UNSIGNED_PCM;
00022         config.channels = SIDEMU_MONO;
00023         config.sidChips = 1;
00024         config.volumeControl = SIDEMU_NONE;
00025         config.mos8580 = false;
00026         config.measuredVolume = true;
00027         config.digiPlayerScans = 10*50;
00028         config.emulateFilter = true;
00029         config.autoPanning = SIDEMU_NONE;
00030         config.memoryMode = MPU_TRANSPARENT_ROM;
00031         config.clockSpeed = SIDTUNE_CLOCK_PAL;
00032         config.forceSongSpeed = false;
00033         
00034 #if defined(SIDEMU_TIME_COUNT)
00035         // Reset data counter.
00036         bytesCount = 0;
00037         secondsTotal = (secondsThisSong = 0);
00038 #endif
00039         
00040         isThreeVoiceTune = false;
00041 
00042         // create new MOS-6510 object
00043         iThe6510 = new C6510;
00044         
00045         // Allocate memory for the interpreter.
00046         MPUstatus = iThe6510->c64memAlloc();
00047 
00048         // create new sidEmu object
00049         iTheSidEmu = new sidEmu(this);
00050         iTheMixer  = new Mixer(this, iTheSidEmu);
00051 
00052         iTheSidEmu->sidEmuResetAutoPanning(config.autoPanning);
00053 
00054         // Allocate memory for the SID emulator engine.
00055         if ( MPUstatus && allocMem() )
00056                 {
00057                 setRandomSeed();
00058                 MPUreset();
00059                 configureSID();
00060                 initMixerEngine(); // OBS! This takes time... TODO optimize
00061                 setDefaultVoiceVolumes();
00062                 setDefaultFilterStrength(); // This takes also some time ~500 ms
00063                 reset();
00064                 isReady = true;
00065                 }
00066         else
00067                 {
00068                 isReady = false;
00069                 }
00070 }
00071 
00072 // -------------------------------------------------------------- destructors
00073 
00074 emuEngine::~emuEngine()
00075 {
00076     DTOR(emuEngine);
00077         freeMem();
00078 
00079         delete iTheMixer;
00080         delete iTheSidEmu;
00081         delete iThe6510;
00082 }
00083 
00084 // -------------------------------------------------- public member functions
00085 
00086 EXPORT_C bool emuEngine::setConfig( struct emuConfig& inCfg )
00093         {
00094         bool gotInvalidConfig = false;
00095         
00096         // Validate input value.
00097         if ((inCfg.memoryMode == MPU_BANK_SWITCHING)
00098                 || (inCfg.memoryMode == MPU_TRANSPARENT_ROM)
00099                 || (inCfg.memoryMode == MPU_PLAYSID_ENVIRONMENT))                       
00100         {
00101                 config.memoryMode = inCfg.memoryMode;
00102         }
00103         else
00104         {
00105                 gotInvalidConfig = true;  // invalid settings
00106         }
00107 
00108         // Validate input value.
00109         // Check various settings before doing a single SID-config call.
00110         bool newSIDconfig = false;
00111 
00112         if ((inCfg.clockSpeed == SIDTUNE_CLOCK_PAL)
00113                 || (inCfg.clockSpeed == SIDTUNE_CLOCK_NTSC))
00114         {
00115                 if (inCfg.clockSpeed != config.clockSpeed)
00116                 {
00117                         config.clockSpeed = inCfg.clockSpeed;
00118                         newSIDconfig = true;
00119                 }
00120         }
00121         else
00122         {
00123                 gotInvalidConfig = true;  // invalid settings
00124         }
00125 
00126         if (inCfg.forceSongSpeed != config.forceSongSpeed)
00127         {
00128                 config.forceSongSpeed = (inCfg.forceSongSpeed == true);
00129         }
00130 
00131         // Range-check the sample frequency.
00132         if (( inCfg.frequency >= 4000 ) && ( inCfg.frequency <= 48000 ))
00133         {       
00134                 // Has it changed ? Then do the necessary initialization.
00135                 if ( inCfg.frequency != config.frequency )
00136                 {
00137                         config.frequency = inCfg.frequency;
00138                         newSIDconfig = true;
00139                 }
00140         }
00141         else
00142         {
00143                 gotInvalidConfig = true;  // invalid settings
00144         }
00145 
00146         if (inCfg.measuredVolume != config.measuredVolume)
00147         {
00148                 config.measuredVolume = (inCfg.measuredVolume == true);
00149                 newSIDconfig = true;
00150         }
00151 
00152         // The mixer mode, the sample format, the number of channels and bits per
00153         // sample all affect the mixing tables and settings.
00154         // Hence we define a handy flag here.
00155         bool newMixerSettings = false;
00156 
00157         // Is the requested sample format valid ?
00158         if (( inCfg.sampleFormat == SIDEMU_UNSIGNED_PCM ) 
00159                 || ( inCfg.sampleFormat == SIDEMU_SIGNED_PCM ))
00160         {
00161                 // Has it changed ? Then do the necessary initialization.
00162                 if ( inCfg.sampleFormat != config.sampleFormat )
00163                 {
00164                         config.sampleFormat = inCfg.sampleFormat;
00165                         newMixerSettings = true;
00166                 }
00167         }
00168         else
00169         {
00170                 gotInvalidConfig = true;  // invalid settings
00171         }
00172         
00173         // Is the requested number of channels valid ?
00174         if (( inCfg.channels == SIDEMU_MONO ) 
00175                 || ( inCfg.channels == SIDEMU_STEREO ))
00176         {
00177                 // Has it changed ? Then do the necessary initialization.
00178                 if ( inCfg.channels != config.channels )
00179                 {
00180                         config.channels = inCfg.channels;
00181                         setDefaultVoiceVolumes();
00182                         newMixerSettings = true;
00183                 }
00184         }
00185         else
00186         {
00187                 gotInvalidConfig = true;  // invalid settings
00188         }
00189         
00190         // Is the requested sample precision valid ?
00191         if (( inCfg.bitsPerSample == SIDEMU_8BIT ) 
00192                 || ( inCfg.bitsPerSample == SIDEMU_16BIT ))
00193         {
00194                 // Has it changed ? Then do the necessary initialization.
00195                 if ( inCfg.bitsPerSample != config.bitsPerSample )
00196                 {
00197                         config.bitsPerSample = inCfg.bitsPerSample;
00198                         newMixerSettings = true;
00199                 }
00200         }
00201         else
00202         {
00203                 gotInvalidConfig = true;  // invalid settings
00204         }
00205         
00206         // Is the requested mixing mode valid ?
00207         if (( inCfg.volumeControl == SIDEMU_NONE ) 
00208                 || ( inCfg.volumeControl == SIDEMU_VOLCONTROL )
00209                 || ( inCfg.volumeControl == SIDEMU_FULLPANNING )
00210                 || ( inCfg.volumeControl == SIDEMU_HWMIXING )
00211                 || ( inCfg.volumeControl == SIDEMU_STEREOSURROUND ))
00212         {
00213                 // Has it changed ? Then do the necessary initialization.
00214                 if ( inCfg.volumeControl != config.volumeControl )
00215                 {
00216                         config.volumeControl = inCfg.volumeControl;
00217                         setDefaultVoiceVolumes();
00218                         newMixerSettings = true;
00219                 }
00220         }
00221         else
00222         {
00223                 gotInvalidConfig = true;  // invalid settings
00224         }
00225 
00226         if ((inCfg.autoPanning == SIDEMU_NONE)
00227                 || (inCfg.autoPanning == SIDEMU_CENTEREDAUTOPANNING))
00228         {
00229                 if (inCfg.autoPanning != config.autoPanning)
00230                 {
00231                         config.autoPanning = inCfg.autoPanning;
00232                         if (config.autoPanning != SIDEMU_NONE)
00233                         {
00234                                 if (( config.volumeControl != SIDEMU_FULLPANNING )
00235                                         && ( config.volumeControl != SIDEMU_STEREOSURROUND ))
00236                                 {
00237                                         config.autoPanning = false;
00238                                         gotInvalidConfig = true;  // wrong mixing mode
00239                                 }
00240                         }
00241 //                      extern void sidEmuResetAutoPanning(int); TODO
00242                         iTheSidEmu->sidEmuResetAutoPanning(config.autoPanning);
00243                 }
00244         }
00245         else
00246         {
00247                 gotInvalidConfig = true;  // invalid panning mode
00248         }
00249         
00250         if (inCfg.emulateFilter != config.emulateFilter)
00251         {
00252                 config.emulateFilter = (inCfg.emulateFilter == true);
00253                 newSIDconfig = true;      // filter
00254                 newMixerSettings = true;  // amplification
00255         }
00256         // Range-check the filter settings.
00257         if (( inCfg.filterFs >= 1.0 ) && ( inCfg.filterFm != 0 ))
00258         {
00259                 // Have they changed ? Then do the necessary initialization.
00260                 if ((inCfg.filterFs != config.filterFs) 
00261                         || (inCfg.filterFm != config.filterFm)
00262                         || (inCfg.filterFt != config.filterFt))
00263                 {
00264                         config.filterFs = inCfg.filterFs;
00265                         config.filterFm = inCfg.filterFm;
00266                         config.filterFt = inCfg.filterFt;
00267                         filterTableInit();
00268                 }
00269         }
00270         else
00271         {
00272                 gotInvalidConfig = true;  // invalid settings
00273         }
00274         
00275         if (inCfg.digiPlayerScans != config.digiPlayerScans)
00276         {
00277                 config.digiPlayerScans = (inCfg.digiPlayerScans == true);
00278                 newMixerSettings = true;  // extra amplification
00279         }
00280 
00281         if ((config.channels==SIDEMU_MONO) &&
00282                 ((config.volumeControl==SIDEMU_STEREOSURROUND)
00283                  ||(config.autoPanning!=SIDEMU_NONE)))
00284         {
00285                 gotInvalidConfig = true;  // invalid settings
00286         }
00287 
00288         if (inCfg.mos8580 != config.mos8580)
00289         {
00290                 config.mos8580 = (inCfg.mos8580 == true);
00291                 newSIDconfig = true;
00292         }
00293 
00294         // Here re-initialize the SID, if required.
00295         if (newSIDconfig)
00296         {
00297                 configureSID();
00298         }
00299         
00300         // Here re-initialize the mixer engine, if required.
00301         if (newMixerSettings)
00302         {
00303                 initMixerEngine();
00304         }
00305 
00306         // Return flag, whether input config was valid.
00307         return !gotInvalidConfig;
00308 }
00309 
00310 EXPORT_C void emuEngine::getConfig( struct emuConfig& outCfg )
00311 {
00312         outCfg = config;
00313 }
00314 
00315 void emuEngine::setDefaultFilterStrength()
00316 {
00317         config.filterFs = SIDEMU_DEFAULTFILTERFS;
00318         config.filterFm = SIDEMU_DEFAULTFILTERFM;
00319         config.filterFt = SIDEMU_DEFAULTFILTERFT;
00320         filterTableInit();
00321 }
00322 
00323 EXPORT_C bool emuEngine::verifyEndianess()
00324 {
00325         // Test endianess. Should swap bytes.
00326         ubyte endTest[2];
00327         writeLEword(endTest,0x55aa);
00328         if (0xaa55!=readBEword(endTest))
00329                 return false;
00330         else
00331                 return true;
00332 }
00333 
00334 EXPORT_C void emuEngine::FillBuffer(sidTune& thistune, void* buffer, udword bufferLen)
00335         {
00336         iTheSidEmu->sidEmuFillBuffer(*this, thistune, buffer, bufferLen);
00337         }
00338 
00339 
00340 #if defined(SIDEMU_TIME_COUNT)
00341 EXPORT_C int emuEngine::getSecondsThisSong()
00342 {
00343         return secondsThisSong;
00344 }
00345 
00346 EXPORT_C int emuEngine::getSecondsTotal()
00347 {
00348         return secondsTotal;
00349 }
00350 #endif
00351 
00352 // ------------------------------------------------- private member functions
00353 
00354 bool emuEngine::freeMem()
00355 {
00356         if ( ampMod1x8 != 0 )
00357                 delete[] ampMod1x8;
00358         ampMod1x8 = 0;
00359         if ( iTheMixer->signedPanMix8 != 0 )
00360                 delete[] iTheMixer->signedPanMix8;
00361         iTheMixer->signedPanMix8 = 0;
00362         if ( iTheMixer->signedPanMix16 != 0 )
00363                 delete[] iTheMixer->signedPanMix16;
00364         iTheMixer->signedPanMix16 = 0;
00365         return true;
00366 }
00367 
00368 bool emuEngine::allocMem()
00369 {
00370         // Keep track of memory allocation failures.
00371         bool wasSuccess = true;
00372         // Seems as if both tables are needed for panning-mixing with 16-bit samples.
00373         // 8-bit
00374         if (( ampMod1x8 = new sbyte[256*256] ) == 0 )  
00375                 wasSuccess = false;
00376         if (( iTheMixer->signedPanMix8 = new sbyte[256*256] ) == 0 )  
00377                 wasSuccess = false;
00378         // 16-bit
00379         if (( iTheMixer->signedPanMix16 = new sword[256*256] ) == 0 )  
00380                 wasSuccess = false;
00381 
00382         if (!wasSuccess)
00383         {
00384                 freeMem();
00385         }
00386         return wasSuccess;
00387 }
00388 
00389 void emuEngine::MPUreset()
00390 {
00391         if (MPUstatus)
00392         {
00393                 iThe6510->initInterpreter(config.memoryMode);
00394                 iThe6510->c64memClear();
00395                 iThe6510->c64memReset(config.clockSpeed,randomSeed);
00396         }
00397 }
00398 
00399 ubyte * emuEngine::MPUreturnRAMbase()
00400 {
00401         if (MPUstatus)
00402         {
00403                 return iThe6510->c64mem1;
00404         }
00405         else
00406         {
00407                 return 0;
00408         }
00409 }
00410 
00411 void emuEngine::setRandomSeed()
00412 {
00413         time_t now = time(NULL);
00414         randomSeed = (ubyte)now;
00415 }
00416 
00417 bool emuEngine::reset()
00418 {
00419         if (isReady)
00420         {
00421                 // Check internal mixer state whether tables have to be redone.
00422                 if (config.digiPlayerScans != 0)
00423                 {
00424                         if (isThreeVoiceAmplified != isThreeVoiceTune)  // needs diff.ampl.
00425                         {
00426                                 initMixerEngine();
00427                         }
00428                 }
00429                 else if (isThreeVoiceAmplified)  // and do not want amplification
00430                 {
00431                         initMixerEngine();
00432                 }
00433 //              extern bool sidEmuReset(); TODO - remove
00434                 iTheSidEmu->sidEmuReset();
00435                 
00436                 resetSampleEmu();
00437         }
00438         return isReady;
00439 }
00440 
00441 bool emuEngine::resetSampleEmu()
00442 {
00443         iTheSidEmu->iTheSampler->sampleEmuReset(iTheSidEmu);
00444         return true;
00445 }
00446 
00447 void emuEngine::amplifyThreeVoiceTunes(bool inIsThreeVoiceTune)
00448 {
00449         // ::initMixerEngine depends on this and config.digiPlayerScans.
00450         // Specify whether a sidtune uses only three voices (here: no digis).
00451         isThreeVoiceTune = inIsThreeVoiceTune;
00452 }
00453 
00454 // Initialize the SID chip and everything that depends on the frequency.
00455 void emuEngine::configureSID()
00456 {
00457         iTheSidEmu->sidEmuConfigure(config);
00458 }
00459 
00460 void emuEngine::initMixerEngine()
00461 {
00462         ELOG1(_L8("initMixerEngine\n"));
00463 
00464         uword uk;
00465 
00466         // If just three (instead of four) voices, do different amplification,
00467         // if that is desired (digiPlayerScans!=0).
00468         if ((config.digiPlayerScans!=0) && isThreeVoiceTune)
00469         {
00470                 isThreeVoiceAmplified = true;
00471         }
00472         else
00473         {
00474                 isThreeVoiceAmplified = false;
00475         }
00476 
00477 #if defined(SID_FPUMIXERINIT)
00478         sdword si, sj;
00479 
00480         // 8-bit volume modulation tables.
00481         float filterAmpl = 1.0;
00482         if (config.emulateFilter)
00483         {
00484                 filterAmpl = 0.7f;
00485         }
00486         uk = 0;
00487         for ( si = 0; si < 256; si++ )
00488         {
00489                 for ( sj = -128; sj < 128; sj++, uk++ )
00490                 {
00491                         ampMod1x8[uk] = (sbyte)(((si*sj)/255)*filterAmpl);
00492                 }
00493         }
00494 
00495         // Determine single-voice de-amplification.
00496         float ampDiv;  // logical voices per physical channel
00497         if ( config.volumeControl == SIDEMU_HWMIXING )
00498         {
00499                 ampDiv = 1.0;
00500         }
00501         else if ((config.channels==SIDEMU_STEREO) &&
00502                          ((config.volumeControl==SIDEMU_NONE)
00503                           ||(config.volumeControl==SIDEMU_VOLCONTROL)))
00504         {
00505                 ampDiv = 2.0;
00506         }
00507         else  // SIDEMU_MONO or SIDEMU_FULLPANNING or SIDEMU_STEREOSURROUND
00508         {
00509                 if (isThreeVoiceAmplified)
00510                 {
00511                         ampDiv = 3.0;
00512                 }
00513                 else
00514                 {
00515                         ampDiv = 4.0;
00516                 }
00517         }
00518 
00519         uk = 0;
00520         for ( si = 0; si < 256; si++ )
00521         {
00522                 for ( sj = -128; sj < 128; sj++, uk++ )
00523                 {
00524                         // 8-bit mixing modulation tables.
00525                         iTheMixer->signedPanMix8[uk] = (sbyte)(((si*sj)/255)/ampDiv);
00526                         // 16-bit mixing modulation tables.
00527 //                      signedPanMix16[uk] = (uword)((si*sj)/ampDiv);
00528                         iTheMixer->signedPanMix16[uk] = (sword)((si*sj)/ampDiv); //ALFRED - TODO: check this, possible bug
00529                 }
00530         }
00531 #else
00532         sdword si, sj;
00533 
00534         // 8-bit volume modulation tables.
00535         sword filterAmpl = 10;
00536         if (config.emulateFilter)
00537         {
00538                 filterAmpl = 7;
00539         }
00540         uk = 0;
00541         for ( si = 0; si < 256; si++ )
00542         {
00543                 for ( sj = -128; sj < 128; sj++, uk++ )
00544                 {
00545                         ampMod1x8[uk] = (sbyte)((si*sj*filterAmpl)/(255*10));
00546                 }
00547         }
00548 
00549         // Determine single-voice de-amplification.
00550         short ampDiv;  // logical voices per physical channel
00551         if ( config.volumeControl == SIDEMU_HWMIXING )
00552         {
00553                 ampDiv = 1;
00554         }
00555         else if ((config.channels==SIDEMU_STEREO) &&
00556                          ((config.volumeControl==SIDEMU_NONE)
00557                           ||(config.volumeControl==SIDEMU_VOLCONTROL)))
00558         {
00559                 ampDiv = 2;
00560         }
00561         else  // SIDEMU_MONO or SIDEMU_FULLPANNING or SIDEMU_STEREOSURROUND
00562         {
00563                 if (isThreeVoiceAmplified)
00564                 {
00565                         ampDiv = 3;
00566                 }
00567                 else
00568                 {
00569                         ampDiv = 4;
00570                 }
00571         }
00572 
00573         uk = 0;
00574         for ( si = 0; si < 256; si++ )
00575         {
00576                 for ( sj = -128; sj < 128; sj++, uk++ )
00577                 {
00578                         // 8-bit mixing modulation tables.
00579                         iTheMixer->signedPanMix8[uk] = (sbyte)((si*sj)/(255*ampDiv));
00580                         // 16-bit mixing modulation tables.
00581                         iTheMixer->signedPanMix16[uk] = (uword)((si*sj)/ampDiv);
00582                 }
00583         }
00584 #endif  
00585 
00586         // ------------------------------------------------- Init mixer function.
00587         
00588         typedef void* (Mixer::*ptr2fillfunc)(void*,udword);
00589         // Fill function lookup-table.
00590         // bits, mono/stereo, control
00591         const ptr2fillfunc fillfunctions[2][2][4] =
00592         {
00593                 {
00594                         {
00595                         &Mixer::fill8bitMono,
00596                           &Mixer::fill8bitsplit,
00597                           &Mixer::fill8bitMonoControl,
00598                           &Mixer::fill8bitMonoControl
00599                         },
00600                         {
00601                         &Mixer::fill8bitStereo,
00602                           &Mixer::fill8bitsplit,
00603                           &Mixer::fill8bitStereoControl,
00604                           &Mixer::fill8bitStereoSurround
00605                         },
00606                 },
00607                 {
00608                         {
00609                         &Mixer::fill16bitMono,
00610                           &Mixer::fill16bitsplit,
00611                           &Mixer::fill16bitMonoControl,
00612                           &Mixer::fill16bitMonoControl
00613                         },
00614                         {
00615                         &Mixer::fill16bitStereo,
00616                           &Mixer::fill16bitsplit,
00617                           &Mixer::fill16bitStereoControl,
00618                           &Mixer::fill16bitStereoSurround
00619                         },
00620                 }
00621         };
00622 
00623         int bitsIndex, monoIndex, controlIndex;
00624 
00625         // Define the ``zero'' sample for signed or unsigned samples.
00626         ubyte zero8bit = 0x80;
00627         uword zero16bit = 0;
00628         
00629         if ( config.bitsPerSample == SIDEMU_16BIT )
00630         {
00631                 bitsIndex = 1;
00632                 switch( config.sampleFormat )
00633                 {
00634                         // waveform and amplification tables are signed samples, 
00635                         // so adjusting the sign should do the conversion 
00636                  case SIDEMU_SIGNED_PCM:
00637                         {
00638                                 zero16bit = 0;
00639                                 break;
00640                         }
00641                  case SIDEMU_UNSIGNED_PCM:
00642                  default:
00643                         {
00644                                 zero16bit = 0x8000;
00645                                 break;
00646                         }
00647                 }
00648         }
00649         else  // if ( config.bitsPerSample == SIDEMU_8BIT )
00650         {
00651                 bitsIndex = 0;
00652                 switch( config.sampleFormat )
00653                 {
00654                         // waveform and amplification tables are signed samples, 
00655                         // so adjusting the sign should do the conversion 
00656                  case SIDEMU_SIGNED_PCM:
00657                         {
00658                                 zero8bit = 0;
00659                                 break;
00660                         }
00661                  case SIDEMU_UNSIGNED_PCM:
00662                  default:
00663                         {
00664                                 zero8bit = 0x80;
00665                                 break;
00666                         }
00667                 }
00668         } // end else config.bitsPerSample
00669         
00670         switch( config.channels )
00671         {
00672          case SIDEMU_MONO:
00673                 {
00674                         monoIndex = 0;
00675                         break;
00676                 }
00677          case SIDEMU_STEREO:
00678          default:
00679                 {
00680                         monoIndex = 1;
00681                         break;
00682                 }
00683         }
00684         
00685         if ( config.volumeControl == SIDEMU_NONE )
00686                 controlIndex = 0;
00687         else if ( config.volumeControl == SIDEMU_HWMIXING )
00688                 controlIndex = 1;
00689         else if ( config.volumeControl == SIDEMU_STEREOSURROUND )
00690                 controlIndex = 3;
00691         else
00692                 controlIndex = 2;
00693 
00694         iTheMixer->sidEmuFillFunc = fillfunctions[bitsIndex][monoIndex][controlIndex];
00695 
00696         // Call a function which inits more local tables.
00697         iTheMixer->MixerInit(isThreeVoiceAmplified,zero8bit,zero16bit);
00698         
00699         // ----------------------------------------------------------------------
00700         
00701         // ensure that samplebuffer will be divided into
00702         // correct number of samples
00703         //  8-bit mono: buflen x = x samples
00704         //      stereo:          = x/2 samples
00705         // 16-bit mono: buflen x = x/2 samples
00706         //      stereo:          = x/4 samples
00707         bufferScale = 0;
00708         // HWMIXING mode does not know about stereo.
00709         if ((config.channels == SIDEMU_STEREO)
00710                 && !(config.volumeControl == SIDEMU_HWMIXING))
00711                 bufferScale++;
00712         if ( config.bitsPerSample == SIDEMU_16BIT )  
00713                 bufferScale++;
00714 }
00715 
00716 
00717 void emuEngine::setDefaultVoiceVolumes()
00718 { 
00719         // Adjust default mixing gain. Does not matter, whether this will be used.
00720         // Signed 8-bit samples will be added to base array index. 
00721         // So middle must be 0x80.
00722         // [-80,-81,...,-FE,-FF,0,1,...,7E,7F]
00723         // Mono: left channel only used.
00724         if ( config.channels == SIDEMU_MONO )
00725         {
00726                 setVoiceVolume(1,255,0,256);
00727                 setVoiceVolume(2,255,0,256);
00728                 setVoiceVolume(3,255,0,256);
00729                 setVoiceVolume(4,255,0,256);
00730         }
00731         // Stereo:
00732         else
00733         { // if ( config.channels == SIDEMU_STEREO )
00734                 if ( config.volumeControl == SIDEMU_STEREOSURROUND )
00735                 {
00736                         setVoiceVolume(1,255,255,256);
00737                         setVoiceVolume(2,255,255,256);
00738                         setVoiceVolume(3,255,255,256);
00739                         setVoiceVolume(4,255,255,256);
00740                 }
00741                 else
00742                 {
00743                         setVoiceVolume(1,255,0,256);
00744                         setVoiceVolume(2,0,255,256);
00745                         setVoiceVolume(3,255,0,256);
00746                         setVoiceVolume(4,0,255,256);
00747                 }
00748         }
00749 }
00750 
00751 
00752 void emuEngine::filterTableInit()
00753 {
00754         uword uk;
00755         // Parameter calculation has not been moved to a separate function
00756         // by purpose.
00757         
00758         float* filterTable = iTheSidEmu->filterTable;
00759 
00760         float yMax = 1.0;
00761         float yMin = (float)0.01;
00762         uk = 0;
00763         for ( float rk = 0; rk < 0x800; rk++ )
00764         {
00765                 filterTable[uk] = (float)(( exp( rk/2048*log(config.filterFs) ) / config.filterFm ) + config.filterFt);
00766                 if ( filterTable[uk] < yMin )
00767                         filterTable[uk] = yMin;
00768                 if ( filterTable[uk] > yMax )
00769                         filterTable[uk] = yMax;
00770                 uk++;
00771         }
00772 
00773         float* bandPassParam = iTheSidEmu->bandPassParam;
00774 
00775         yMax = (float)0.22;
00776         yMin = (float)0.002;
00777         float yAdd = (float)((yMax-yMin)/2048.0);
00778         float yTmp = yMin;
00779         uk = 0;
00780         for ( float rk2 = 0; rk2 < 0x800; rk2++ ) // use rk2 instead of rk due to MS compiler bug
00781         {
00782                 bandPassParam[uk] = yTmp;
00783                 yTmp += yAdd;
00784                 uk++;
00785         }
00786         
00787         float* filterResTable = iTheSidEmu->filterResTable;
00788 
00789         float resDyMax = 1.0;
00790         float resDyMin = 2.0;
00791         float resDy = resDyMin;
00792         for ( uk = 0; uk < 16; uk++ )
00793         {
00794                 filterResTable[uk] = resDy;
00795                 resDy -= (( resDyMin - resDyMax ) / 15 );
00796         }
00797         filterResTable[0] = resDyMin;
00798         filterResTable[15] = resDyMax;
00799 }
00800 
00801 bool emuEngine::setVoiceVolume(int voice, ubyte leftLevel, ubyte rightLevel, uword total)
00802 {
00803         if ( config.volumeControl == SIDEMU_NONE )
00804                 return false;
00805         if ((voice < 1) || (voice > 4) || (total > 256))
00806                 return false;
00807         if ( config.channels == SIDEMU_MONO )
00808                 rightLevel = 0;
00809 //      extern void sidEmuSetVoiceVolume(int v,uword L,uword R,uword T);
00810         iTheSidEmu->sidEmuSetVoiceVolume(voice,leftLevel,rightLevel,total);
00811         return true;
00812 }
00813 
00814 uword emuEngine::getVoiceVolume(int voice)
00815 {
00816 //      extern uword sidEmuReturnVoiceVolume(int);
00817         if (( voice < 1 ) || ( voice > 4 ))
00818                 return false;
00819         else
00820                 return iTheSidEmu->sidEmuReturnVoiceVolume(voice);
00821 }

Generated on Tue Feb 8 04:13:57 2005 for Esidplay by doxygen 1.3.3