attempt to merge mic samples work from master
This commit is contained in:
parent
c07d7945d8
commit
3695f5b329
|
@ -80,6 +80,8 @@ int lagframecounter;
|
|||
int LagFrameFlag;
|
||||
int lastLag;
|
||||
int TotalLagFrames;
|
||||
u8 MicSampleSelection = 0;
|
||||
std::vector<std::vector<u8>> micSamples;
|
||||
|
||||
TSCalInfo TSCal;
|
||||
|
||||
|
@ -2593,6 +2595,7 @@ void NDS_Reset()
|
|||
|
||||
LidClosed = FALSE;
|
||||
countLid = 0;
|
||||
MicSampleSelection = 0;
|
||||
|
||||
resetUserInput();
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "types.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(_WINDOWS) && !defined(WXPORT)
|
||||
#include "pathsettings.h"
|
||||
|
@ -398,6 +399,7 @@ struct UserTouch
|
|||
struct UserMicrophone
|
||||
{
|
||||
u32 micButtonPressed;
|
||||
u8 micSample;
|
||||
};
|
||||
struct UserInput
|
||||
{
|
||||
|
@ -628,6 +630,8 @@ extern struct TCommonSettings {
|
|||
extern std::string InputDisplayString;
|
||||
extern int LagFrameFlag;
|
||||
extern int lastLag, TotalLagFrames;
|
||||
extern u8 MicSampleSelection;
|
||||
extern std::vector<std::vector<u8>> micSamples;
|
||||
|
||||
void MovieSRAM();
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#ifdef WIN32
|
||||
static char MicSampleName[256];
|
||||
bool LoadSample(const char *name);
|
||||
bool LoadSamples(const char *name);
|
||||
#endif
|
||||
|
||||
extern int MicDisplay;
|
||||
|
|
|
@ -41,7 +41,9 @@ bool autoMovieBackup = true;
|
|||
|
||||
#define FCEU_PrintError LOG
|
||||
|
||||
#define MOVIE_VERSION 1
|
||||
//version 1 - was the main version for a long time, most of 201x
|
||||
//version 2 - march 2019, added mic sample
|
||||
#define MOVIE_VERSION 2
|
||||
|
||||
#ifdef WIN32
|
||||
#include ".\windows\main.h"
|
||||
|
@ -105,9 +107,6 @@ bool MovieRecord::Compare(MovieRecord& compareRec)
|
|||
|
||||
//Check Stylus
|
||||
if (this->touch.padding != compareRec.touch.padding) return false;
|
||||
if (this->touch.touch != compareRec.touch.touch) return false;
|
||||
if (this->touch.x != compareRec.touch.x) return false;
|
||||
if (this->touch.y != compareRec.touch.y) return false;
|
||||
|
||||
//Check comamnds
|
||||
//if new commands are ever recordable, they need to be added here if we go with this method
|
||||
|
@ -165,6 +164,7 @@ void MovieRecord::parse(MovieData* md, EMUFILE* fp)
|
|||
touch.x = u32DecFromIstream(fp);
|
||||
touch.y = u32DecFromIstream(fp);
|
||||
touch.touch = u32DecFromIstream(fp);
|
||||
touch.micsample = u32DecFromIstream(fp);
|
||||
|
||||
fp->fgetc(); //eat the pipe
|
||||
|
||||
|
@ -183,7 +183,8 @@ void MovieRecord::dump(MovieData* md, EMUFILE* fp, int index)
|
|||
dumpPad(fp, pad);
|
||||
putdec<u8,3,true>(fp,touch.x); fp->fputc(' ');
|
||||
putdec<u8,3,true>(fp,touch.y); fp->fputc(' ');
|
||||
putdec<u8,1,true>(fp,touch.touch);
|
||||
putdec<u8,1,true>(fp,touch.touch); fp->fputc(' ');
|
||||
putdec<u8,3,true>(fp,touch.micsample);
|
||||
fp->fputc('|');
|
||||
|
||||
//each frame is on a new line
|
||||
|
@ -213,6 +214,18 @@ void MovieData::truncateAt(int frame)
|
|||
}
|
||||
|
||||
|
||||
void MovieData::installMicSample(std::string& key, std::string& val)
|
||||
{
|
||||
//which sample?
|
||||
int which = atoi(key.c_str()+strlen("micsample"));
|
||||
|
||||
//make sure we have this many
|
||||
if(micSamples.size()<which+1)
|
||||
micSamples.resize(which+1);
|
||||
|
||||
BinaryDataFromString(val, &micSamples[which]);
|
||||
}
|
||||
|
||||
void MovieData::installValue(std::string& key, std::string& val)
|
||||
{
|
||||
//todo - use another config system, or drive this from a little data structure. because this is gross
|
||||
|
@ -288,6 +301,19 @@ void MovieData::installValue(std::string& key, std::string& val)
|
|||
StringToBytes(val,&sram[0],len); // decodes either base64 or hex
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0;i<256;i++)
|
||||
{
|
||||
char tmp[256];
|
||||
sprintf(tmp,"micsample%d",i);
|
||||
if(key == tmp)
|
||||
{
|
||||
if(micSamples.size()<i+1)
|
||||
micSamples.resize(i+1);
|
||||
BinaryDataFromString(val, &micSamples[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -350,6 +376,17 @@ int MovieData::dump(EMUFILE* fp, bool binary)
|
|||
if(sram.size() != 0)
|
||||
fp->fprintf("sram %s\n", BytesToString(&sram[0],sram.size()).c_str());
|
||||
|
||||
for(int i=0;i<256;i++)
|
||||
{
|
||||
//TODO - how do these get put in here
|
||||
if(micSamples.size() > i)
|
||||
{
|
||||
char tmp[32];
|
||||
sprintf(tmp,"micsample%d",i);
|
||||
fp->fprintf("%s %s\n",tmp, BytesToString(&micSamples[i][0],micSamples[i].size()).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if(binary)
|
||||
{
|
||||
//put one | to start the binary dump
|
||||
|
@ -377,8 +414,12 @@ bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader)
|
|||
fp->fread(buf,9);
|
||||
fp->fseek(curr, SEEK_SET);
|
||||
// if(fp->fail()) return false;
|
||||
if(memcmp(buf,"version 1",9))
|
||||
return false;
|
||||
bool version1 = memcmp(buf, "version 1", 9)==0;
|
||||
bool version2 = memcmp(buf, "version 2", 9)==0;
|
||||
|
||||
if(version1) {}
|
||||
else if(version2) {}
|
||||
else return false;
|
||||
|
||||
std::string key,value;
|
||||
enum {
|
||||
|
@ -604,6 +645,11 @@ const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tas
|
|||
bool success = MovieData::loadSramFrom(&currMovieData.sram);
|
||||
if(!success) return "failed to load sram";
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
::micSamples = currMovieData.micSamples;
|
||||
#endif
|
||||
|
||||
freshMovie = true;
|
||||
ClearAutoHold();
|
||||
|
||||
|
@ -688,6 +734,7 @@ void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::stri
|
|||
currMovieData.romSerial = gameInfo.ROMserial;
|
||||
currMovieData.romFilename = path.GetRomName();
|
||||
currMovieData.rtcStart = rtcstart;
|
||||
currMovieData.micSamples = ::micSamples;
|
||||
|
||||
// reset firmware (some games can write to it)
|
||||
if (CommonSettings.UseExtFirmware == false)
|
||||
|
@ -755,6 +802,7 @@ void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::stri
|
|||
|
||||
if(mr->command_microphone()) input.mic.micButtonPressed = 1;
|
||||
else input.mic.micButtonPressed = 0;
|
||||
input.mic.micSample = MicSampleSelection;
|
||||
|
||||
if(mr->command_reset()) NDS_Reset();
|
||||
|
||||
|
@ -833,6 +881,7 @@ void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::stri
|
|||
mr.touch.touch = input.touch.isTouch ? 1 : 0;
|
||||
mr.touch.x = input.touch.isTouch ? input.touch.touchX >> 4 : 0;
|
||||
mr.touch.y = input.touch.isTouch ? input.touch.touchY >> 4 : 0;
|
||||
mr.touch.micsample = MicSampleSelection;
|
||||
|
||||
assert(mr.touch.touch || (!mr.touch.x && !mr.touch.y));
|
||||
//assert(nds.touchX == input.touch.touchX && nds.touchY == input.touch.touchY);
|
||||
|
@ -1268,3 +1317,13 @@ void FCEUI_MakeBackupMovie(bool dispMessage)
|
|||
}
|
||||
}
|
||||
|
||||
void BinaryDataFromString(std::string &inStringData, std::vector<u8> *outBinaryData)
|
||||
{
|
||||
int len = Base64StringToBytesLength(inStringData);
|
||||
if(len == -1) len = HexStringToBytesLength(inStringData); // wasn't base64, try hex
|
||||
if(len >= 1)
|
||||
{
|
||||
outBinaryData->resize(len);
|
||||
StringToBytes(inStringData, &outBinaryData->front(), len); // decodes either base64 or hex
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
struct {
|
||||
u8 x, y;
|
||||
u8 touch;
|
||||
u8 micsample;
|
||||
};
|
||||
|
||||
u32 padding;
|
||||
|
@ -144,6 +145,7 @@ public:
|
|||
std::vector<u8> sram;
|
||||
std::vector<MovieRecord> records;
|
||||
std::vector<std::wstring> comments;
|
||||
std::vector<std::vector<u8> > micSamples;
|
||||
|
||||
int rerecordCount;
|
||||
Desmume_Guid guid;
|
||||
|
@ -185,6 +187,7 @@ public:
|
|||
|
||||
void truncateAt(int frame);
|
||||
void installValue(std::string& key, std::string& val);
|
||||
void installMicSample(std::string& key, std::string& val);
|
||||
int dump(EMUFILE* fp, bool binary);
|
||||
void clearRecordRange(int start, int len);
|
||||
void insertEmpty(int at, int frames);
|
||||
|
@ -228,4 +231,5 @@ extern bool movie_readonly;
|
|||
extern bool ShowInputDisplay;
|
||||
void FCEUI_MakeBackupMovie(bool dispMessage);
|
||||
DateTime FCEUI_MovieGetRTCDefault();
|
||||
void BinaryDataFromString(std::string &inStringData, std::vector<u8> *outBinaryData);
|
||||
#endif
|
||||
|
|
|
@ -289,6 +289,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();
|
||||
osd->addLine("Mic sample %d selected", MicSampleSelection);
|
||||
}
|
||||
|
||||
void HK_PrevSampleKeyDown(int, bool justPressed)
|
||||
{
|
||||
Mic_PrevSample();
|
||||
osd->addLine("Mic sample %d selected", MicSampleSelection);
|
||||
}
|
||||
|
||||
void HK_AutoHoldKeyDown(int, bool justPressed) {AutoHoldPressed = true;}
|
||||
void HK_AutoHoldKeyUp(int) {AutoHoldPressed = false;}
|
||||
|
||||
|
@ -652,6 +667,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";
|
||||
|
|
|
@ -79,7 +79,7 @@ struct SCustomKeys
|
|||
#ifdef HAVE_JIT
|
||||
SCustomKey CpuMode, JitBlockSizeDec, JitBlockSizeInc;
|
||||
#endif
|
||||
SCustomKey FrameAdvance, FastForward, FastForwardToggle, IncreaseSpeed, DecreaseSpeed, FrameLimitToggle, Microphone, IncreasePressure, DecreasePressure, ToggleStylusJitter;
|
||||
SCustomKey FrameAdvance, FastForward, FastForwardToggle, IncreaseSpeed, DecreaseSpeed, FrameLimitToggle, Microphone, PrevSample, NextSample, IncreasePressure, DecreasePressure, ToggleStylusJitter;
|
||||
|
||||
SCustomKey PlayMovie, RecordMovie, StopMovie, ToggleReadOnly;
|
||||
|
||||
|
|
|
@ -2772,14 +2772,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
|
||||
{
|
||||
osd->addLine("Mic sample %d selected", MicSampleSelection);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadSample(NULL);
|
||||
LoadSamples(NULL);
|
||||
if(CommonSettings.micMode == TCommonSettings::Physical)
|
||||
{
|
||||
Mic_Init_Physical();
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <fstream>
|
||||
|
||||
int MicDisplay;
|
||||
int SampleLoaded=0;
|
||||
|
||||
#define MIC_CHECKERR(hr) if(hr != MMSYSERR_NOERROR) return FALSE;
|
||||
|
||||
|
@ -76,12 +75,8 @@ 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;
|
||||
|
||||
static bool dataChunk(EMUFILE* inf)
|
||||
{
|
||||
bool found = false;
|
||||
|
@ -102,11 +97,14 @@ static bool dataChunk(EMUFILE* inf)
|
|||
if (memcmp(chunk_id, "data", 4) == 0) {
|
||||
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<u8>& thisSample = micSamples[micSamples.size()-1];
|
||||
thisSample.resize(chunk_length);
|
||||
memcpy(&thisSample[0], temp, chunk_length);
|
||||
delete[] temp;
|
||||
chunk_length = 0;
|
||||
}
|
||||
|
@ -166,11 +164,27 @@ static bool formatChunk(EMUFILE* inf)
|
|||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -201,14 +215,59 @@ bool LoadSample(const char *name)
|
|||
return false;
|
||||
}
|
||||
|
||||
delete[] samplebuffer;
|
||||
samplebuffersize = (int)newWavData.size();
|
||||
samplebuffer = new char[samplebuffersize];
|
||||
memcpy(samplebuffer,newWavData.buf(),samplebuffersize);
|
||||
new(&newWavData) EMUFILE_MEMORY();
|
||||
return true;
|
||||
}
|
||||
|
||||
SampleLoaded=1;
|
||||
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 = strrchr(name,'.');
|
||||
|
||||
//in case the filename had no extension... it's an error.
|
||||
if(!ext) return false;
|
||||
|
||||
const char* maybe_0 = ext-2;
|
||||
|
||||
//in case this was an absurdly short filename
|
||||
if(ext<name)
|
||||
return LoadSample(name);
|
||||
|
||||
//if it was not a _0, just load it
|
||||
if(strncmp(maybe_0,"_0",2))
|
||||
return LoadSample(name);
|
||||
|
||||
//otherwise replace it with increasing numbers and load all those
|
||||
std::string prefix = name;
|
||||
prefix.resize(maybe_0-name+1); //take care to keep the _
|
||||
|
||||
//if found, it's a wildcard. load all those samples
|
||||
//this is limited to 254 entries in order to prevent some surprises, because I was stupid and used a byte for the MicSampleSelection.
|
||||
//I should probably change that. But it has to be limited somehow...
|
||||
for(int i=0;i<255;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;
|
||||
}
|
||||
|
||||
|
@ -333,17 +392,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];
|
||||
//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 == samplebuffersize*2)
|
||||
micReadSamplePos=0;
|
||||
if(micReadSamplePos == micSamples[MicSampleSelection].size()*2)
|
||||
{
|
||||
printf("Ended mic sample MicSampleSelection\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue