Surprise! Added support for microphone emulation, but only for Win32.
There are 3 problems : 1. the sound crackles a bit 2. the microphone amplifier isn't supported 3. the emu freezes if you don't close it by the console
This commit is contained in:
parent
c0cb8ee700
commit
47db86ec02
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
Microphone emulation for Win32
|
||||||
|
|
||||||
|
The NDS microphone produces 8-bit sound sampled at 16khz.
|
||||||
|
The sound data must be read sample-by-sample through the
|
||||||
|
ARM7 SPI device (touchscreen controller, channel 6).
|
||||||
|
|
||||||
|
Note : I added these notes because the microphone isn't
|
||||||
|
documented on GBATek.
|
||||||
|
*/
|
||||||
|
#include <windows.h>
|
||||||
|
#include "../types.h"
|
||||||
|
#include "../debug.h"
|
||||||
|
#include "../mic.h"
|
||||||
|
|
||||||
|
#define MIC_CHECKERR(hr) if(hr != MMSYSERR_NOERROR) return FALSE;
|
||||||
|
|
||||||
|
#define MIC_BUFSIZE 4096
|
||||||
|
|
||||||
|
BOOL Mic_Inited = FALSE;
|
||||||
|
|
||||||
|
s8 Mic_Buffer[MIC_BUFSIZE];
|
||||||
|
u16 Mic_BufPos;
|
||||||
|
|
||||||
|
HWAVEIN waveIn;
|
||||||
|
WAVEHDR waveHdr;
|
||||||
|
|
||||||
|
static int CALLBACK waveInProc(HWAVEIN wavein, UINT msg, DWORD instance, DWORD param1, DWORD param2)
|
||||||
|
{
|
||||||
|
LPWAVEHDR lpWaveHdr;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
if(!Mic_Inited)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if(msg == WIM_DATA)
|
||||||
|
{
|
||||||
|
lpWaveHdr = (LPWAVEHDR)param1;
|
||||||
|
|
||||||
|
hr = waveInAddBuffer(waveIn, lpWaveHdr, sizeof(WAVEHDR));
|
||||||
|
if(hr != MMSYSERR_NOERROR)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL Mic_Init()
|
||||||
|
{
|
||||||
|
if(Mic_Inited)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
Mic_Inited = FALSE;
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
|
WAVEFORMATEX wfx;
|
||||||
|
|
||||||
|
memset(Mic_Buffer, 0, MIC_BUFSIZE);
|
||||||
|
Mic_BufPos = 0;
|
||||||
|
|
||||||
|
memset(&wfx, 0, sizeof(wfx));
|
||||||
|
wfx.cbSize = 0;
|
||||||
|
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
|
wfx.nChannels = 1;
|
||||||
|
wfx.nSamplesPerSec = 16000;
|
||||||
|
wfx.nBlockAlign = 1;
|
||||||
|
wfx.nAvgBytesPerSec = 16000;
|
||||||
|
wfx.wBitsPerSample = 8;
|
||||||
|
|
||||||
|
hr = waveInOpen(&waveIn, WAVE_MAPPER, &wfx, (DWORD_PTR)waveInProc, 0, CALLBACK_FUNCTION);
|
||||||
|
MIC_CHECKERR(hr)
|
||||||
|
|
||||||
|
memset(&waveHdr, 0, sizeof(waveHdr));
|
||||||
|
waveHdr.lpData = (LPSTR)Mic_Buffer;
|
||||||
|
waveHdr.dwBufferLength = MIC_BUFSIZE;
|
||||||
|
|
||||||
|
hr = waveInPrepareHeader(waveIn, &waveHdr, sizeof(WAVEHDR));
|
||||||
|
MIC_CHECKERR(hr)
|
||||||
|
|
||||||
|
hr = waveInAddBuffer(waveIn, &waveHdr, sizeof(WAVEHDR));
|
||||||
|
MIC_CHECKERR(hr)
|
||||||
|
|
||||||
|
hr = waveInStart(waveIn);
|
||||||
|
MIC_CHECKERR(hr)
|
||||||
|
|
||||||
|
Mic_Inited = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mic_Reset()
|
||||||
|
{
|
||||||
|
if(!Mic_Inited)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset(Mic_Buffer, 0, MIC_BUFSIZE);
|
||||||
|
Mic_BufPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mic_DeInit()
|
||||||
|
{
|
||||||
|
if(!Mic_Inited)
|
||||||
|
return;
|
||||||
|
|
||||||
|
waveInReset(waveIn);
|
||||||
|
waveInClose(waveIn);
|
||||||
|
|
||||||
|
Mic_Inited = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 Mic_ReadSample()
|
||||||
|
{
|
||||||
|
if(!Mic_Inited)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
u8 tmp = (u8)Mic_Buffer[Mic_BufPos >> 1];
|
||||||
|
u8 ret;
|
||||||
|
|
||||||
|
if(Mic_BufPos & 0x1)
|
||||||
|
{
|
||||||
|
ret = ((tmp & 0x1) << 7);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = ((tmp & 0xFE) >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mic_BufPos++;
|
||||||
|
Mic_BufPos %= (MIC_BUFSIZE << 1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
Loading…
Reference in New Issue