winport - support multiple mic samples, selected with new hotkeys

This commit is contained in:
zeromus 2019-03-17 22:55:53 -04:00
parent ec351f3015
commit 9805fe3de4
8 changed files with 169 additions and 63 deletions

View File

@ -99,6 +99,8 @@ int lagframecounter;
int LagFrameFlag;
int lastLag;
int TotalLagFrames;
u8 MicSampleSelection = 0;
TSCalInfo TSCal;

View File

@ -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();

View File

@ -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";

View File

@ -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;

View File

@ -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();

View File

@ -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<std::vector<char>> 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<char>& 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
{

View File

@ -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

View File

@ -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;