bool Sound_Init(MDFNGI *gi) { SexyAL_DriverInfo CurDriver; NeedReInit = false; SoundRate = 0; memset(&format, 0, sizeof(format)); memset(&buffering, 0, sizeof(buffering)); Interface = new SexyAL(); format.sampformat = SEXYAL_FMT_PCMS16; assert(gi->soundchan); format.channels = gi->soundchan; format.revbyteorder = 0; format.noninterleaved = false; format.rate = gi->soundrate ? gi->soundrate : MDFN_GetSettingUI("sound.rate"); buffering.ms = MDFN_GetSettingUI("sound.buffer_time"); if(!buffering.ms) { buffering.overhead_kludge = true; buffering.ms = 7 + floor(0.5 + 1.5 * 1000.0 / gi->fps * (256 * 65536)); } else buffering.overhead_kludge = false; buffering.period_us = MDFN_GetSettingUI("sound.period_time"); std::string zedevice = MDFN_GetSettingS("sound.device"); std::string zedriver = MDFN_GetSettingS("sound.driver"); MDFNI_printf(_("\nInitializing sound...\n")); MDFN_indent(1); if(!Interface->FindDriver(&CurDriver, zedriver.c_str())) { std::vector<SexyAL_DriverInfo> DriverTypes = Interface->GetDriverList(); MDFN_printf(_("\nUnknown sound driver \"%s\". Compiled-in sound drivers:\n"), zedriver.c_str()); MDFN_indent(2); for(unsigned x = 0; x < DriverTypes.size(); x++) { MDFN_printf("%s\n", DriverTypes[x].short_name); } MDFN_indent(-2); MDFN_printf("\n"); delete Interface; Interface = NULL; MDFN_indent(-1); return(FALSE); } if(!strcasecmp(zedevice.c_str(), "default")) MDFNI_printf(_("Using \"%s\" audio driver with SexyAL's default device selection."), CurDriver.name); else MDFNI_printf(_("Using \"%s\" audio driver with device \"%s\":"), CurDriver.name, zedevice.c_str()); MDFN_indent(1); //RunSexyALTest(Interface, &buffering, zedevice.c_str(), CurDriver.type); //exit(1); if(!(Output=Interface->Open(zedevice.c_str(), &format, &buffering, CurDriver.type))) { MDFND_PrintError(_("Error opening a sound device.")); delete Interface; Interface = NULL; MDFN_indent(-2); return(FALSE); } if(format.rate < 22050 || format.rate > 192000) { MDFND_PrintError(_("Set rate is out of range [22050-192000]")); Sound_Kill(); MDFN_indent(-2); return(FALSE); } MDFNI_printf(_("\nBits: %u%s\nRate: %u\nChannels: %u%s\nByte order: CPU %s\nBuffer size: %u sample frames(%f ms)\n"), (format.sampformat>>4)*8, (format.sampformat == SEXYAL_FMT_PCMFLOAT) ? _(" (floating-point)") : "",format.rate,format.channels,format.noninterleaved ? _(" (non-interleaved) ") : "", format.revbyteorder?"Reversed":"Native", buffering.buffer_size, (double)buffering.buffer_size * 1000 / format.rate); MDFNI_printf(_("Latency: %u sample frames(%f ms)\n"), buffering.latency, (double)buffering.latency * 1000 / format.rate); if(buffering.period_size) { //int64_t pt_test_result = ((int64_t)buffering.period_size * (1000 * 1000) / format.rate); int64_t bt_test_result = ((int64_t)(buffering.bt_gran ? buffering.bt_gran : buffering.period_size) * (1000 * 1000) / format.rate); MDFNI_printf(_("Period size: %u sample frames(%f ms)\n"), buffering.period_size, (double)buffering.period_size * 1000 / format.rate); if(bt_test_result > 5333) { MDFN_indent(1); if(!buffering.bt_gran) MDFN_printf(_("Warning: Period time is too large(it should be <= ~5.333ms). Video will appear very jerky.\n")); else MDFN_printf(_("Warning: Buffer update timing granularity is too large(%f; it should be <= ~5.333ms). Video will appear very jerky.\n"), (double)buffering.bt_gran * 1000 / format.rate); MDFN_indent(-1); } } format.sampformat = SEXYAL_FMT_PCMS16; format.channels = gi->soundchan?gi->soundchan:1; format.revbyteorder = 0; format.noninterleaved = false; //format.rate=gi->soundrate?gi->soundrate:soundrate; Output->SetConvert(Output, &format); EmuModBufferSize = (500 * format.rate + 999) / 1000; EmuModBuffer = (int16 *)calloc(sizeof(int16) * format.channels, EmuModBufferSize); SoundRate = format.rate; MDFN_indent(-2); return(1); }
bool MDFNI_InitializeModules(const std::vector<MDFNGI *> &ExternalSystems) { static MDFNGI *InternalSystems[] = { #ifdef WANT_NES_EMU &EmulatedNES, #endif #ifdef WANT_SNES_EMU &EmulatedSNES, #endif #ifdef WANT_GB_EMU &EmulatedGB, #endif #ifdef WANT_GBA_EMU &EmulatedGBA, #endif #ifdef WANT_PCE_EMU &EmulatedPCE, #endif #ifdef WANT_PCE_FAST_EMU &EmulatedPCE_Fast, #endif #ifdef WANT_LYNX_EMU &EmulatedLynx, #endif #ifdef WANT_MD_EMU &EmulatedMD, #endif #ifdef WANT_PCFX_EMU &EmulatedPCFX, #endif #ifdef WANT_NGP_EMU &EmulatedNGP, #endif #ifdef WANT_PSX_EMU &EmulatedPSX, #endif #ifdef WANT_VB_EMU &EmulatedVB, #endif #ifdef WANT_WSWAN_EMU &EmulatedWSwan, #endif #ifdef WANT_SMS_EMU &EmulatedSMS, &EmulatedGG, #endif &EmulatedCDPlay }; std::string i_modules_string, e_modules_string; for(unsigned int i = 0; i < sizeof(InternalSystems) / sizeof(MDFNGI *); i++) { AddSystem(InternalSystems[i]); if(i) i_modules_string += " "; i_modules_string += std::string(InternalSystems[i]->shortname); } for(unsigned int i = 0; i < ExternalSystems.size(); i++) { AddSystem(ExternalSystems[i]); if(i) i_modules_string += " "; e_modules_string += std::string(ExternalSystems[i]->shortname); } MDFNI_printf(_("Internal emulation modules: %s\n"), i_modules_string.c_str()); MDFNI_printf(_("External emulation modules: %s\n"), e_modules_string.c_str()); for(unsigned int i = 0; i < MDFNSystems.size(); i++) MDFNSystemsPrio.push_back(MDFNSystems[i]); MDFNSystemsPrio.sort(MDFNSystemsPrio_CompareFunc); #if 0 std::string a_modules; std::list<MDFNGI *>: iterator it; for(it = MDFNSystemsPrio. f #endif CDUtility::CDUtility_Init(); return(1); } int MDFNI_Initialize(const char *basedir, const std::vector<MDFNSetting> &DriverSettings) { // FIXME static static std::vector<MDFNSetting> dynamic_settings; if(!MDFN_RunMathTests()) { return(0); } memset(PortDataCache, 0, sizeof(PortDataCache)); memset(PortDataLenCache, 0, sizeof(PortDataLenCache)); memset(PortDeviceCache, 0, sizeof(PortDeviceCache)); lzo_init(); MDFNI_SetBaseDirectory(basedir); MDFN_InitFontData(); // Generate dynamic settings for(unsigned int i = 0; i < MDFNSystems.size(); i++) { MDFNSetting setting; const char *sysname; sysname = (const char *)MDFNSystems[i]->shortname; if(!MDFNSystems[i]->soundchan) printf("0 sound channels for %s????\n", sysname); if(MDFNSystems[i]->soundchan == 2) { BuildDynamicSetting(&setting, sysname, "forcemono", MDFNSF_COMMON_TEMPLATE | MDFNSF_CAT_SOUND, CSD_forcemono, MDFNST_BOOL, "0"); dynamic_settings.push_back(setting); } BuildDynamicSetting(&setting, sysname, "enable", MDFNSF_COMMON_TEMPLATE, CSD_enable, MDFNST_BOOL, "1"); dynamic_settings.push_back(setting); BuildDynamicSetting(&setting, sysname, "tblur", MDFNSF_COMMON_TEMPLATE | MDFNSF_CAT_VIDEO, CSD_tblur, MDFNST_BOOL, "0"); dynamic_settings.push_back(setting); BuildDynamicSetting(&setting, sysname, "tblur.accum", MDFNSF_COMMON_TEMPLATE | MDFNSF_CAT_VIDEO, CSD_tblur_accum, MDFNST_BOOL, "0"); dynamic_settings.push_back(setting); BuildDynamicSetting(&setting, sysname, "tblur.accum.amount", MDFNSF_COMMON_TEMPLATE | MDFNSF_CAT_VIDEO, CSD_tblur_accum_amount, MDFNST_FLOAT, "50", "0", "100"); dynamic_settings.push_back(setting); } if(DriverSettings.size()) MDFN_MergeSettings(DriverSettings); // First merge all settable settings, then load the settings from the SETTINGS FILE OF DOOOOM MDFN_MergeSettings(MednafenSettings); MDFN_MergeSettings(dynamic_settings); MDFN_MergeSettings(MDFNMP_Settings); for(unsigned int x = 0; x < MDFNSystems.size(); x++) { if(MDFNSystems[x]->Settings) MDFN_MergeSettings(MDFNSystems[x]->Settings); } MDFN_MergeSettings(RenamedSettings); if(!MFDN_LoadSettings(basedir)) return(0); #ifdef WANT_DEBUGGER MDFNDBG_Init(); #endif return(1); } void MDFNI_Kill(void) { MDFN_SaveSettings(); } static double multiplier_save, volume_save; static std::vector<int16> SoundBufPristine; static void ProcessAudio(EmulateSpecStruct *espec) { if(espec->SoundVolume != 1) volume_save = espec->SoundVolume; if(espec->soundmultiplier != 1) multiplier_save = espec->soundmultiplier; if(espec->SoundBuf && espec->SoundBufSize) { int16 *const SoundBuf = espec->SoundBuf + espec->SoundBufSizeALMS * MDFNGameInfo->soundchan; int32 SoundBufSize = espec->SoundBufSize - espec->SoundBufSizeALMS; const int32 SoundBufMaxSize = espec->SoundBufMaxSize - espec->SoundBufSizeALMS; if(qtrecorder && (volume_save != 1 || multiplier_save != 1)) { int32 orig_size = SoundBufPristine.size(); SoundBufPristine.resize(orig_size + SoundBufSize * MDFNGameInfo->soundchan); for(int i = 0; i < SoundBufSize * MDFNGameInfo->soundchan; i++) SoundBufPristine[orig_size + i] = SoundBuf[i]; } if(espec->NeedSoundReverse) { int16 *yaybuf = SoundBuf; int32 slen = SoundBufSize; if(MDFNGameInfo->soundchan == 1) { for(int x = 0; x < (slen / 2); x++) { int16 cha = yaybuf[slen - x - 1]; yaybuf[slen - x - 1] = yaybuf[x]; yaybuf[x] = cha; } } else if(MDFNGameInfo->soundchan == 2) { for(int x = 0; x < (slen * 2) / 2; x++) { int16 cha = yaybuf[slen * 2 - (x&~1) - ((x&1) ^ 1) - 1]; yaybuf[slen * 2 - (x&~1) - ((x&1) ^ 1) - 1] = yaybuf[x]; yaybuf[x] = cha; } } } try { if(wavrecorder) wavrecorder->WriteSound(SoundBuf, SoundBufSize); } catch(std::exception &e) { MDFND_PrintError(e.what()); delete wavrecorder; wavrecorder = NULL; } if(multiplier_save != LastSoundMultiplier) { ff_resampler.time_ratio(multiplier_save, 0.9965); LastSoundMultiplier = multiplier_save; } if(multiplier_save != 1) { if(FFDiscard) { if(SoundBufSize >= multiplier_save) SoundBufSize /= multiplier_save; } else { if(MDFNGameInfo->soundchan == 2) { assert(ff_resampler.max_write() >= SoundBufSize * 2); for(int i = 0; i < SoundBufSize * 2; i++) ff_resampler.buffer()[i] = SoundBuf[i]; } else { assert(ff_resampler.max_write() >= SoundBufSize * 2); for(int i = 0; i < SoundBufSize; i++) { ff_resampler.buffer()[i * 2] = SoundBuf[i]; ff_resampler.buffer()[i * 2 + 1] = 0; } } ff_resampler.write(SoundBufSize * 2); int avail = ff_resampler.avail(); int real_read = std::min((int)(SoundBufMaxSize * MDFNGameInfo->soundchan), avail); if(MDFNGameInfo->soundchan == 2) SoundBufSize = ff_resampler.read(SoundBuf, real_read ) >> 1; else SoundBufSize = ff_resampler.read_mono_hack(SoundBuf, real_read ); avail -= real_read; if(avail > 0) { printf("ff_resampler.avail() > espec->SoundBufMaxSize * MDFNGameInfo->soundchan - %d\n", avail); ff_resampler.clear(); } } } if(volume_save != 1) { if(volume_save < 1) { int volume = (int)(16384 * volume_save); for(int i = 0; i < SoundBufSize * MDFNGameInfo->soundchan; i++) SoundBuf[i] = (SoundBuf[i] * volume) >> 14; } else {
bool MDFNI_InitializeModules(const std::vector<MDFNGI *> &ExternalSystems) { static MDFNGI *InternalSystems[] = { #ifdef WANT_NES_EMU &EmulatedNES, #endif #ifdef WANT_SNES_EMU &EmulatedSNES, #endif #ifdef WANT_SNES_PERF_EMU &EmulatedSNES_Perf, #endif #ifdef WANT_GB_EMU &EmulatedGB, #endif #ifdef WANT_GBA_EMU &EmulatedGBA, #endif #ifdef WANT_PC_EMU &EmulatedPC, #endif #ifdef WANT_PCE_EMU &EmulatedPCE, #endif #ifdef WANT_PCE_FAST_EMU &EmulatedPCE_Fast, #endif #ifdef WANT_LYNX_EMU &EmulatedLynx, #endif #ifdef WANT_MD_EMU &EmulatedMD, #endif #ifdef WANT_PCFX_EMU &EmulatedPCFX, #endif #ifdef WANT_NGP_EMU &EmulatedNGP, #endif #ifdef WANT_PSX_EMU &EmulatedPSX, #endif #ifdef WANT_VB_EMU &EmulatedVB, #endif #ifdef WANT_WSWAN_EMU &EmulatedWSwan, #endif #ifdef WANT_SMS_EMU &EmulatedSMS, &EmulatedGG, #endif &EmulatedCDPlay }; std::string i_modules_string, e_modules_string; assert(MEDNAFEN_VERSION_NUMERIC >= 0x0927); for(unsigned int i = 0; i < sizeof(InternalSystems) / sizeof(MDFNGI *); i++) { AddSystem(InternalSystems[i]); if(i) i_modules_string += " "; i_modules_string += std::string(InternalSystems[i]->shortname); } for(unsigned int i = 0; i < ExternalSystems.size(); i++) { AddSystem(ExternalSystems[i]); if(i) i_modules_string += " "; e_modules_string += std::string(ExternalSystems[i]->shortname); } MDFNI_printf(_("Internal emulation modules: %s\n"), i_modules_string.c_str()); MDFNI_printf(_("External emulation modules: %s\n"), e_modules_string.c_str()); for(unsigned int i = 0; i < MDFNSystems.size(); i++) MDFNSystemsPrio.push_back(MDFNSystems[i]); MDFNSystemsPrio.sort(MDFNSystemsPrio_CompareFunc); CDUtility::CDUtility_Init(); return(1); }
bool NSFLoad(const char *name, MDFNFILE *fp, NESGameType *gt) { char magic[5]; int x; if(!(NSFInfo = (NSFINFO *)MDFN_malloc(sizeof(NSFINFO), _("NSF header")))) { return(0); } memset(NSFInfo, 0, sizeof(NSFINFO)); fp->rewind(); fp->fread(magic, 1, 5); if(!memcmp(magic, "NESM\x1a", 5)) { if(!LoadNSF(fp)) { FreeNSF(); return(0); } } else if(!memcmp(magic, "NSFE", 4)) { if(!LoadNSFE(NSFInfo, fp->data, fp->Size(), 0)) { FreeNSF(); return(0); } } else { FreeNSF(); return(FALSE); } if(NSFInfo->LoadAddr < 0x6000) { MDFNI_printf(_("Load address is invalid!")); FreeNSF(); return(0); } if(NSFInfo->TotalSongs < 1) { MDFNI_printf(_("Total number of songs is less than 1!")); FreeNSF(); return(0); } BSon = 0; for(x=0;x<8;x++) BSon |= NSFInfo->BankSwitch[x]; MDFNGameInfo->GameType = GMT_PLAYER; if(NSFInfo->GameName) MDFNGameInfo->name = (UTF8*)strdup((char*)NSFInfo->GameName); for(x=0;;x++) { if(NSFROM[x]==0x20) { NSFROM[x+1]=NSFInfo->InitAddr&0xFF; NSFROM[x+2]=NSFInfo->InitAddr>>8; NSFROM[x+8]=NSFInfo->PlayAddr&0xFF; NSFROM[x+9]=NSFInfo->PlayAddr>>8; break; } }
bool InitSound(MDFNGI *gi) { SoundRate = 0; memset(&format,0,sizeof(format)); memset(&buffering,0,sizeof(buffering)); Interface = (SexyAL *)SexyAL_Init(0); DriverTypes = Interface->EnumerateTypes(Interface); format.sampformat = SEXYAL_FMT_PCMS16; assert(gi->soundchan); format.channels = gi->soundchan; format.revbyteorder = 0; format.rate = gi->soundrate ? gi->soundrate : MDFN_GetSettingUI("sound.rate"); buffering.ms = MDFN_GetSettingUI("sound.buffer_time"); buffering.period_us = MDFN_GetSettingUI("sound.period_time"); std::string zedevice = MDFN_GetSettingS("sound.device"); std::string zedriver = MDFN_GetSettingS("sound.driver"); CurDriverIndex = -1; if(!strcasecmp(zedriver.c_str(), "default")) CurDriverIndex = 0; else { for(int x = 0; DriverTypes[x].short_name; x++) { if(!strcasecmp(zedriver.c_str(), DriverTypes[x].short_name)) { CurDriverIndex = x; break; } } } MDFNI_printf(_("\nInitializing sound...\n")); MDFN_indent(1); if(CurDriverIndex == -1) { MDFN_printf(_("\nUnknown sound driver \"%s\". Supported sound drivers:\n"), zedriver.c_str()); MDFN_indent(2); for(int x = 0; DriverTypes[x].short_name; x++) { MDFN_printf("%s\n", DriverTypes[x].short_name); } MDFN_indent(-2); MDFN_printf("\n"); Interface->Destroy(Interface); Interface = NULL; MDFN_indent(-1); return(FALSE); } MDFNI_printf(_("Using \"%s\" audio driver with device \"%s\":"),DriverTypes[CurDriverIndex].name, zedevice.c_str()); MDFN_indent(1); //RunSexyALTest(Interface, &buffering, zedevice.c_str(), DriverTypes[CurDriverIndex].type); //exit(1); if(!(Output=Interface->Open(Interface, zedevice.c_str(), &format, &buffering, DriverTypes[CurDriverIndex].type))) { MDFND_PrintError(_("Error opening a sound device.")); Interface->Destroy(Interface); Interface=0; MDFN_indent(-2); return(FALSE); } if(format.rate<8192 || format.rate > 48000) { MDFND_PrintError(_("Set rate is out of range [8192-48000]")); KillSound(); MDFN_indent(-2); return(FALSE); } MDFNI_printf(_("\nBits: %u\nRate: %u\nChannels: %u\nByte order: CPU %s\nBuffer size: %u sample frames(%f ms)\n"), (format.sampformat>>4)*8,format.rate,format.channels,format.revbyteorder?"Reversed":"Native", buffering.buffer_size, (double)buffering.buffer_size * 1000 / format.rate); MDFNI_printf(_("Latency: %u sample frames(%f ms)\n"), buffering.latency, (double)buffering.latency * 1000 / format.rate); if(buffering.period_size) { int64_t pt_test_result = ((int64_t)buffering.period_size * (1000 * 1000) / format.rate); MDFNI_printf(_("Period size: %u sample frames(%f ms)\n"), buffering.period_size, (double)buffering.period_size * 1000 / format.rate); if(pt_test_result > 5333) { MDFN_indent(1); MDFN_printf(_("Warning: Period time is too large(it should be <= ~5.333ms). Video will appear very jerky.\n")); MDFN_indent(-1); } } format.sampformat=SEXYAL_FMT_PCMS16; format.channels=gi->soundchan?gi->soundchan:1; format.revbyteorder=0; //format.rate=gi->soundrate?gi->soundrate:soundrate; Output->SetConvert(Output, &format); EmuModBufferSize = (500 * format.rate + 999) / 1000; EmuModBuffer = (int16 *)calloc(sizeof(int16) * format.channels, EmuModBufferSize); SoundRate = format.rate; MDFN_indent(-2); return(1); }