diff --git a/desmume/src/SPU.cpp b/desmume/src/SPU.cpp index c402cb7d6..6d547ad2f 100644 --- a/desmume/src/SPU.cpp +++ b/desmume/src/SPU.cpp @@ -47,8 +47,8 @@ #define K_ADPCM_LOOPING_RECOVERY_INDEX 99999 //#ifdef FASTBUILD -// #undef FORCEINLINE -// #define FORCEINLINE + #undef FORCEINLINE + #define FORCEINLINE //#endif //static ISynchronizingAudioBuffer* synchronizer = metaspu_construct(ESynchMethod_Z); @@ -538,6 +538,7 @@ void SPU_struct::ProbeCapture(int which) u32 len = regs.cap[which].len; if(len==0) len=1; regs.cap[which].runtime.maxdad = regs.cap[which].dad + len*4; + regs.cap[which].runtime.sampcnt = 0; } void SPU_struct::WriteByte(u32 addr, u8 val) @@ -889,10 +890,7 @@ template static FORCEINLINE void TestForLoop(SPU_struct *SPU, channe } else { - chan->status = CHANSTAT_STOPPED; - - if(SPU == SPU_core) - MMU.ARM7_REG[0x403 + (((chan-SPU->channels) ) * 0x10)] &= 0x7F; + SPU->KeyOff(chan->index); SPU->bufpos = SPU->buflength; } } @@ -926,8 +924,7 @@ static FORCEINLINE void TestForLoop2(SPU_struct *SPU, channel_struct *chan) else { chan->status = CHANSTAT_STOPPED; - if(SPU == SPU_core) - MMU.ARM7_REG[0x403 + (((chan-SPU->channels) ) * 0x10)] &= 0x7F; + SPU->KeyOff(chan->index); SPU->bufpos = SPU->buflength; } } @@ -943,6 +940,7 @@ template FORCEINLINE static void SPU_Mix(SPU_struct* SPU, channel_ } } +//WORK template FORCEINLINE static void ____SPU_ChanUpdate(SPU_struct* const SPU, channel_struct* const chan) { @@ -1006,6 +1004,7 @@ FORCEINLINE static void _SPU_ChanUpdate(const bool actuallyMix, SPU_struct* cons } } +//ENTER static void SPU_MixAudio(bool actuallyMix, SPU_struct *SPU, int length) { if(actuallyMix) @@ -1040,8 +1039,70 @@ static void SPU_MixAudio(bool actuallyMix, SPU_struct *SPU, int length) // Mix audio _SPU_ChanUpdate(!CommonSettings.spu_muteChannels[i] && actuallyMix, SPU, chan); + //_SPU_ChanUpdate(actuallyMix, SPU, chan); } + //TODO - a lot of capture and output modes are not supported. + //this works in starfy, but not in nsmb, which requires the other modes. + //so, we'll have to support it soon + +#ifdef ENABLE_SOUND_CAPTURE + + bool skipcap = false; +#ifdef _MSC_VER + if(GetAsyncKeyState(VK_SHIFT)) skipcap=true; +#endif + + static FILE* test = NULL; + if(!test) test = fopen("d:\\raw.raw","wb"); + if(SPU==SPU_core) + { + for(int capchan=0;capchan<2;capchan++) + { + if(SPU->regs.cap[capchan].runtime.running) + { + SPU_struct::REGS::CAP& cap = SPU->regs.cap[capchan]; + for(int i=0;isndbuf[i*2+capchan]; + u32 last = sputrunc(cap.runtime.sampcnt); + cap.runtime.sampcnt += SPU->channels[1+2*capchan].sampinc; + u32 curr = sputrunc(cap.runtime.sampcnt); + for(u32 j=last+1;j<=curr;j++) + { + u32 multiplier; + + if(cap.bits8) + { + s8 sample8 = sample>>8; + if(skipcap) _MMU_write08<1,MMU_AT_DMA>(cap.runtime.curdad,0); + else _MMU_write08<1,MMU_AT_DMA>(cap.runtime.curdad,sample8); + cap.runtime.curdad++; + multiplier = 4; + } + else + { + s16 sample16 = sample; + if(skipcap) _MMU_write16<1,MMU_AT_DMA>(cap.runtime.curdad,0); + else _MMU_write16<1,MMU_AT_DMA>(cap.runtime.curdad,sample16); + if(capchan==0) fwrite(&sample16,2,1,test); + cap.runtime.curdad+=2; + multiplier = 2; + } + + if(cap.runtime.curdad>=cap.runtime.maxdad) { + cap.runtime.curdad = cap.dad; + cap.runtime.sampcnt -= cap.len*multiplier; + } + } + } + } + } + } + +#endif + + // convert from 32-bit->16-bit if(actuallyMix && speakers) for (int i = 0; i < length*2; i++) @@ -1279,7 +1340,7 @@ void WAV_WavSoundUpdate(void* soundData, int numSamples, WAVMode mode) void spu_savestate(EMUFILE* os) { //version - write32le(4,os); + write32le(5,os); SPU_struct *spu = SPU_core; @@ -1319,20 +1380,20 @@ void spu_savestate(EMUFILE* os) write8le(spu->regs.masteren,os); write16le(spu->regs.soundbias,os); - //save capture regs for later, when we're sure what we need - //for(int i=0;i<2;i++) - //{ - // write8le(spu->regs.cap[i].add,os); - // write8le(spu->regs.cap[i].source,os); - // write8le(spu->regs.cap[i].oneshot,os); - // write8le(spu->regs.cap[i].bits8,os); - // write8le(spu->regs.cap[i].active,os); - // write32le(spu->regs.cap[i].dad,os); - // write16le(spu->regs.cap[i].len,os); - // write8le(spu->regs.cap[i].runtime.running,os); - // write32le(spu->regs.cap[i].runtime.curdad,os); - // write32le(spu->regs.cap[i].runtime.maxdad,os); - //} + for(int i=0;i<2;i++) + { + write8le(spu->regs.cap[i].add,os); + write8le(spu->regs.cap[i].source,os); + write8le(spu->regs.cap[i].oneshot,os); + write8le(spu->regs.cap[i].bits8,os); + write8le(spu->regs.cap[i].active,os); + write32le(spu->regs.cap[i].dad,os); + write16le(spu->regs.cap[i].len,os); + write8le(spu->regs.cap[i].runtime.running,os); + write32le(spu->regs.cap[i].runtime.curdad,os); + write32le(spu->regs.cap[i].runtime.maxdad,os); + write_double_le(spu->regs.cap[i].runtime.sampcnt,os); + } } bool spu_loadstate(EMUFILE* is, int size) @@ -1403,21 +1464,24 @@ bool spu_loadstate(EMUFILE* is, int size) read8le(&spu->regs.ctl_ch2,is); read8le(&spu->regs.masteren,is); read16le(&spu->regs.soundbias,is); + } - //save capture regs for later, when we're sure what we need - //for(int i=0;i<2;i++) - //{ - // read8le(&spu->regs.cap[i].add,is); - // read8le(&spu->regs.cap[i].source,is); - // read8le(&spu->regs.cap[i].oneshot,is); - // read8le(&spu->regs.cap[i].bits8,is); - // read8le(&spu->regs.cap[i].active,is); - // read32le(&spu->regs.cap[i].dad,is); - // read16le(&spu->regs.cap[i].len,is); - // read8le(&spu->regs.cap[i].runtime.running,is); - // read32le(&spu->regs.cap[i].runtime.curdad,is); - // read32le(&spu->regs.cap[i].runtime.maxdad,is); - //} + if(version>=5) + { + for(int i=0;i<2;i++) + { + read8le(&spu->regs.cap[i].add,is); + read8le(&spu->regs.cap[i].source,is); + read8le(&spu->regs.cap[i].oneshot,is); + read8le(&spu->regs.cap[i].bits8,is); + read8le(&spu->regs.cap[i].active,is); + read32le(&spu->regs.cap[i].dad,is); + read16le(&spu->regs.cap[i].len,is); + read8le(&spu->regs.cap[i].runtime.running,is); + read32le(&spu->regs.cap[i].runtime.curdad,is); + read32le(&spu->regs.cap[i].runtime.maxdad,is); + read_double_le(&spu->regs.cap[i].runtime.sampcnt,is); + } } //older versions didnt store a mastervol; diff --git a/desmume/src/SPU.h b/desmume/src/SPU.h index 343b9239e..75b00f16f 100644 --- a/desmume/src/SPU.h +++ b/desmume/src/SPU.h @@ -147,6 +147,7 @@ public: u8 running; u32 curdad; u32 maxdad; + double sampcnt; } runtime; } cap[2]; } regs; diff --git a/desmume/src/readwrite.h b/desmume/src/readwrite.h index e95e16b2e..9b4d78667 100644 --- a/desmume/src/readwrite.h +++ b/desmume/src/readwrite.h @@ -32,6 +32,7 @@ inline int write8le(u8* b, EMUFILE *fp) { return write8le(*b,fp); } int write16le(u16 b, EMUFILE* os); int write32le(u32 b, EMUFILE* os); int write64le(u64 b, EMUFILE* os); +inline int write_double_le(double b, EMUFILE*is) { u64 temp = double_to_u64(b); int ret = write64le(temp,is); return ret; } int read8le(u8 *Bufo, EMUFILE*is); int read16le(u16 *Bufo, EMUFILE*is); @@ -39,6 +40,7 @@ inline int read16le(s16 *Bufo, EMUFILE*is) { return read16le((u16*)Bufo,is); } int read32le(u32 *Bufo, EMUFILE*is); inline int read32le(s32 *Bufo, EMUFILE*is) { return read32le((u32*)Bufo,is); } int read64le(u64 *Bufo, EMUFILE*is); +inline int read_double_le(double *Bufo, EMUFILE*is) { u64 temp; int ret = read64le(&temp,is); *Bufo = u64_to_double(temp); return ret; } int read16le(u16 *Bufo, std::istream *is);