From 9805fe3de4d305c11cb7ad332429be25faa0355c Mon Sep 17 00:00:00 2001 From: zeromus Date: Sun, 17 Mar 2019 22:55:53 -0400 Subject: [PATCH] winport - support multiple mic samples, selected with new hotkeys --- desmume/src/NDSSystem.cpp | 2 + desmume/src/NDSSystem.h | 4 +- desmume/src/frontend/windows/hotkey.cpp | 41 +++++- desmume/src/frontend/windows/hotkey.h | 4 +- desmume/src/frontend/windows/main.cpp | 10 +- desmume/src/frontend/windows/mic-win.cpp | 165 +++++++++++++++------- desmume/src/frontend/windows/resources.rc | 2 +- desmume/src/mic.h | 4 +- 8 files changed, 169 insertions(+), 63 deletions(-) diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index dd207e040..b8cf6e52e 100755 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -99,6 +99,8 @@ int lagframecounter; int LagFrameFlag; int lastLag; int TotalLagFrames; +u8 MicSampleSelection = 0; + TSCalInfo TSCal; diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index 7041f3b10..6b89eea88 100755 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -1,6 +1,6 @@ /* Copyright (C) 2006 yopyop - Copyright (C) 2008-2017 DeSmuME team + Copyright (C) 2008-2019 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -416,6 +416,7 @@ struct UserTouch struct UserMicrophone { u32 micButtonPressed; + u8 micSample; }; struct UserInput { @@ -683,6 +684,7 @@ void NDS_RunAdvansceneAutoImport(); extern std::string InputDisplayString; extern int LagFrameFlag; extern int lastLag, TotalLagFrames; +extern u8 MicSampleSelection; void MovieSRAM(); diff --git a/desmume/src/frontend/windows/hotkey.cpp b/desmume/src/frontend/windows/hotkey.cpp index e40914281..4bdab10ef 100644 --- a/desmume/src/frontend/windows/hotkey.cpp +++ b/desmume/src/frontend/windows/hotkey.cpp @@ -3,7 +3,7 @@ licensed under the terms supplied at the end of this file (for the terms are very long!) Differences from that baseline version are: - Copyright (C) 2009-2017 DeSmuME team + Copyright (C) 2009-2019 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -339,6 +339,21 @@ void HK_StateQuickLoadSlot(int, bool justPressed) void HK_MicrophoneKeyDown(int, bool justPressed) { NDS_setMic(1); } void HK_MicrophoneKeyUp(int) { NDS_setMic(0); } +void Mic_NextSample(); +void Mic_PrevSample(); + +void HK_NextSampleKeyDown(int, bool justPressed) +{ + Mic_NextSample(); + driver->AddLine("Mic sample %d selected", MicSampleSelection); +} + +void HK_PrevSampleKeyDown(int, bool justPressed) +{ + Mic_PrevSample(); + driver->AddLine("Mic sample %d selected", MicSampleSelection); +} + void HK_AutoHoldKeyDown(int, bool justPressed) {AutoHoldPressed = true;} void HK_AutoHoldKeyUp(int) {AutoHoldPressed = false;} @@ -702,6 +717,18 @@ void InitCustomKeys (SCustomKeys *keys) keys->Microphone.page = HOTKEY_PAGE_MAIN; keys->Microphone.key = NULL; + keys->PrevSample.handleKeyDown = HK_PrevSampleKeyDown; + keys->PrevSample.code = "Mic Prev Sample"; + keys->PrevSample.name = L"Mic Prev Sample"; + keys->PrevSample.page = HOTKEY_PAGE_MAIN; + keys->PrevSample.key = NULL; + + keys->NextSample.handleKeyDown = HK_NextSampleKeyDown; + keys->NextSample.code = "Mic Next Sample"; + keys->NextSample.name = L"Mic Next Sample"; + keys->NextSample.page = HOTKEY_PAGE_MAIN; + keys->NextSample.key = NULL; + keys->AutoHold.handleKeyDown = HK_AutoHoldKeyDown; keys->AutoHold.handleKeyUp = HK_AutoHoldKeyUp; keys->AutoHold.code = "AutoHold"; @@ -715,11 +742,7 @@ void InitCustomKeys (SCustomKeys *keys) keys->AutoHoldClear.page = HOTKEY_PAGE_MAIN; keys->AutoHoldClear.key = NULL; - keys->ToggleRasterizer.handleKeyDown = HK_ToggleRasterizer; - keys->ToggleRasterizer.code = "ToggleRasterizer"; - keys->ToggleRasterizer.name = STRW(ID_LABEL_HK12); - keys->ToggleRasterizer.page = HOTKEY_PAGE_MAIN; - keys->ToggleRasterizer.key = VK_SUBTRACT; + //Tools Page ---------------------------------------------------------- keys->PrintScreen.handleKeyDown = HK_PrintScreen; @@ -1059,6 +1082,12 @@ void InitCustomKeys (SCustomKeys *keys) keys->ToggleSubOBJLayer.page = HOTKEY_PAGE_OTHER; keys->ToggleSubOBJLayer.key = NULL; + keys->ToggleRasterizer.handleKeyDown = HK_ToggleRasterizer; + keys->ToggleRasterizer.code = "ToggleRasterizer"; + keys->ToggleRasterizer.name = STRW(ID_LABEL_HK12); + keys->ToggleRasterizer.page = HOTKEY_PAGE_OTHER; + keys->ToggleRasterizer.key = VK_SUBTRACT; + //State/Slots Pages ------------------------------------------------ keys->NextSaveSlot.handleKeyDown = HK_NextSaveSlot; keys->NextSaveSlot.code = "NextSaveSlot"; diff --git a/desmume/src/frontend/windows/hotkey.h b/desmume/src/frontend/windows/hotkey.h index 8bd6645c8..6a79c589c 100644 --- a/desmume/src/frontend/windows/hotkey.h +++ b/desmume/src/frontend/windows/hotkey.h @@ -1,6 +1,6 @@ /* Copyright (C) 2006 yopyop - Copyright (C) 2008-2017 DeSmuME team + Copyright (C) 2008-2019 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -78,7 +78,7 @@ struct SCustomKeys #ifdef HAVE_JIT SCustomKey CpuMode, JitBlockSizeDec, JitBlockSizeInc; #endif - SCustomKey FrameAdvance, FastForward, FastForwardToggle, IncreaseSpeed, DecreaseSpeed, FrameLimitToggle, Microphone, IncreasePressure, DecreasePressure; + SCustomKey FrameAdvance, FastForward, FastForwardToggle, IncreaseSpeed, DecreaseSpeed, FrameLimitToggle, Microphone, PrevSample, NextSample, IncreasePressure, DecreasePressure; SCustomKey PlayMovie, RecordMovie, StopMovie, ToggleReadOnly; diff --git a/desmume/src/frontend/windows/main.cpp b/desmume/src/frontend/windows/main.cpp index b5b122f9f..0042f9a0e 100755 --- a/desmume/src/frontend/windows/main.cpp +++ b/desmume/src/frontend/windows/main.cpp @@ -1,6 +1,6 @@ /* Copyright (C) 2006 Theo Berkau - Copyright (C) 2006-2018 DeSmuME team + Copyright (C) 2006-2019 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1854,14 +1854,18 @@ static void RefreshMicSettings() Mic_DeInit_Physical(); if(CommonSettings.micMode == TCommonSettings::Sample) { - if(!LoadSample(MicSampleName)) + if(!LoadSamples(MicSampleName)) { MessageBox(NULL, "Unable to read the mic sample", "DeSmuME", (MB_OK | MB_ICONEXCLAMATION)); } + else + { + driver->AddLine("Mic sample %d selected", MicSampleSelection); + } } else { - LoadSample(NULL); + LoadSamples(nullptr); if(CommonSettings.micMode == TCommonSettings::Physical) { Mic_Init_Physical(); diff --git a/desmume/src/frontend/windows/mic-win.cpp b/desmume/src/frontend/windows/mic-win.cpp index 5a59636df..ec9634da7 100644 --- a/desmume/src/frontend/windows/mic-win.cpp +++ b/desmume/src/frontend/windows/mic-win.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2008-2017 DeSmuME team + Copyright (C) 2008-2019 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,7 +40,6 @@ #include "readwrite.h" int MicDisplay; -int SampleLoaded=0; #define MIC_CHECKERR(hr) if(hr != MMSYSERR_NOERROR) return FALSE; @@ -82,11 +81,9 @@ static int CALLBACK waveInProc(HWAVEIN wavein, UINT msg, DWORD instance, DWORD_P return 0; } -static char* samplebuffer = NULL; -static int samplebuffersize = 0; static FILE* fp = NULL; -EMUFILE_MEMORY newWavData; +std::vector> micSamples; static bool dataChunk(EMUFILE &inf) { @@ -110,12 +107,15 @@ static bool dataChunk(EMUFILE &inf) { found = true; u8 *temp = new u8[chunk_length]; - if (inf.fread(temp,chunk_length) != chunk_length) + if (inf.fread(temp,chunk_length) != chunk_length || chunk_length == 0) { delete[] temp; return false; } - newWavData.fwrite(temp,chunk_length); + micSamples.resize(micSamples.size()+1); + std::vector& thisSample = micSamples[micSamples.size()-1]; + thisSample.resize(chunk_length); + memcpy(&thisSample[0], temp, chunk_length); delete[] temp; chunk_length = 0; } @@ -178,53 +178,109 @@ static bool formatChunk(EMUFILE &inf) return false; } -bool LoadSample(const char *name) +void Mic_PrevSample() +{ + if(MicSampleSelection==0) return; + MicSampleSelection--; +} + +void Mic_NextSample() +{ + if(MicSampleSelection==255) return; + MicSampleSelection++; + if(MicSampleSelection >= micSamples.size()) + { + if(micSamples.size()==0) + MicSampleSelection = 0; + else + MicSampleSelection = micSamples.size()-1; + } +} + +bool LoadSample(const char* name) { - SampleLoaded = 0; - if (!name) return true; - EMUFILE_FILE inf(name,"rb"); if (inf.fail()) return false; //wav reading code adapted from AUDIERE (LGPL) - // read the RIFF header - u8 riff_id[4]; - u32 riff_length; - u8 riff_datatype[4]; + // read the RIFF header + u8 riff_id[4]; + u32 riff_length; + u8 riff_datatype[4]; - inf.fread(riff_id, 4); - inf.read_32LE(riff_length); - inf.fread(riff_datatype, 4); + inf.fread(riff_id, 4); + inf.read_32LE(riff_length); + inf.fread(riff_datatype, 4); if (inf.size() < 12 || - memcmp(riff_id, "RIFF", 4) != 0 || - riff_length == 0 || - memcmp(riff_datatype, "WAVE", 4) != 0) { - MessageBox(0,"not a valid RIFF WAVE file",0,0); - return false; + memcmp(riff_id, "RIFF", 4) != 0 || + riff_length == 0 || + memcmp(riff_datatype, "WAVE", 4) != 0) { + MessageBox(0,"not a valid RIFF WAVE file",0,0); + return false; } - - if (!formatChunk(inf)) - return false; - - if (!dataChunk(inf)) - { - MessageBox(0,"not a valid WAVE file. some unknown problem.",0,0); - return false; - } - delete[] samplebuffer; - samplebuffersize = (int)newWavData.size(); - samplebuffer = new char[samplebuffersize]; - memcpy(samplebuffer,newWavData.buf(),samplebuffersize); - new(&newWavData) EMUFILE_MEMORY(); + if (!formatChunk(inf)) + return false; - SampleLoaded=1; + if (!dataChunk(inf)) + { + MessageBox(0,"not a valid WAVE file. some unknown problem.",0,0); + return false; + } return true; } +bool LoadSamples(const char *name) +{ + //unload any existing mic samples + micSamples.resize(0); + + //select NO mic sample + micReadSamplePos = 0; + MicSampleSelection = 0; + + //if we're disabling the mic samples system, just bail now + if (!name || !*name) return true; + + //analyze the filename for 0 at the end. anything with 0 at the end is assumed to be the beginning of a series of files + //(and if not, it can still be loaded just fine) + const char* ext = strchr(name,'.'); + + //in case the filename had no extension... it's an error. + if(!ext) return false; + + const char* maybe0 = ext-1; + + //if it was not a 0, just load it + if(*maybe0 != '0') + return LoadSample(name); + + //otherwise replace it with increasing numbers and load all those + std::string prefix = name; + prefix.resize(maybe0-name); + + //if found, it's a wildcard. load all those samples + for(int i=0;;i++) + { + char tmp[32]; + sprintf(tmp,"%d",i); + std::string trial = prefix + tmp + ".wav"; + printf("Trying sample %s\n",trial.c_str()); + bool ok = LoadSample(trial.c_str()); + if(!ok) + { + if(i==0) return false; + break; + } + } + + //OK, we loaded some samples. that's all we have to do + return true; +} + BOOL Mic_DeInit_Physical() { if(!Mic_Inited) @@ -345,17 +401,30 @@ u8 Mic_ReadSample() { if (NDS_getFinalUserInput().mic.micButtonPressed) { - if (SampleLoaded) + if (micSamples.size() > 0) { - //use a sample - //TODO: what if a movie is active? - // for now I'm going to hope that if anybody records a movie with a sample loaded, - // either they know what they're doing and plan to distribute the sample, - // or they're playing a game where it doesn't even matter or they never press the mic button. - tmp = samplebuffer[micReadSamplePos >> 1]; - micReadSamplePos++; - if (micReadSamplePos == samplebuffersize*2) - micReadSamplePos=0; + //why is this reading every sample twice? I did this for some reason in 57dbe9128d0f8cbb4bd79154fb9cda3ab6fab386 + //maybe the game reads two samples in succession to check them or something. stuff definitely works better with the two-in-a-row + if (micReadSamplePos == micSamples[MicSampleSelection].size()*2) + { + tmp = 0x80; //silence, with 8 bit signed values + } + else + { + tmp = micSamples[MicSampleSelection][micReadSamplePos >> 1]; + + //nintendogs seems sensitive to clipped samples, at least. + //by clamping these, we get better sounds on playback + //I don't know how important it is, but I like nintendogs to sound good at least.. + if(tmp == 0) tmp = 1; + if(tmp == 255) tmp = 254; + + micReadSamplePos++; + if(micReadSamplePos == micSamples[MicSampleSelection].size()*2) + { + printf("Ended mic sample MicSampleSelection\n"); + } + } } else { diff --git a/desmume/src/frontend/windows/resources.rc b/desmume/src/frontend/windows/resources.rc index b3606f74e..75f19c3ea 100755 --- a/desmume/src/frontend/windows/resources.rc +++ b/desmume/src/frontend/windows/resources.rc @@ -844,7 +844,7 @@ BEGIN LTEXT "Sample:",IDC_STATIC,15,83,110,8 EDITTEXT IDC_MICSAMPLE,15,93,190,14,ES_AUTOHSCROLL PUSHBUTTON "...",IDC_MICSAMPLEBROWSE,210,94,20,14 - CONTROL "Use Microphone Sample",IDC_USEMICSAMPLE,"Button",BS_AUTORADIOBUTTON,18,70,93,10 + CONTROL "Use Microphone Samples",IDC_USEMICSAMPLE,"Button",BS_AUTORADIOBUTTON,18,70,93,10 CONTROL "Use rand() whitenoise (NOT suitable for TAS)",IDC_USEMICRAND, "Button",BS_AUTORADIOBUTTON,18,56,157,10 CONTROL "Use internal noise sample",IDC_USENOISE,"Button",BS_AUTORADIOBUTTON,18,43,96,10 diff --git a/desmume/src/mic.h b/desmume/src/mic.h index 5ebd107aa..f22927938 100644 --- a/desmume/src/mic.h +++ b/desmume/src/mic.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2017 DeSmuME Team + Copyright (C) 2009-2019 DeSmuME Team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,7 +24,7 @@ class EMUFILE; #ifdef WIN32 static char MicSampleName[256]; -bool LoadSample(const char *name); +bool LoadSamples(const char *name); #endif extern int MicDisplay;