diff --git a/src/NDS.cpp b/src/NDS.cpp index aee9e60f..9bf2fabd 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -74,6 +74,7 @@ ARMv4* ARM7; u32 NumFrames; u64 SysClockCycles; u64 LastSysClockCycles; +u32 FrameSysClockCycles; s32 CurIterationCycles; s32 ARM7Offset; @@ -760,6 +761,8 @@ void RunSystem(s32 cycles) u32 RunFrame() { + FrameSysClockCycles = 0; + if (!Running) return 263; // dorp GPU::StartFrame(); @@ -848,6 +851,7 @@ u32 RunFrame() SysClockCycles += ndscyclestorun; LastSysClockCycles += ndscyclestorun; + FrameSysClockCycles += ndscyclestorun; } #ifdef DEBUG_CHECK_DESYNC @@ -949,6 +953,11 @@ void SetKeyMask(u32 mask) KeyInput |= key_lo | (key_hi << 16); } +void MicInputFrame(s16* data, int samples) +{ + return SPI_TSC::MicInputFrame(data, samples); +} + void Halt() { @@ -1111,14 +1120,15 @@ u64 GetSysClockCycles(int num) { u64 ret; - if (num == 0) + if (num == 0 || num == 2) { - ret = SysClockCycles; + if (num == 0) ret = SysClockCycles; + else if (num == 2) ret = FrameSysClockCycles; if (CurCPU == 1) ret += (ARM9->Cycles >> 1); else if (CurCPU == 2) ret += ARM7->Cycles; } - else + else if (num == 1) { ret = LastSysClockCycles; LastSysClockCycles = 0; diff --git a/src/NDS.h b/src/NDS.h index 5b726b17..2ffb35f6 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -152,6 +152,8 @@ void ReleaseScreen(); void SetKeyMask(u32 mask); +void MicInputFrame(s16* data, int samples); + void ScheduleEvent(u32 id, bool periodic, s32 delay, void (*func)(u32), u32 param); void CancelEvent(u32 id); @@ -170,6 +172,7 @@ void GXFIFOStall(); void GXFIFOUnstall(); u32 GetPC(u32 cpu); +u64 GetSysClockCycles(int num); void NocashPrint(u32 cpu, u32 addr); bool DMAsInMode(u32 cpu, u32 mode); diff --git a/src/SPI.cpp b/src/SPI.cpp index 76b5b756..a354705f 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -453,6 +453,9 @@ u16 ConvResult; u16 TouchX, TouchY; +s16 MicBuffer[1024]; +int MicBufferLen; + bool Init() { @@ -469,6 +472,8 @@ void Reset() Data = 0; ConvResult = 0; + + MicBufferLen = 0; } void DoSavestate(Savestate* file) @@ -497,6 +502,13 @@ void SetTouchCoords(u16 x, u16 y) TouchY <<= 4; } +void MicInputFrame(s16* data, int samples) +{ + if (samples > 1024) samples = 1024; + memcpy(MicBuffer, data, samples*sizeof(s16)); + MicBufferLen = samples; +} + u8 Read() { return Data; @@ -520,7 +532,30 @@ void Write(u8 val, u32 hold) { case 0x10: ConvResult = TouchY; break; case 0x50: ConvResult = TouchX; break; - case 0x60: ConvResult = 0x800; break; // TODO: mic + + case 0x60: + { + if (MicBufferLen == 0) + ConvResult = 0x800; + else + { + // 560190 cycles per frame + u32 cyclepos = (u32)NDS::GetSysClockCycles(2); + u32 samplepos = (cyclepos * MicBufferLen) / 560190; + s16 sample = MicBuffer[samplepos]; + + // make it louder + //if (sample > 0x3FFF) sample = 0x7FFF; + //else if (sample < -0x4000) sample = -0x8000; + //else sample <<= 1; + + // make it unsigned 12-bit + sample ^= 0x8000; + ConvResult = sample >> 4; + } + } + break; + default: ConvResult = 0xFFF; break; } diff --git a/src/SPI.h b/src/SPI.h index f2f8e0aa..87ed63d5 100644 --- a/src/SPI.h +++ b/src/SPI.h @@ -36,6 +36,7 @@ namespace SPI_TSC { void SetTouchCoords(u16 x, u16 y); +void MicInputFrame(s16* data, int samples); } diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index d620d4d3..0c7cee28 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -109,6 +109,10 @@ bool Touching = false; u32 KeyInputMask; SDL_Joystick* Joystick; +const u32 kMicBufferSize = 2048; // must be power of two +s16 MicBuffer[kMicBufferSize]; +u32 MicBufferReadPos, MicBufferWritePos; + void SetupScreenRects(int width, int height); @@ -147,7 +151,6 @@ void AudioCallback(void* data, Uint8* stream, int len) // buffer length is 1024 samples // which is 710 samples at the original sample rate - //SPU::ReadOutput((s16*)stream, len>>2); s16 buf_in[710*2]; s16* buf_out = (s16*)stream; @@ -185,6 +188,23 @@ void AudioCallback(void* data, Uint8* stream, int len) } } +void MicCallback(void* data, Uint8* stream, int len) +{ + s16* input = (s16*)stream; + len /= sizeof(s16); + + if ((MicBufferWritePos + len) > kMicBufferSize) + { + u32 len1 = kMicBufferSize-MicBufferWritePos; + memcpy(&MicBuffer[MicBufferWritePos], &input[0], len1*sizeof(s16)); + memcpy(&MicBuffer[0], &input[len1], (len-len1)*sizeof(s16)); + } + else + memcpy(&MicBuffer[MicBufferWritePos], input, len*sizeof(s16)); + MicBufferWritePos += len; + MicBufferWritePos &= (kMicBufferSize-1); +} + int EmuThreadFunc(void* burp) { NDS::Init(); @@ -254,6 +274,20 @@ int EmuThreadFunc(void* burp) } NDS::SetKeyMask(keymask & joymask); + // microphone input + if ((MicBufferReadPos + 735) > kMicBufferSize) + { + s16 tmp[735]; + u32 len1 = kMicBufferSize-MicBufferReadPos; + memcpy(&tmp[0], &MicBuffer[MicBufferReadPos], len1*sizeof(s16)); + memcpy(&tmp[len1], &MicBuffer[0], (735-len1)*sizeof(s16)); + NDS::MicInputFrame(tmp, 735); + } + else + NDS::MicInputFrame(&MicBuffer[MicBufferReadPos], 735); + MicBufferReadPos += 735; + MicBufferReadPos &= (kMicBufferSize-1); + // emulate u32 nlines = NDS::RunFrame(); @@ -1594,6 +1628,26 @@ int main(int argc, char** argv) SDL_PauseAudioDevice(audio, 0); } + memset(&whatIwant, 0, sizeof(SDL_AudioSpec)); + whatIwant.freq = 44100; + whatIwant.format = AUDIO_S16LSB; + whatIwant.channels = 1; + whatIwant.samples = 1024; + whatIwant.callback = MicCallback; + audio = SDL_OpenAudioDevice(NULL, 1, &whatIwant, &whatIget, 0); + if (!audio) + { + printf("Mic init failed: %s\n", SDL_GetError()); + } + else + { + SDL_PauseAudioDevice(audio, 0); + } + + memset(MicBuffer, 0, sizeof(MicBuffer)); + MicBufferReadPos = 0; + MicBufferWritePos = 0; + // TODO: support more joysticks if (SDL_NumJoysticks() > 0) Joystick = SDL_JoystickOpen(0);