aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/frontend/FrontendUtil.h11
-rw-r--r--src/frontend/Util_Audio.cpp64
-rw-r--r--src/frontend/qt_sdl/main.cpp177
3 files changed, 247 insertions, 5 deletions
diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h
index faa29de..6a6f8ea 100644
--- a/src/frontend/FrontendUtil.h
+++ b/src/frontend/FrontendUtil.h
@@ -101,6 +101,17 @@ int AudioOut_GetNumSamples(int outlen);
// note: this assumes the output buffer is interleaved stereo
void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen);
+// feed silence to the microphone input
+void Mic_FeedSilence();
+
+// feed random noise to the microphone input
+void Mic_FeedNoise();
+
+// feed an external buffer to the microphone input
+// buffer should be mono
+void Mic_FeedExternalBuffer();
+void Mic_SetExternalBuffer(s16* buffer, u32 len);
+
}
#endif // FRONTENDUTIL_H
diff --git a/src/frontend/Util_Audio.cpp b/src/frontend/Util_Audio.cpp
index fe0ecab..2088efe 100644
--- a/src/frontend/Util_Audio.cpp
+++ b/src/frontend/Util_Audio.cpp
@@ -17,6 +17,7 @@
*/
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <math.h>
@@ -26,7 +27,6 @@
#include "Platform.h"
#include "NDS.h"
-#include "GBACart.h"
namespace Frontend
@@ -35,13 +35,22 @@ namespace Frontend
int AudioOut_Freq;
float AudioOut_SampleFrac;
+s16* MicBuffer;
+u32 MicBufferLength;
+u32 MicBufferReadPos;
+
void Init_Audio(int outputfreq)
{
AudioOut_Freq = outputfreq;
AudioOut_SampleFrac = 0;
+
+ MicBuffer = nullptr;
+ MicBufferLength = 0;
+ MicBufferReadPos = 0;
}
+
int AudioOut_GetNumSamples(int outlen)
{
float f_len_in = (outlen * 32823.6328125) / (float)AudioOut_Freq;
@@ -74,4 +83,57 @@ void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen)
}
}
+
+void Mic_FeedSilence()
+{
+ MicBufferReadPos = 0;
+ NDS::MicInputFrame(NULL, 0);
+}
+
+void Mic_FeedNoise()
+{
+ // note: DS games seem to expect very saturated 'blowing into mic' noise
+
+ s16 tmp[735];
+
+ for (int i = 0; i < 735; i++)
+ {
+ int val = rand() >> 8;
+ if (val < -0x8000) val = -0x8000;
+ else if (val > 0x7FFF) val = 0x7FFF;
+
+ tmp[i] = val;
+ }
+
+ NDS::MicInputFrame(tmp, 735);
+}
+
+void Mic_FeedExternalBuffer()
+{
+ if (!MicBuffer) return Mic_FeedSilence();
+
+ if ((MicBufferReadPos + 735) > MicBufferLength)
+ {
+ s16 tmp[735];
+ u32 len1 = MicBufferLength - MicBufferReadPos;
+ memcpy(&tmp[0], &MicBuffer[MicBufferReadPos], len1*sizeof(s16));
+ memcpy(&tmp[len1], &MicBuffer[0], (735 - len1)*sizeof(s16));
+
+ NDS::MicInputFrame(tmp, 735);
+ MicBufferReadPos = 735 - len1;
+ }
+ else
+ {
+ NDS::MicInputFrame(&MicBuffer[MicBufferReadPos], 735);
+ MicBufferReadPos += 735;
+ }
+}
+
+void Mic_SetExternalBuffer(s16* buffer, u32 len)
+{
+ MicBuffer = buffer;
+ MicBufferLength = len;
+ MicBufferReadPos = 0;
+}
+
}
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index 67272af..1615fa3 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -66,6 +66,13 @@ int audioFreq;
SDL_cond* audioSync;
SDL_mutex* audioSyncLock;
+SDL_AudioDeviceID micDevice;
+s16 micExtBuffer[2048];
+u32 micExtBufferWritePos;
+
+u32 micWavLength;
+s16* micWavBuffer;
+
void audioCallback(void* data, Uint8* stream, int len)
{
@@ -104,6 +111,133 @@ void audioCallback(void* data, Uint8* stream, int len)
}
+void micLoadWav(const char* name)
+{
+ SDL_AudioSpec format;
+ memset(&format, 0, sizeof(SDL_AudioSpec));
+
+ if (micWavBuffer) delete[] micWavBuffer;
+ micWavBuffer = nullptr;
+ micWavLength = 0;
+
+ u8* buf;
+ u32 len;
+ if (!SDL_LoadWAV(name, &format, &buf, &len))
+ return;
+
+ const u64 dstfreq = 44100;
+
+ if (format.format == AUDIO_S16 || format.format == AUDIO_U16)
+ {
+ int srcinc = format.channels;
+ len /= (2 * srcinc);
+
+ micWavLength = (len * dstfreq) / format.freq;
+ if (micWavLength < 735) micWavLength = 735;
+ micWavBuffer = new s16[micWavLength];
+
+ float res_incr = len / (float)micWavLength;
+ float res_timer = 0;
+ int res_pos = 0;
+
+ for (int i = 0; i < micWavLength; i++)
+ {
+ u16 val = ((u16*)buf)[res_pos];
+ if (SDL_AUDIO_ISUNSIGNED(format.format)) val ^= 0x8000;
+
+ micWavBuffer[i] = val;
+
+ res_timer += res_incr;
+ while (res_timer >= 1.0)
+ {
+ res_timer -= 1.0;
+ res_pos += srcinc;
+ }
+ }
+ }
+ else if (format.format == AUDIO_S8 || format.format == AUDIO_U8)
+ {
+ int srcinc = format.channels;
+ len /= srcinc;
+
+ micWavLength = (len * dstfreq) / format.freq;
+ if (micWavLength < 735) micWavLength = 735;
+ micWavBuffer = new s16[micWavLength];
+
+ float res_incr = len / (float)micWavLength;
+ float res_timer = 0;
+ int res_pos = 0;
+
+ for (int i = 0; i < micWavLength; i++)
+ {
+ u16 val = buf[res_pos] << 8;
+ if (SDL_AUDIO_ISUNSIGNED(format.format)) val ^= 0x8000;
+
+ micWavBuffer[i] = val;
+
+ res_timer += res_incr;
+ while (res_timer >= 1.0)
+ {
+ res_timer -= 1.0;
+ res_pos += srcinc;
+ }
+ }
+ }
+ else
+ printf("bad WAV format %08X\n", format.format);
+
+ SDL_FreeWAV(buf);
+}
+
+void micCallback(void* data, Uint8* stream, int len)
+{
+ s16* input = (s16*)stream;
+ len /= sizeof(s16);
+
+ int maxlen = sizeof(micExtBuffer) / sizeof(s16);
+
+ if ((micExtBufferWritePos + len) > maxlen)
+ {
+ u32 len1 = maxlen - micExtBufferWritePos;
+ memcpy(&micExtBuffer[micExtBufferWritePos], &input[0], len1*sizeof(s16));
+ memcpy(&micExtBuffer[0], &input[len1], (len - len1)*sizeof(s16));
+ micExtBufferWritePos = len - len1;
+ }
+ else
+ {
+ memcpy(&micExtBuffer[micExtBufferWritePos], input, len*sizeof(s16));
+ micExtBufferWritePos += len;
+ }
+}
+
+void micProcess()
+{
+ int type = Config::MicInputType;
+ bool cmd = Input::HotkeyDown(HK_Mic);
+
+ if (type != 1 && !cmd)
+ {
+ type = 0;
+ }
+
+ switch (type)
+ {
+ case 0: // no mic
+ Frontend::Mic_FeedSilence();
+ break;
+
+ case 1: // host mic
+ case 3: // WAV
+ Frontend::Mic_FeedExternalBuffer();
+ break;
+
+ case 2: // white noise
+ Frontend::Mic_FeedNoise();
+ break;
+ }
+}
+
+
EmuThread::EmuThread(QObject* parent) : QThread(parent)
{
EmuStatus = 0;
@@ -189,9 +323,9 @@ void EmuThread::run()
}
// microphone input
- /*FeedMicInput();
+ micProcess();
- if (Screen_UseGL)
+ /*if (Screen_UseGL)
{
uiGLBegin(GLContext);
uiGLMakeContextCurrent(GLContext);
@@ -365,6 +499,7 @@ void EmuThread::emuRun()
// checkme
emit windowEmuStart();
if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0);
+ if (micDevice) SDL_PauseAudioDevice(micDevice, 0);
}
void EmuThread::emuPause()
@@ -374,6 +509,7 @@ void EmuThread::emuPause()
while (EmuStatus != 2);
if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1);
+ if (micDevice) SDL_PauseAudioDevice(micDevice, 1);
}
void EmuThread::emuUnpause()
@@ -381,6 +517,7 @@ void EmuThread::emuUnpause()
EmuRunning = PrevEmuStatus;
if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0);
+ if (micDevice) SDL_PauseAudioDevice(micDevice, 0);
}
void EmuThread::emuStop()
@@ -388,6 +525,7 @@ void EmuThread::emuStop()
EmuRunning = 0;
if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1);
+ if (micDevice) SDL_PauseAudioDevice(micDevice, 1);
}
bool EmuThread::emuIsRunning()
@@ -1300,9 +1438,40 @@ int main(int argc, char** argv)
SDL_PauseAudioDevice(audioDevice, 1);
}
+ memset(&whatIwant, 0, sizeof(SDL_AudioSpec));
+ whatIwant.freq = 44100;
+ whatIwant.format = AUDIO_S16LSB;
+ whatIwant.channels = 1;
+ whatIwant.samples = 1024;
+ whatIwant.callback = micCallback;
+ micDevice = SDL_OpenAudioDevice(NULL, 1, &whatIwant, &whatIget, 0);
+ if (!micDevice)
+ {
+ printf("Mic init failed: %s\n", SDL_GetError());
+ }
+ else
+ {
+ SDL_PauseAudioDevice(micDevice, 1);
+ }
+
+
+ memset(micExtBuffer, 0, sizeof(micExtBuffer));
+ micExtBufferWritePos = 0;
+ micWavBuffer = nullptr;
+
Frontend::Init_ROM();
Frontend::Init_Audio(audioFreq);
+ if (Config::MicInputType == 1)
+ {
+ Frontend::Mic_SetExternalBuffer(micExtBuffer, sizeof(micExtBuffer)/sizeof(s16));
+ }
+ else if (Config::MicInputType == 3)
+ {
+ micLoadWav(Config::MicWavPath);
+ Frontend::Mic_SetExternalBuffer(micWavBuffer, micWavLength);
+ }
+
Input::JoystickID = Config::JoystickID;
Input::OpenJoystick();
@@ -1349,12 +1518,12 @@ int main(int argc, char** argv)
Input::CloseJoystick();
if (audioDevice) SDL_CloseAudioDevice(audioDevice);
- //if (MicDevice) SDL_CloseAudioDevice(MicDevice);
+ if (micDevice) SDL_CloseAudioDevice(micDevice);
SDL_DestroyCond(audioSync);
SDL_DestroyMutex(audioSyncLock);
- //if (MicWavBuffer) delete[] MicWavBuffer;
+ if (micWavBuffer) delete[] micWavBuffer;
Config::Save();