aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStapleButter <thetotalworm@gmail.com>2018-12-12 16:33:40 +0100
committerStapleButter <thetotalworm@gmail.com>2018-12-12 16:33:40 +0100
commit758bed93bc321e4909ee5a35cba349c233aa36dd (patch)
tree14fe080f875711ec2e4e6891bbe6149ed9daed1e /src
parent24d6bd27866648aaf02d4a6fbbcf68c208712180 (diff)
preliminary microphone code. requires an actual microphone. resulting audio is farty and blargy as fuck.
Diffstat (limited to 'src')
-rw-r--r--src/NDS.cpp16
-rw-r--r--src/NDS.h3
-rw-r--r--src/SPI.cpp37
-rw-r--r--src/SPI.h1
-rw-r--r--src/libui_sdl/main.cpp56
5 files changed, 108 insertions, 5 deletions
diff --git a/src/NDS.cpp b/src/NDS.cpp
index aee9e60..9bf2fab 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 5b726b1..2ffb35f 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 76b5b75..a354705 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 f2f8e0a..87ed63d 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 d620d4d..0c7cee2 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);