attempt to merge mic samples work from master

This commit is contained in:
zeromus 2019-03-21 15:20:23 -04:00
parent c07d7945d8
commit 3695f5b329
9 changed files with 212 additions and 39 deletions

View File

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

View File

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

View File

@ -24,7 +24,7 @@
#ifdef WIN32
static char MicSampleName[256];
bool LoadSample(const char *name);
bool LoadSamples(const char *name);
#endif
extern int MicDisplay;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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