mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-23 06:10:03 -06:00
preliminary microphone code. requires an actual microphone. resulting audio is farty and blargy as fuck.
This commit is contained in:
16
src/NDS.cpp
16
src/NDS.cpp
@ -74,6 +74,7 @@ ARMv4* ARM7;
|
|||||||
u32 NumFrames;
|
u32 NumFrames;
|
||||||
u64 SysClockCycles;
|
u64 SysClockCycles;
|
||||||
u64 LastSysClockCycles;
|
u64 LastSysClockCycles;
|
||||||
|
u32 FrameSysClockCycles;
|
||||||
|
|
||||||
s32 CurIterationCycles;
|
s32 CurIterationCycles;
|
||||||
s32 ARM7Offset;
|
s32 ARM7Offset;
|
||||||
@ -760,6 +761,8 @@ void RunSystem(s32 cycles)
|
|||||||
|
|
||||||
u32 RunFrame()
|
u32 RunFrame()
|
||||||
{
|
{
|
||||||
|
FrameSysClockCycles = 0;
|
||||||
|
|
||||||
if (!Running) return 263; // dorp
|
if (!Running) return 263; // dorp
|
||||||
|
|
||||||
GPU::StartFrame();
|
GPU::StartFrame();
|
||||||
@ -848,6 +851,7 @@ u32 RunFrame()
|
|||||||
|
|
||||||
SysClockCycles += ndscyclestorun;
|
SysClockCycles += ndscyclestorun;
|
||||||
LastSysClockCycles += ndscyclestorun;
|
LastSysClockCycles += ndscyclestorun;
|
||||||
|
FrameSysClockCycles += ndscyclestorun;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_CHECK_DESYNC
|
#ifdef DEBUG_CHECK_DESYNC
|
||||||
@ -949,6 +953,11 @@ void SetKeyMask(u32 mask)
|
|||||||
KeyInput |= key_lo | (key_hi << 16);
|
KeyInput |= key_lo | (key_hi << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MicInputFrame(s16* data, int samples)
|
||||||
|
{
|
||||||
|
return SPI_TSC::MicInputFrame(data, samples);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Halt()
|
void Halt()
|
||||||
{
|
{
|
||||||
@ -1111,14 +1120,15 @@ u64 GetSysClockCycles(int num)
|
|||||||
{
|
{
|
||||||
u64 ret;
|
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);
|
if (CurCPU == 1) ret += (ARM9->Cycles >> 1);
|
||||||
else if (CurCPU == 2) ret += ARM7->Cycles;
|
else if (CurCPU == 2) ret += ARM7->Cycles;
|
||||||
}
|
}
|
||||||
else
|
else if (num == 1)
|
||||||
{
|
{
|
||||||
ret = LastSysClockCycles;
|
ret = LastSysClockCycles;
|
||||||
LastSysClockCycles = 0;
|
LastSysClockCycles = 0;
|
||||||
|
@ -152,6 +152,8 @@ void ReleaseScreen();
|
|||||||
|
|
||||||
void SetKeyMask(u32 mask);
|
void SetKeyMask(u32 mask);
|
||||||
|
|
||||||
|
void MicInputFrame(s16* data, int samples);
|
||||||
|
|
||||||
void ScheduleEvent(u32 id, bool periodic, s32 delay, void (*func)(u32), u32 param);
|
void ScheduleEvent(u32 id, bool periodic, s32 delay, void (*func)(u32), u32 param);
|
||||||
void CancelEvent(u32 id);
|
void CancelEvent(u32 id);
|
||||||
|
|
||||||
@ -170,6 +172,7 @@ void GXFIFOStall();
|
|||||||
void GXFIFOUnstall();
|
void GXFIFOUnstall();
|
||||||
|
|
||||||
u32 GetPC(u32 cpu);
|
u32 GetPC(u32 cpu);
|
||||||
|
u64 GetSysClockCycles(int num);
|
||||||
void NocashPrint(u32 cpu, u32 addr);
|
void NocashPrint(u32 cpu, u32 addr);
|
||||||
|
|
||||||
bool DMAsInMode(u32 cpu, u32 mode);
|
bool DMAsInMode(u32 cpu, u32 mode);
|
||||||
|
37
src/SPI.cpp
37
src/SPI.cpp
@ -453,6 +453,9 @@ u16 ConvResult;
|
|||||||
|
|
||||||
u16 TouchX, TouchY;
|
u16 TouchX, TouchY;
|
||||||
|
|
||||||
|
s16 MicBuffer[1024];
|
||||||
|
int MicBufferLen;
|
||||||
|
|
||||||
|
|
||||||
bool Init()
|
bool Init()
|
||||||
{
|
{
|
||||||
@ -469,6 +472,8 @@ void Reset()
|
|||||||
Data = 0;
|
Data = 0;
|
||||||
|
|
||||||
ConvResult = 0;
|
ConvResult = 0;
|
||||||
|
|
||||||
|
MicBufferLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoSavestate(Savestate* file)
|
void DoSavestate(Savestate* file)
|
||||||
@ -497,6 +502,13 @@ void SetTouchCoords(u16 x, u16 y)
|
|||||||
TouchY <<= 4;
|
TouchY <<= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MicInputFrame(s16* data, int samples)
|
||||||
|
{
|
||||||
|
if (samples > 1024) samples = 1024;
|
||||||
|
memcpy(MicBuffer, data, samples*sizeof(s16));
|
||||||
|
MicBufferLen = samples;
|
||||||
|
}
|
||||||
|
|
||||||
u8 Read()
|
u8 Read()
|
||||||
{
|
{
|
||||||
return Data;
|
return Data;
|
||||||
@ -520,7 +532,30 @@ void Write(u8 val, u32 hold)
|
|||||||
{
|
{
|
||||||
case 0x10: ConvResult = TouchY; break;
|
case 0x10: ConvResult = TouchY; break;
|
||||||
case 0x50: ConvResult = TouchX; 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;
|
default: ConvResult = 0xFFF; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ namespace SPI_TSC
|
|||||||
{
|
{
|
||||||
|
|
||||||
void SetTouchCoords(u16 x, u16 y);
|
void SetTouchCoords(u16 x, u16 y);
|
||||||
|
void MicInputFrame(s16* data, int samples);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +109,10 @@ bool Touching = false;
|
|||||||
u32 KeyInputMask;
|
u32 KeyInputMask;
|
||||||
SDL_Joystick* Joystick;
|
SDL_Joystick* Joystick;
|
||||||
|
|
||||||
|
const u32 kMicBufferSize = 2048; // must be power of two
|
||||||
|
s16 MicBuffer[kMicBufferSize];
|
||||||
|
u32 MicBufferReadPos, MicBufferWritePos;
|
||||||
|
|
||||||
|
|
||||||
void SetupScreenRects(int width, int height);
|
void SetupScreenRects(int width, int height);
|
||||||
|
|
||||||
@ -147,7 +151,6 @@ void AudioCallback(void* data, Uint8* stream, int len)
|
|||||||
// buffer length is 1024 samples
|
// buffer length is 1024 samples
|
||||||
// which is 710 samples at the original sample rate
|
// which is 710 samples at the original sample rate
|
||||||
|
|
||||||
//SPU::ReadOutput((s16*)stream, len>>2);
|
|
||||||
s16 buf_in[710*2];
|
s16 buf_in[710*2];
|
||||||
s16* buf_out = (s16*)stream;
|
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)
|
int EmuThreadFunc(void* burp)
|
||||||
{
|
{
|
||||||
NDS::Init();
|
NDS::Init();
|
||||||
@ -254,6 +274,20 @@ int EmuThreadFunc(void* burp)
|
|||||||
}
|
}
|
||||||
NDS::SetKeyMask(keymask & joymask);
|
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
|
// emulate
|
||||||
u32 nlines = NDS::RunFrame();
|
u32 nlines = NDS::RunFrame();
|
||||||
|
|
||||||
@ -1594,6 +1628,26 @@ int main(int argc, char** argv)
|
|||||||
SDL_PauseAudioDevice(audio, 0);
|
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
|
// TODO: support more joysticks
|
||||||
if (SDL_NumJoysticks() > 0)
|
if (SDL_NumJoysticks() > 0)
|
||||||
Joystick = SDL_JoystickOpen(0);
|
Joystick = SDL_JoystickOpen(0);
|
||||||
|
Reference in New Issue
Block a user