mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 08:44:04 +02:00
WASAPI: Add support for integer PCM formats.
This commit is contained in:
@@ -287,6 +287,7 @@ typedef int mal_result;
|
|||||||
#define MAL_WASAPI_FAILED_TO_CREATE_DEVICE -3073
|
#define MAL_WASAPI_FAILED_TO_CREATE_DEVICE -3073
|
||||||
#define MAL_WASAPI_FAILED_TO_ACTIVATE_DEVICE -3074
|
#define MAL_WASAPI_FAILED_TO_ACTIVATE_DEVICE -3074
|
||||||
#define MAL_WASAPI_FAILED_TO_INITIALIZE_DEVICE -3075
|
#define MAL_WASAPI_FAILED_TO_INITIALIZE_DEVICE -3075
|
||||||
|
#define MAL_WASAPI_FAILED_TO_FIND_BEST_FORMAT -3076
|
||||||
|
|
||||||
typedef struct mal_device mal_device;
|
typedef struct mal_device mal_device;
|
||||||
|
|
||||||
@@ -2104,6 +2105,48 @@ static void mal_device_uninit__wasapi(mal_device* pDevice)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mal_result mal_device__find_best_format__wasapi(mal_device* pDevice, WAVEFORMATEXTENSIBLE* pBestFormat)
|
||||||
|
{
|
||||||
|
mal_assert(pDevice != NULL);
|
||||||
|
mal_assert(pBestFormat != NULL);
|
||||||
|
|
||||||
|
WAVEFORMATEXTENSIBLE wf;
|
||||||
|
mal_zero_object(&wf);
|
||||||
|
wf.Format.cbSize = sizeof(wf);
|
||||||
|
wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||||
|
wf.Format.nChannels = (WORD)pDevice->channels;
|
||||||
|
wf.Format.nSamplesPerSec = (DWORD)pDevice->sampleRate;
|
||||||
|
wf.Format.wBitsPerSample = (WORD)mal_get_sample_size_in_bytes(pDevice->format)*8;
|
||||||
|
wf.Format.nBlockAlign = (wf.Format.nChannels * wf.Format.wBitsPerSample) / 8;
|
||||||
|
wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
|
||||||
|
wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample;
|
||||||
|
wf.dwChannelMask = ~(((DWORD)-1) << pDevice->channels);
|
||||||
|
if (pDevice->format == mal_format_f32) {
|
||||||
|
wf.SubFormat = MAL_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
||||||
|
} else {
|
||||||
|
wf.SubFormat = MAL_GUID_KSDATAFORMAT_SUBTYPE_PCM;
|
||||||
|
}
|
||||||
|
|
||||||
|
WAVEFORMATEXTENSIBLE* pBestFormatTemp;
|
||||||
|
#ifdef __cplusplus
|
||||||
|
HRESULT hr = ((IAudioClient*)pDevice->wasapi.pAudioClient)->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*)&wf, (WAVEFORMATEX**)&pBestFormatTemp);
|
||||||
|
#else
|
||||||
|
HRESULT hr = ((IAudioClient*)pDevice->wasapi.pAudioClient)->lpVtbl->IsFormatSupported((IAudioClient*)pDevice->wasapi.pAudioClient, AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*)&wf, (WAVEFORMATEX**)&pBestFormatTemp);
|
||||||
|
#endif
|
||||||
|
if (hr != S_OK && hr != S_FALSE && hr != AUDCLNT_E_UNSUPPORTED_FORMAT) {
|
||||||
|
return MAL_WASAPI_FAILED_TO_FIND_BEST_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pBestFormatTemp != NULL) {
|
||||||
|
mal_copy_memory(pBestFormat, pBestFormatTemp, sizeof(*pBestFormat));
|
||||||
|
((MAL_PFN_CoTaskMemFree)pDevice->pContext->win32.CoTaskMemFree)(pBestFormatTemp);
|
||||||
|
} else {
|
||||||
|
mal_copy_memory(pBestFormat, &wf, sizeof(*pBestFormat));
|
||||||
|
}
|
||||||
|
|
||||||
|
return MAL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static mal_result mal_device_init__wasapi(mal_context* pContext, mal_device_type type, mal_device_id* pDeviceID, mal_device_config* pConfig, mal_device* pDevice)
|
static mal_result mal_device_init__wasapi(mal_context* pContext, mal_device_type type, mal_device_id* pDeviceID, mal_device_config* pConfig, mal_device* pDevice)
|
||||||
{
|
{
|
||||||
(void)pContext;
|
(void)pContext;
|
||||||
@@ -2169,44 +2212,31 @@ static mal_result mal_device_init__wasapi(mal_context* pContext, mal_device_type
|
|||||||
REFERENCE_TIME bufferDurationInMicroseconds = ((mal_uint64)pConfig->bufferSizeInFrames * 1000 * 1000) / pConfig->sampleRate;
|
REFERENCE_TIME bufferDurationInMicroseconds = ((mal_uint64)pConfig->bufferSizeInFrames * 1000 * 1000) / pConfig->sampleRate;
|
||||||
|
|
||||||
WAVEFORMATEXTENSIBLE wf;
|
WAVEFORMATEXTENSIBLE wf;
|
||||||
mal_zero_object(&wf);
|
mal_result result = mal_device__find_best_format__wasapi(pDevice, &wf);
|
||||||
wf.Format.cbSize = sizeof(wf);
|
if (result != MAL_SUCCESS) {
|
||||||
wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
|
||||||
wf.Format.nChannels = (WORD)pConfig->channels;
|
|
||||||
wf.Format.nSamplesPerSec = (DWORD)pConfig->sampleRate;
|
|
||||||
wf.Format.wBitsPerSample = (WORD)mal_get_sample_size_in_bytes(pConfig->format)*8;
|
|
||||||
wf.Format.nBlockAlign = (wf.Format.nChannels * wf.Format.wBitsPerSample) / 8;
|
|
||||||
wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
|
|
||||||
wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample;
|
|
||||||
wf.dwChannelMask = (pConfig->channels <= 2) ? 0 : ~(((DWORD)-1) << pConfig->channels);
|
|
||||||
wf.SubFormat = MAL_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
|
||||||
|
|
||||||
WAVEFORMATEXTENSIBLE* pClosestWF;
|
|
||||||
#if 0
|
|
||||||
#ifdef __cplusplus
|
|
||||||
hr = ((IAudioClient*)pDevice->wasapi.pAudioClient)->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*)&wf, (WAVEFORMATEX**)&pClosestWF);
|
|
||||||
#else
|
|
||||||
hr = ((IAudioClient*)pDevice->wasapi.pAudioClient)->lpVtbl->IsFormatSupported((IAudioClient*)pDevice->wasapi.pAudioClient, AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*)&wf, (WAVEFORMATEX**)&pClosestWF);
|
|
||||||
#endif
|
|
||||||
if (hr != S_OK && hr != S_FALSE) {
|
|
||||||
mal_device_uninit__wasapi(pDevice);
|
mal_device_uninit__wasapi(pDevice);
|
||||||
return mal_post_error(pDevice, "[WASAPI] Failed to get device mix format.", MAL_WASAPI_FAILED_TO_ACTIVATE_DEVICE);
|
return mal_post_error(pDevice, "[WASAPI] Failed to find best device mix format.", MAL_WASAPI_FAILED_TO_ACTIVATE_DEVICE);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#ifdef __cplusplus
|
|
||||||
hr = ((IAudioClient*)pDevice->wasapi.pAudioClient)->GetMixFormat((WAVEFORMATEX**)&pClosestWF);
|
|
||||||
#else
|
|
||||||
hr = ((IAudioClient*)pDevice->wasapi.pAudioClient)->lpVtbl->GetMixFormat((IAudioClient*)pDevice->wasapi.pAudioClient, (WAVEFORMATEX**)&pClosestWF);
|
|
||||||
#endif
|
|
||||||
if (hr != S_OK && hr != S_FALSE) {
|
|
||||||
mal_device_uninit__wasapi(pDevice);
|
|
||||||
return mal_post_error(pDevice, "[WASAPI] Failed to get device mix format.", MAL_WASAPI_FAILED_TO_ACTIVATE_DEVICE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//if (hr != S_OK) {
|
if (IsEqualGUID(&wf.SubFormat, &MAL_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
|
||||||
mal_copy_memory(&wf, pClosestWF, sizeof(wf));
|
pDevice->internalFormat = mal_format_f32;
|
||||||
//}
|
} else {
|
||||||
|
if (wf.Format.wBitsPerSample == 32) {
|
||||||
|
pDevice->internalFormat = mal_format_s32;
|
||||||
|
} else if (wf.Format.wBitsPerSample == 24) {
|
||||||
|
pDevice->internalFormat = mal_format_s24;
|
||||||
|
} else if (wf.Format.wBitsPerSample == 16) {
|
||||||
|
pDevice->internalFormat = mal_format_s16;
|
||||||
|
} else if (wf.Format.wBitsPerSample == 8) {
|
||||||
|
pDevice->internalFormat = mal_format_u8;
|
||||||
|
} else {
|
||||||
|
mal_device_uninit__wasapi(pDevice);
|
||||||
|
return mal_post_error(pDevice, "[WASAPI] Device's native format is not supported.", MAL_FORMAT_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pDevice->internalChannels = wf.Format.nChannels;
|
||||||
|
//pDevice->internalSampleRate = wf.Format.nSamplesPerSec; // TODO: Uncomment this when SRC is implemented.
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
hr = ((IAudioClient*)pDevice->wasapi.pAudioClient)->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, bufferDurationInMicroseconds*10, 0, (WAVEFORMATEX*)&wf, NULL);
|
hr = ((IAudioClient*)pDevice->wasapi.pAudioClient)->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, bufferDurationInMicroseconds*10, 0, (WAVEFORMATEX*)&wf, NULL);
|
||||||
@@ -2214,13 +2244,10 @@ static mal_result mal_device_init__wasapi(mal_context* pContext, mal_device_type
|
|||||||
hr = ((IAudioClient*)pDevice->wasapi.pAudioClient)->lpVtbl->Initialize((IAudioClient*)pDevice->wasapi.pAudioClient, AUDCLNT_SHAREMODE_SHARED, 0, bufferDurationInMicroseconds*10, 0, (WAVEFORMATEX*)&wf, NULL);
|
hr = ((IAudioClient*)pDevice->wasapi.pAudioClient)->lpVtbl->Initialize((IAudioClient*)pDevice->wasapi.pAudioClient, AUDCLNT_SHAREMODE_SHARED, 0, bufferDurationInMicroseconds*10, 0, (WAVEFORMATEX*)&wf, NULL);
|
||||||
#endif
|
#endif
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
((MAL_PFN_CoTaskMemFree)pContext->win32.CoTaskMemFree)(pClosestWF);
|
|
||||||
mal_device_uninit__wasapi(pDevice);
|
mal_device_uninit__wasapi(pDevice);
|
||||||
return mal_post_error(pDevice, "[WASAPI] Failed to activate device.", MAL_WASAPI_FAILED_TO_INITIALIZE_DEVICE);
|
return mal_post_error(pDevice, "[WASAPI] Failed to activate device.", MAL_WASAPI_FAILED_TO_INITIALIZE_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
((MAL_PFN_CoTaskMemFree)pContext->win32.CoTaskMemFree)(pClosestWF);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
hr = ((IAudioClient*)pDevice->wasapi.pAudioClient)->GetBufferSize(&pDevice->bufferSizeInFrames);
|
hr = ((IAudioClient*)pDevice->wasapi.pAudioClient)->GetBufferSize(&pDevice->bufferSizeInFrames);
|
||||||
#else
|
#else
|
||||||
@@ -6031,10 +6058,7 @@ void mal_pcm_f32_to_s32(int* pOut, const float* pIn, unsigned int count)
|
|||||||
//
|
//
|
||||||
// WASAPI
|
// WASAPI
|
||||||
// ------
|
// ------
|
||||||
// - Add support for non-f32 formats.
|
|
||||||
// - Add support for exclusive mode?
|
// - Add support for exclusive mode?
|
||||||
// - GetMixFormat() instead of IsFormatSupported().
|
|
||||||
// - Requires a large suite of conversion routines including channel shuffling, SRC and format conversion.
|
|
||||||
// - Look into event callbacks: AUDCLNT_STREAMFLAGS_EVENTCALLBACK
|
// - Look into event callbacks: AUDCLNT_STREAMFLAGS_EVENTCALLBACK
|
||||||
// - Clean up that terrible "__cplusplus" mess by implementing wrapper functions.
|
// - Clean up that terrible "__cplusplus" mess by implementing wrapper functions.
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user