mirror of
https://github.com/love2d/love-android.git
synced 2026-08-20 12:40:28 +02:00
Updated openal-soft to version 1.15.1
This commit is contained in:
@@ -28,32 +28,34 @@
|
||||
#include <mmsystem.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "alu.h"
|
||||
#include "threads.h"
|
||||
|
||||
#ifndef WAVE_FORMAT_IEEE_FLOAT
|
||||
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
// MMSYSTEM Device
|
||||
volatile ALboolean bWaveShutdown;
|
||||
HANDLE hWaveThreadEvent;
|
||||
HANDLE hWaveThread;
|
||||
DWORD ulWaveThreadID;
|
||||
LONG lWaveBuffersCommitted;
|
||||
volatile ALboolean killNow;
|
||||
HANDLE WaveThreadEvent;
|
||||
HANDLE WaveThread;
|
||||
DWORD WaveThreadID;
|
||||
volatile LONG WaveBuffersCommitted;
|
||||
WAVEHDR WaveBuffer[4];
|
||||
|
||||
union {
|
||||
HWAVEIN In;
|
||||
HWAVEOUT Out;
|
||||
} hWaveHandle;
|
||||
} WaveHandle;
|
||||
|
||||
ALuint Frequency;
|
||||
WAVEFORMATEX Format;
|
||||
|
||||
RingBuffer *pRing;
|
||||
RingBuffer *Ring;
|
||||
} WinMMData;
|
||||
|
||||
|
||||
static const ALCchar woDefault[] = "WaveOut Default";
|
||||
|
||||
static ALCchar **PlaybackDeviceList;
|
||||
static ALuint NumPlaybackDevices;
|
||||
static ALCchar **CaptureDeviceList;
|
||||
@@ -145,33 +147,16 @@ static void ProbeCaptureDevices(void)
|
||||
Posts a message to 'PlaybackThreadProc' everytime a WaveOut Buffer is completed and
|
||||
returns to the application (for more data)
|
||||
*/
|
||||
static void CALLBACK WaveOutProc(HWAVEOUT hDevice,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2)
|
||||
static void CALLBACK WaveOutProc(HWAVEOUT UNUSED(device), UINT msg, DWORD_PTR instance, DWORD_PTR param1, DWORD_PTR UNUSED(param2))
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)dwInstance;
|
||||
WinMMData *pData = pDevice->ExtraData;
|
||||
ALCdevice *Device = (ALCdevice*)instance;
|
||||
WinMMData *data = Device->ExtraData;
|
||||
|
||||
(void)hDevice;
|
||||
(void)dwParam2;
|
||||
|
||||
if(uMsg != WOM_DONE)
|
||||
if(msg != WOM_DONE)
|
||||
return;
|
||||
|
||||
// Decrement number of buffers in use
|
||||
InterlockedDecrement(&pData->lWaveBuffersCommitted);
|
||||
|
||||
if(pData->bWaveShutdown == AL_FALSE)
|
||||
{
|
||||
// Notify Wave Processor Thread that a Wave Header has returned
|
||||
PostThreadMessage(pData->ulWaveThreadID, uMsg, 0, dwParam1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pData->lWaveBuffersCommitted == 0)
|
||||
{
|
||||
// Post 'Quit' Message to WaveOut Processor Thread
|
||||
PostThreadMessage(pData->ulWaveThreadID, WM_QUIT, 0, 0);
|
||||
}
|
||||
}
|
||||
InterlockedDecrement(&data->WaveBuffersCommitted);
|
||||
PostThreadMessage(data->WaveThreadID, msg, 0, param1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -180,38 +165,44 @@ static void CALLBACK WaveOutProc(HWAVEOUT hDevice,UINT uMsg,DWORD_PTR dwInstance
|
||||
Used by "MMSYSTEM" Device. Called when a WaveOut buffer has used up its
|
||||
audio data.
|
||||
*/
|
||||
static DWORD WINAPI PlaybackThreadProc(LPVOID lpParameter)
|
||||
FORCE_ALIGN static DWORD WINAPI PlaybackThreadProc(LPVOID param)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)lpParameter;
|
||||
WinMMData *pData = pDevice->ExtraData;
|
||||
LPWAVEHDR pWaveHdr;
|
||||
ALCdevice *Device = (ALCdevice*)param;
|
||||
WinMMData *data = Device->ExtraData;
|
||||
LPWAVEHDR WaveHdr;
|
||||
ALuint FrameSize;
|
||||
MSG msg;
|
||||
|
||||
FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
|
||||
FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
|
||||
|
||||
SetRTPriority();
|
||||
SetThreadName(MIXER_THREAD_NAME);
|
||||
|
||||
while(GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
if(msg.message != WOM_DONE || pData->bWaveShutdown)
|
||||
if(msg.message != WOM_DONE)
|
||||
continue;
|
||||
|
||||
pWaveHdr = ((LPWAVEHDR)msg.lParam);
|
||||
if(data->killNow)
|
||||
{
|
||||
if(data->WaveBuffersCommitted == 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
aluMixData(pDevice, pWaveHdr->lpData, pWaveHdr->dwBufferLength/FrameSize);
|
||||
WaveHdr = ((LPWAVEHDR)msg.lParam);
|
||||
aluMixData(Device, WaveHdr->lpData, WaveHdr->dwBufferLength/FrameSize);
|
||||
|
||||
// Send buffer back to play more data
|
||||
waveOutWrite(pData->hWaveHandle.Out, pWaveHdr, sizeof(WAVEHDR));
|
||||
InterlockedIncrement(&pData->lWaveBuffersCommitted);
|
||||
waveOutWrite(data->WaveHandle.Out, WaveHdr, sizeof(WAVEHDR));
|
||||
InterlockedIncrement(&data->WaveBuffersCommitted);
|
||||
}
|
||||
|
||||
// Signal Wave Thread completed event
|
||||
if(pData->hWaveThreadEvent)
|
||||
SetEvent(pData->hWaveThreadEvent);
|
||||
if(data->WaveThreadEvent)
|
||||
SetEvent(data->WaveThreadEvent);
|
||||
|
||||
ExitThread(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -221,33 +212,16 @@ static DWORD WINAPI PlaybackThreadProc(LPVOID lpParameter)
|
||||
Posts a message to 'CaptureThreadProc' everytime a WaveIn Buffer is completed and
|
||||
returns to the application (with more data)
|
||||
*/
|
||||
static void CALLBACK WaveInProc(HWAVEIN hDevice,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2)
|
||||
static void CALLBACK WaveInProc(HWAVEIN UNUSED(device), UINT msg, DWORD_PTR instance, DWORD_PTR param1, DWORD_PTR UNUSED(param2))
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)dwInstance;
|
||||
WinMMData *pData = pDevice->ExtraData;
|
||||
ALCdevice *Device = (ALCdevice*)instance;
|
||||
WinMMData *data = Device->ExtraData;
|
||||
|
||||
(void)hDevice;
|
||||
(void)dwParam2;
|
||||
|
||||
if(uMsg != WIM_DATA)
|
||||
if(msg != WIM_DATA)
|
||||
return;
|
||||
|
||||
// Decrement number of buffers in use
|
||||
InterlockedDecrement(&pData->lWaveBuffersCommitted);
|
||||
|
||||
if(pData->bWaveShutdown == AL_FALSE)
|
||||
{
|
||||
// Notify Wave Processor Thread that a Wave Header has returned
|
||||
PostThreadMessage(pData->ulWaveThreadID,uMsg,0,dwParam1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pData->lWaveBuffersCommitted == 0)
|
||||
{
|
||||
// Post 'Quit' Message to WaveIn Processor Thread
|
||||
PostThreadMessage(pData->ulWaveThreadID,WM_QUIT,0,0);
|
||||
}
|
||||
}
|
||||
InterlockedDecrement(&data->WaveBuffersCommitted);
|
||||
PostThreadMessage(data->WaveThreadID, msg, 0, param1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -256,196 +230,223 @@ static void CALLBACK WaveInProc(HWAVEIN hDevice,UINT uMsg,DWORD_PTR dwInstance,D
|
||||
Used by "MMSYSTEM" Device. Called when a WaveIn buffer had been filled with new
|
||||
audio data.
|
||||
*/
|
||||
static DWORD WINAPI CaptureThreadProc(LPVOID lpParameter)
|
||||
static DWORD WINAPI CaptureThreadProc(LPVOID param)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)lpParameter;
|
||||
WinMMData *pData = pDevice->ExtraData;
|
||||
LPWAVEHDR pWaveHdr;
|
||||
ALCdevice *Device = (ALCdevice*)param;
|
||||
WinMMData *data = Device->ExtraData;
|
||||
LPWAVEHDR WaveHdr;
|
||||
ALuint FrameSize;
|
||||
MSG msg;
|
||||
|
||||
FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
|
||||
FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
|
||||
SetThreadName("alsoft-record");
|
||||
|
||||
while(GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
if(msg.message != WIM_DATA || pData->bWaveShutdown)
|
||||
if(msg.message != WIM_DATA)
|
||||
continue;
|
||||
/* Don't wait for other buffers to finish before quitting. We're
|
||||
* closing so we don't need them. */
|
||||
if(data->killNow)
|
||||
break;
|
||||
|
||||
pWaveHdr = ((LPWAVEHDR)msg.lParam);
|
||||
|
||||
WriteRingBuffer(pData->pRing, (ALubyte*)pWaveHdr->lpData,
|
||||
pWaveHdr->dwBytesRecorded/FrameSize);
|
||||
WaveHdr = ((LPWAVEHDR)msg.lParam);
|
||||
WriteRingBuffer(data->Ring, (ALubyte*)WaveHdr->lpData, WaveHdr->dwBytesRecorded/FrameSize);
|
||||
|
||||
// Send buffer back to capture more data
|
||||
waveInAddBuffer(pData->hWaveHandle.In,pWaveHdr,sizeof(WAVEHDR));
|
||||
InterlockedIncrement(&pData->lWaveBuffersCommitted);
|
||||
waveInAddBuffer(data->WaveHandle.In, WaveHdr, sizeof(WAVEHDR));
|
||||
InterlockedIncrement(&data->WaveBuffersCommitted);
|
||||
}
|
||||
|
||||
// Signal Wave Thread completed event
|
||||
if(pData->hWaveThreadEvent)
|
||||
SetEvent(pData->hWaveThreadEvent);
|
||||
if(data->WaveThreadEvent)
|
||||
SetEvent(data->WaveThreadEvent);
|
||||
|
||||
ExitThread(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static ALCenum WinMMOpenPlayback(ALCdevice *pDevice, const ALCchar *deviceName)
|
||||
static ALCenum WinMMOpenPlayback(ALCdevice *Device, const ALCchar *deviceName)
|
||||
{
|
||||
WAVEFORMATEX wfexFormat;
|
||||
WinMMData *pData = NULL;
|
||||
UINT lDeviceID = 0;
|
||||
WinMMData *data = NULL;
|
||||
UINT DeviceID = 0;
|
||||
MMRESULT res;
|
||||
ALuint i = 0;
|
||||
|
||||
if(!PlaybackDeviceList)
|
||||
ProbePlaybackDevices();
|
||||
|
||||
// Find the Device ID matching the deviceName if valid
|
||||
if(!deviceName || strcmp(deviceName, woDefault) == 0)
|
||||
lDeviceID = WAVE_MAPPER;
|
||||
for(i = 0;i < NumPlaybackDevices;i++)
|
||||
{
|
||||
if(PlaybackDeviceList[i] &&
|
||||
(!deviceName || strcmp(deviceName, PlaybackDeviceList[i]) == 0))
|
||||
{
|
||||
DeviceID = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == NumPlaybackDevices)
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
data = calloc(1, sizeof(*data));
|
||||
if(!data)
|
||||
return ALC_OUT_OF_MEMORY;
|
||||
Device->ExtraData = data;
|
||||
|
||||
retry_open:
|
||||
memset(&data->Format, 0, sizeof(WAVEFORMATEX));
|
||||
if(Device->FmtType == DevFmtFloat)
|
||||
{
|
||||
data->Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
data->Format.wBitsPerSample = 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!PlaybackDeviceList)
|
||||
ProbePlaybackDevices();
|
||||
data->Format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
if(Device->FmtType == DevFmtUByte || Device->FmtType == DevFmtByte)
|
||||
data->Format.wBitsPerSample = 8;
|
||||
else
|
||||
data->Format.wBitsPerSample = 16;
|
||||
}
|
||||
data->Format.nChannels = ((Device->FmtChans == DevFmtMono) ? 1 : 2);
|
||||
data->Format.nBlockAlign = data->Format.wBitsPerSample *
|
||||
data->Format.nChannels / 8;
|
||||
data->Format.nSamplesPerSec = Device->Frequency;
|
||||
data->Format.nAvgBytesPerSec = data->Format.nSamplesPerSec *
|
||||
data->Format.nBlockAlign;
|
||||
data->Format.cbSize = 0;
|
||||
|
||||
for(i = 0;i < NumPlaybackDevices;i++)
|
||||
if((res=waveOutOpen(&data->WaveHandle.Out, DeviceID, &data->Format, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)Device, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
|
||||
{
|
||||
if(Device->FmtType == DevFmtFloat)
|
||||
{
|
||||
if(PlaybackDeviceList[i] &&
|
||||
strcmp(deviceName, PlaybackDeviceList[i]) == 0)
|
||||
{
|
||||
lDeviceID = i;
|
||||
break;
|
||||
}
|
||||
Device->FmtType = DevFmtShort;
|
||||
goto retry_open;
|
||||
}
|
||||
if(i == NumPlaybackDevices)
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
pData = calloc(1, sizeof(*pData));
|
||||
if(!pData)
|
||||
return ALC_OUT_OF_MEMORY;
|
||||
pDevice->ExtraData = pData;
|
||||
|
||||
if(pDevice->FmtChans != DevFmtMono)
|
||||
{
|
||||
if((pDevice->Flags&DEVICE_CHANNELS_REQUEST) &&
|
||||
pDevice->FmtChans != DevFmtStereo)
|
||||
{
|
||||
ERR("Failed to set %s, got Stereo instead\n", DevFmtChannelsString(pDevice->FmtChans));
|
||||
pDevice->Flags &= ~DEVICE_CHANNELS_REQUEST;
|
||||
}
|
||||
pDevice->FmtChans = DevFmtStereo;
|
||||
}
|
||||
switch(pDevice->FmtType)
|
||||
{
|
||||
case DevFmtByte:
|
||||
pDevice->FmtType = DevFmtUByte;
|
||||
break;
|
||||
case DevFmtUShort:
|
||||
case DevFmtFloat:
|
||||
pDevice->FmtType = DevFmtShort;
|
||||
break;
|
||||
case DevFmtUByte:
|
||||
case DevFmtShort:
|
||||
break;
|
||||
}
|
||||
|
||||
memset(&wfexFormat, 0, sizeof(WAVEFORMATEX));
|
||||
wfexFormat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfexFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans);
|
||||
wfexFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8;
|
||||
wfexFormat.nBlockAlign = wfexFormat.wBitsPerSample *
|
||||
wfexFormat.nChannels / 8;
|
||||
wfexFormat.nSamplesPerSec = pDevice->Frequency;
|
||||
wfexFormat.nAvgBytesPerSec = wfexFormat.nSamplesPerSec *
|
||||
wfexFormat.nBlockAlign;
|
||||
wfexFormat.cbSize = 0;
|
||||
|
||||
if((res=waveOutOpen(&pData->hWaveHandle.Out, lDeviceID, &wfexFormat, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
|
||||
{
|
||||
ERR("waveOutOpen failed: %u\n", res);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
pData->hWaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if(pData->hWaveThreadEvent == NULL)
|
||||
data->WaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if(data->WaveThreadEvent == NULL)
|
||||
{
|
||||
ERR("CreateEvent failed: %lu\n", GetLastError());
|
||||
goto failure;
|
||||
}
|
||||
|
||||
pData->Frequency = pDevice->Frequency;
|
||||
|
||||
pDevice->szDeviceName = strdup((lDeviceID==WAVE_MAPPER) ? woDefault :
|
||||
PlaybackDeviceList[lDeviceID]);
|
||||
Device->DeviceName = strdup(PlaybackDeviceList[DeviceID]);
|
||||
return ALC_NO_ERROR;
|
||||
|
||||
failure:
|
||||
if(pData->hWaveThreadEvent)
|
||||
CloseHandle(pData->hWaveThreadEvent);
|
||||
if(data->WaveThreadEvent)
|
||||
CloseHandle(data->WaveThreadEvent);
|
||||
|
||||
if(pData->hWaveHandle.Out)
|
||||
waveOutClose(pData->hWaveHandle.Out);
|
||||
if(data->WaveHandle.Out)
|
||||
waveOutClose(data->WaveHandle.Out);
|
||||
|
||||
free(pData);
|
||||
pDevice->ExtraData = NULL;
|
||||
free(data);
|
||||
Device->ExtraData = NULL;
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
static void WinMMClosePlayback(ALCdevice *device)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)device->ExtraData;
|
||||
WinMMData *data = (WinMMData*)device->ExtraData;
|
||||
|
||||
// Close the Wave device
|
||||
CloseHandle(pData->hWaveThreadEvent);
|
||||
pData->hWaveThreadEvent = 0;
|
||||
CloseHandle(data->WaveThreadEvent);
|
||||
data->WaveThreadEvent = 0;
|
||||
|
||||
waveOutClose(pData->hWaveHandle.Out);
|
||||
pData->hWaveHandle.Out = 0;
|
||||
waveOutClose(data->WaveHandle.Out);
|
||||
data->WaveHandle.Out = 0;
|
||||
|
||||
free(pData);
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
}
|
||||
|
||||
static ALCboolean WinMMResetPlayback(ALCdevice *device)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)device->ExtraData;
|
||||
ALbyte *BufferData;
|
||||
ALint lBufferSize;
|
||||
ALuint i;
|
||||
|
||||
pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlaybackThreadProc, (LPVOID)device, 0, &pData->ulWaveThreadID);
|
||||
if(pData->hWaveThread == NULL)
|
||||
return ALC_FALSE;
|
||||
WinMMData *data = (WinMMData*)device->ExtraData;
|
||||
|
||||
device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
|
||||
pData->Frequency / device->Frequency);
|
||||
if(device->Frequency != pData->Frequency)
|
||||
data->Format.nSamplesPerSec /
|
||||
device->Frequency);
|
||||
device->UpdateSize = (device->UpdateSize*device->NumUpdates + 3) / 4;
|
||||
device->NumUpdates = 4;
|
||||
device->Frequency = data->Format.nSamplesPerSec;
|
||||
|
||||
if(data->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
|
||||
{
|
||||
if((device->Flags&DEVICE_FREQUENCY_REQUEST))
|
||||
ERR("WinMM does not support changing sample rates (wanted %dhz, got %dhz)\n", device->Frequency, pData->Frequency);
|
||||
device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
|
||||
device->Frequency = pData->Frequency;
|
||||
if(data->Format.wBitsPerSample == 32)
|
||||
device->FmtType = DevFmtFloat;
|
||||
else
|
||||
{
|
||||
ERR("Unhandled IEEE float sample depth: %d\n", data->Format.wBitsPerSample);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
}
|
||||
else if(data->Format.wFormatTag == WAVE_FORMAT_PCM)
|
||||
{
|
||||
if(data->Format.wBitsPerSample == 16)
|
||||
device->FmtType = DevFmtShort;
|
||||
else if(data->Format.wBitsPerSample == 8)
|
||||
device->FmtType = DevFmtUByte;
|
||||
else
|
||||
{
|
||||
ERR("Unhandled PCM sample depth: %d\n", data->Format.wBitsPerSample);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("Unhandled format tag: 0x%04x\n", data->Format.wFormatTag);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
if(data->Format.nChannels == 2)
|
||||
device->FmtChans = DevFmtStereo;
|
||||
else if(data->Format.nChannels == 1)
|
||||
device->FmtChans = DevFmtMono;
|
||||
else
|
||||
{
|
||||
ERR("Unhandled channel count: %d\n", data->Format.nChannels);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
SetDefaultWFXChannelOrder(device);
|
||||
|
||||
pData->lWaveBuffersCommitted = 0;
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static ALCboolean WinMMStartPlayback(ALCdevice *device)
|
||||
{
|
||||
WinMMData *data = (WinMMData*)device->ExtraData;
|
||||
ALbyte *BufferData;
|
||||
ALint BufferSize;
|
||||
ALuint i;
|
||||
|
||||
data->WaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlaybackThreadProc, (LPVOID)device, 0, &data->WaveThreadID);
|
||||
if(data->WaveThread == NULL)
|
||||
return ALC_FALSE;
|
||||
|
||||
data->WaveBuffersCommitted = 0;
|
||||
|
||||
// Create 4 Buffers
|
||||
lBufferSize = device->UpdateSize*device->NumUpdates / 4;
|
||||
lBufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||
BufferSize = device->UpdateSize*device->NumUpdates / 4;
|
||||
BufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||
|
||||
BufferData = calloc(4, lBufferSize);
|
||||
BufferData = calloc(4, BufferSize);
|
||||
for(i = 0;i < 4;i++)
|
||||
{
|
||||
memset(&pData->WaveBuffer[i], 0, sizeof(WAVEHDR));
|
||||
pData->WaveBuffer[i].dwBufferLength = lBufferSize;
|
||||
pData->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
|
||||
(pData->WaveBuffer[i-1].lpData +
|
||||
pData->WaveBuffer[i-1].dwBufferLength));
|
||||
waveOutPrepareHeader(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
waveOutWrite(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
InterlockedIncrement(&pData->lWaveBuffersCommitted);
|
||||
memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR));
|
||||
data->WaveBuffer[i].dwBufferLength = BufferSize;
|
||||
data->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
|
||||
(data->WaveBuffer[i-1].lpData +
|
||||
data->WaveBuffer[i-1].dwBufferLength));
|
||||
waveOutPrepareHeader(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
waveOutWrite(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
InterlockedIncrement(&data->WaveBuffersCommitted);
|
||||
}
|
||||
|
||||
return ALC_TRUE;
|
||||
@@ -453,43 +454,42 @@ static ALCboolean WinMMResetPlayback(ALCdevice *device)
|
||||
|
||||
static void WinMMStopPlayback(ALCdevice *device)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)device->ExtraData;
|
||||
WinMMData *data = (WinMMData*)device->ExtraData;
|
||||
void *buffer = NULL;
|
||||
int i;
|
||||
|
||||
if(pData->hWaveThread == NULL)
|
||||
if(data->WaveThread == NULL)
|
||||
return;
|
||||
|
||||
// Set flag to stop processing headers
|
||||
pData->bWaveShutdown = AL_TRUE;
|
||||
data->killNow = AL_TRUE;
|
||||
|
||||
// Wait for signal that Wave Thread has been destroyed
|
||||
WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE);
|
||||
WaitForSingleObjectEx(data->WaveThreadEvent, 5000, FALSE);
|
||||
|
||||
CloseHandle(pData->hWaveThread);
|
||||
pData->hWaveThread = 0;
|
||||
CloseHandle(data->WaveThread);
|
||||
data->WaveThread = 0;
|
||||
|
||||
pData->bWaveShutdown = AL_FALSE;
|
||||
data->killNow = AL_FALSE;
|
||||
|
||||
// Release the wave buffers
|
||||
for(i = 0;i < 4;i++)
|
||||
{
|
||||
waveOutUnprepareHeader(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
if(i == 0) buffer = pData->WaveBuffer[i].lpData;
|
||||
pData->WaveBuffer[i].lpData = NULL;
|
||||
waveOutUnprepareHeader(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
if(i == 0) buffer = data->WaveBuffer[i].lpData;
|
||||
data->WaveBuffer[i].lpData = NULL;
|
||||
}
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
||||
static ALCenum WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
|
||||
static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName)
|
||||
{
|
||||
WAVEFORMATEX wfexCaptureFormat;
|
||||
ALbyte *BufferData = NULL;
|
||||
DWORD ulCapturedDataSize;
|
||||
WinMMData *pData = NULL;
|
||||
UINT lDeviceID = 0;
|
||||
ALint lBufferSize;
|
||||
DWORD CapturedDataSize;
|
||||
WinMMData *data = NULL;
|
||||
UINT DeviceID = 0;
|
||||
ALint BufferSize;
|
||||
MMRESULT res;
|
||||
ALuint i;
|
||||
|
||||
@@ -497,196 +497,207 @@ static ALCenum WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
|
||||
ProbeCaptureDevices();
|
||||
|
||||
// Find the Device ID matching the deviceName if valid
|
||||
if(deviceName)
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
{
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
if(CaptureDeviceList[i] &&
|
||||
(!deviceName || strcmp(deviceName, CaptureDeviceList[i]) == 0))
|
||||
{
|
||||
if(CaptureDeviceList[i] &&
|
||||
strcmp(deviceName, CaptureDeviceList[i]) == 0)
|
||||
{
|
||||
lDeviceID = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
{
|
||||
if(CaptureDeviceList[i])
|
||||
{
|
||||
lDeviceID = i;
|
||||
break;
|
||||
}
|
||||
DeviceID = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == NumCaptureDevices)
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
pData = calloc(1, sizeof(*pData));
|
||||
if(!pData)
|
||||
switch(Device->FmtChans)
|
||||
{
|
||||
case DevFmtMono:
|
||||
case DevFmtStereo:
|
||||
break;
|
||||
|
||||
case DevFmtQuad:
|
||||
case DevFmtX51:
|
||||
case DevFmtX51Side:
|
||||
case DevFmtX61:
|
||||
case DevFmtX71:
|
||||
return ALC_INVALID_ENUM;
|
||||
}
|
||||
|
||||
switch(Device->FmtType)
|
||||
{
|
||||
case DevFmtUByte:
|
||||
case DevFmtShort:
|
||||
case DevFmtInt:
|
||||
case DevFmtFloat:
|
||||
break;
|
||||
|
||||
case DevFmtByte:
|
||||
case DevFmtUShort:
|
||||
case DevFmtUInt:
|
||||
return ALC_INVALID_ENUM;
|
||||
}
|
||||
|
||||
data = calloc(1, sizeof(*data));
|
||||
if(!data)
|
||||
return ALC_OUT_OF_MEMORY;
|
||||
pDevice->ExtraData = pData;
|
||||
Device->ExtraData = data;
|
||||
|
||||
if((pDevice->FmtChans != DevFmtMono && pDevice->FmtChans != DevFmtStereo) ||
|
||||
(pDevice->FmtType != DevFmtUByte && pDevice->FmtType != DevFmtShort))
|
||||
goto failure;
|
||||
memset(&data->Format, 0, sizeof(WAVEFORMATEX));
|
||||
data->Format.wFormatTag = ((Device->FmtType == DevFmtFloat) ?
|
||||
WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM);
|
||||
data->Format.nChannels = ChannelsFromDevFmt(Device->FmtChans);
|
||||
data->Format.wBitsPerSample = BytesFromDevFmt(Device->FmtType) * 8;
|
||||
data->Format.nBlockAlign = data->Format.wBitsPerSample *
|
||||
data->Format.nChannels / 8;
|
||||
data->Format.nSamplesPerSec = Device->Frequency;
|
||||
data->Format.nAvgBytesPerSec = data->Format.nSamplesPerSec *
|
||||
data->Format.nBlockAlign;
|
||||
data->Format.cbSize = 0;
|
||||
|
||||
memset(&wfexCaptureFormat, 0, sizeof(WAVEFORMATEX));
|
||||
wfexCaptureFormat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfexCaptureFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans);
|
||||
wfexCaptureFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8;
|
||||
wfexCaptureFormat.nBlockAlign = wfexCaptureFormat.wBitsPerSample *
|
||||
wfexCaptureFormat.nChannels / 8;
|
||||
wfexCaptureFormat.nSamplesPerSec = pDevice->Frequency;
|
||||
wfexCaptureFormat.nAvgBytesPerSec = wfexCaptureFormat.nSamplesPerSec *
|
||||
wfexCaptureFormat.nBlockAlign;
|
||||
wfexCaptureFormat.cbSize = 0;
|
||||
|
||||
if((res=waveInOpen(&pData->hWaveHandle.In, lDeviceID, &wfexCaptureFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
|
||||
if((res=waveInOpen(&data->WaveHandle.In, DeviceID, &data->Format, (DWORD_PTR)&WaveInProc, (DWORD_PTR)Device, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
|
||||
{
|
||||
ERR("waveInOpen failed: %u\n", res);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
pData->hWaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if(pData->hWaveThreadEvent == NULL)
|
||||
data->WaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if(data->WaveThreadEvent == NULL)
|
||||
{
|
||||
ERR("CreateEvent failed: %lu\n", GetLastError());
|
||||
goto failure;
|
||||
}
|
||||
|
||||
pData->Frequency = pDevice->Frequency;
|
||||
|
||||
// Allocate circular memory buffer for the captured audio
|
||||
ulCapturedDataSize = pDevice->UpdateSize*pDevice->NumUpdates;
|
||||
CapturedDataSize = Device->UpdateSize*Device->NumUpdates;
|
||||
|
||||
// Make sure circular buffer is at least 100ms in size
|
||||
if(ulCapturedDataSize < (wfexCaptureFormat.nSamplesPerSec / 10))
|
||||
ulCapturedDataSize = wfexCaptureFormat.nSamplesPerSec / 10;
|
||||
if(CapturedDataSize < (data->Format.nSamplesPerSec / 10))
|
||||
CapturedDataSize = data->Format.nSamplesPerSec / 10;
|
||||
|
||||
pData->pRing = CreateRingBuffer(wfexCaptureFormat.nBlockAlign, ulCapturedDataSize);
|
||||
if(!pData->pRing)
|
||||
data->Ring = CreateRingBuffer(data->Format.nBlockAlign, CapturedDataSize);
|
||||
if(!data->Ring)
|
||||
goto failure;
|
||||
|
||||
pData->lWaveBuffersCommitted = 0;
|
||||
data->WaveBuffersCommitted = 0;
|
||||
|
||||
// Create 4 Buffers of 50ms each
|
||||
lBufferSize = wfexCaptureFormat.nAvgBytesPerSec / 20;
|
||||
lBufferSize -= (lBufferSize % wfexCaptureFormat.nBlockAlign);
|
||||
BufferSize = data->Format.nAvgBytesPerSec / 20;
|
||||
BufferSize -= (BufferSize % data->Format.nBlockAlign);
|
||||
|
||||
BufferData = calloc(4, lBufferSize);
|
||||
BufferData = calloc(4, BufferSize);
|
||||
if(!BufferData)
|
||||
goto failure;
|
||||
|
||||
for(i = 0;i < 4;i++)
|
||||
{
|
||||
memset(&pData->WaveBuffer[i], 0, sizeof(WAVEHDR));
|
||||
pData->WaveBuffer[i].dwBufferLength = lBufferSize;
|
||||
pData->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
|
||||
(pData->WaveBuffer[i-1].lpData +
|
||||
pData->WaveBuffer[i-1].dwBufferLength));
|
||||
pData->WaveBuffer[i].dwFlags = 0;
|
||||
pData->WaveBuffer[i].dwLoops = 0;
|
||||
waveInPrepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
waveInAddBuffer(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
InterlockedIncrement(&pData->lWaveBuffersCommitted);
|
||||
memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR));
|
||||
data->WaveBuffer[i].dwBufferLength = BufferSize;
|
||||
data->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
|
||||
(data->WaveBuffer[i-1].lpData +
|
||||
data->WaveBuffer[i-1].dwBufferLength));
|
||||
data->WaveBuffer[i].dwFlags = 0;
|
||||
data->WaveBuffer[i].dwLoops = 0;
|
||||
waveInPrepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
waveInAddBuffer(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
InterlockedIncrement(&data->WaveBuffersCommitted);
|
||||
}
|
||||
|
||||
pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)pDevice, 0, &pData->ulWaveThreadID);
|
||||
if (pData->hWaveThread == NULL)
|
||||
data->WaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)Device, 0, &data->WaveThreadID);
|
||||
if (data->WaveThread == NULL)
|
||||
goto failure;
|
||||
|
||||
pDevice->szDeviceName = strdup(CaptureDeviceList[lDeviceID]);
|
||||
Device->DeviceName = strdup(CaptureDeviceList[DeviceID]);
|
||||
return ALC_NO_ERROR;
|
||||
|
||||
failure:
|
||||
if(pData->hWaveThread)
|
||||
CloseHandle(pData->hWaveThread);
|
||||
if(data->WaveThread)
|
||||
CloseHandle(data->WaveThread);
|
||||
|
||||
if(BufferData)
|
||||
{
|
||||
for(i = 0;i < 4;i++)
|
||||
waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
waveInUnprepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
free(BufferData);
|
||||
}
|
||||
|
||||
if(pData->pRing)
|
||||
DestroyRingBuffer(pData->pRing);
|
||||
if(data->Ring)
|
||||
DestroyRingBuffer(data->Ring);
|
||||
|
||||
if(pData->hWaveThreadEvent)
|
||||
CloseHandle(pData->hWaveThreadEvent);
|
||||
if(data->WaveThreadEvent)
|
||||
CloseHandle(data->WaveThreadEvent);
|
||||
|
||||
if(pData->hWaveHandle.In)
|
||||
waveInClose(pData->hWaveHandle.In);
|
||||
if(data->WaveHandle.In)
|
||||
waveInClose(data->WaveHandle.In);
|
||||
|
||||
free(pData);
|
||||
pDevice->ExtraData = NULL;
|
||||
free(data);
|
||||
Device->ExtraData = NULL;
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
static void WinMMCloseCapture(ALCdevice *pDevice)
|
||||
static void WinMMCloseCapture(ALCdevice *Device)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
WinMMData *data = (WinMMData*)Device->ExtraData;
|
||||
void *buffer = NULL;
|
||||
int i;
|
||||
|
||||
// Call waveOutReset to shutdown wave device
|
||||
pData->bWaveShutdown = AL_TRUE;
|
||||
waveInReset(pData->hWaveHandle.In);
|
||||
/* Tell the processing thread to quit and wait for it to do so. */
|
||||
data->killNow = AL_TRUE;
|
||||
PostThreadMessage(data->WaveThreadID, WM_QUIT, 0, 0);
|
||||
|
||||
// Wait for signal that Wave Thread has been destroyed
|
||||
WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE);
|
||||
WaitForSingleObjectEx(data->WaveThreadEvent, 5000, FALSE);
|
||||
|
||||
CloseHandle(pData->hWaveThread);
|
||||
pData->hWaveThread = 0;
|
||||
/* Make sure capture is stopped and all pending buffers are flushed. */
|
||||
waveInReset(data->WaveHandle.In);
|
||||
|
||||
CloseHandle(data->WaveThread);
|
||||
data->WaveThread = 0;
|
||||
|
||||
// Release the wave buffers
|
||||
for(i = 0;i < 4;i++)
|
||||
{
|
||||
waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
if(i == 0) buffer = pData->WaveBuffer[i].lpData;
|
||||
pData->WaveBuffer[i].lpData = NULL;
|
||||
waveInUnprepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
if(i == 0) buffer = data->WaveBuffer[i].lpData;
|
||||
data->WaveBuffer[i].lpData = NULL;
|
||||
}
|
||||
free(buffer);
|
||||
|
||||
DestroyRingBuffer(pData->pRing);
|
||||
pData->pRing = NULL;
|
||||
DestroyRingBuffer(data->Ring);
|
||||
data->Ring = NULL;
|
||||
|
||||
// Close the Wave device
|
||||
CloseHandle(pData->hWaveThreadEvent);
|
||||
pData->hWaveThreadEvent = 0;
|
||||
CloseHandle(data->WaveThreadEvent);
|
||||
data->WaveThreadEvent = 0;
|
||||
|
||||
waveInClose(pData->hWaveHandle.In);
|
||||
pData->hWaveHandle.In = 0;
|
||||
waveInClose(data->WaveHandle.In);
|
||||
data->WaveHandle.In = 0;
|
||||
|
||||
free(pData);
|
||||
pDevice->ExtraData = NULL;
|
||||
free(data);
|
||||
Device->ExtraData = NULL;
|
||||
}
|
||||
|
||||
static void WinMMStartCapture(ALCdevice *pDevice)
|
||||
static void WinMMStartCapture(ALCdevice *Device)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
waveInStart(pData->hWaveHandle.In);
|
||||
WinMMData *data = (WinMMData*)Device->ExtraData;
|
||||
waveInStart(data->WaveHandle.In);
|
||||
}
|
||||
|
||||
static void WinMMStopCapture(ALCdevice *pDevice)
|
||||
static void WinMMStopCapture(ALCdevice *Device)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
waveInStop(pData->hWaveHandle.In);
|
||||
WinMMData *data = (WinMMData*)Device->ExtraData;
|
||||
waveInStop(data->WaveHandle.In);
|
||||
}
|
||||
|
||||
static ALCenum WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
|
||||
static ALCenum WinMMCaptureSamples(ALCdevice *Device, ALCvoid *Buffer, ALCuint Samples)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
ReadRingBuffer(pData->pRing, pBuffer, lSamples);
|
||||
WinMMData *data = (WinMMData*)Device->ExtraData;
|
||||
ReadRingBuffer(data->Ring, Buffer, Samples);
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static ALCuint WinMMAvailableSamples(ALCdevice *pDevice)
|
||||
static ALCuint WinMMAvailableSamples(ALCdevice *Device)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
return RingBufferSize(pData->pRing);
|
||||
WinMMData *data = (WinMMData*)Device->ExtraData;
|
||||
return RingBufferSize(data->Ring);
|
||||
}
|
||||
|
||||
|
||||
@@ -694,13 +705,15 @@ static const BackendFuncs WinMMFuncs = {
|
||||
WinMMOpenPlayback,
|
||||
WinMMClosePlayback,
|
||||
WinMMResetPlayback,
|
||||
WinMMStartPlayback,
|
||||
WinMMStopPlayback,
|
||||
WinMMOpenCapture,
|
||||
WinMMCloseCapture,
|
||||
WinMMStartCapture,
|
||||
WinMMStopCapture,
|
||||
WinMMCaptureSamples,
|
||||
WinMMAvailableSamples
|
||||
WinMMAvailableSamples,
|
||||
ALCdevice_GetLatencyDefault
|
||||
};
|
||||
|
||||
ALCboolean alcWinMMInit(BackendFuncs *FuncList)
|
||||
@@ -711,18 +724,18 @@ ALCboolean alcWinMMInit(BackendFuncs *FuncList)
|
||||
|
||||
void alcWinMMDeinit()
|
||||
{
|
||||
ALuint lLoop;
|
||||
ALuint i;
|
||||
|
||||
for(lLoop = 0;lLoop < NumPlaybackDevices;lLoop++)
|
||||
free(PlaybackDeviceList[lLoop]);
|
||||
for(i = 0;i < NumPlaybackDevices;i++)
|
||||
free(PlaybackDeviceList[i]);
|
||||
free(PlaybackDeviceList);
|
||||
PlaybackDeviceList = NULL;
|
||||
|
||||
NumPlaybackDevices = 0;
|
||||
|
||||
|
||||
for(lLoop = 0; lLoop < NumCaptureDevices; lLoop++)
|
||||
free(CaptureDeviceList[lLoop]);
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
free(CaptureDeviceList[i]);
|
||||
free(CaptureDeviceList);
|
||||
CaptureDeviceList = NULL;
|
||||
|
||||
@@ -735,20 +748,12 @@ void alcWinMMProbe(enum DevProbe type)
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case DEVICE_PROBE:
|
||||
ProbePlaybackDevices();
|
||||
if(NumPlaybackDevices > 0)
|
||||
AppendDeviceList(woDefault);
|
||||
break;
|
||||
|
||||
case ALL_DEVICE_PROBE:
|
||||
ProbePlaybackDevices();
|
||||
if(NumPlaybackDevices > 0)
|
||||
AppendAllDeviceList(woDefault);
|
||||
for(i = 0;i < NumPlaybackDevices;i++)
|
||||
{
|
||||
if(PlaybackDeviceList[i])
|
||||
AppendAllDeviceList(PlaybackDeviceList[i]);
|
||||
AppendAllDevicesList(PlaybackDeviceList[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user