diff --git a/OpenDialog/windows.c b/OpenDialog/windows.c index e940804..5a0af0e 100644 --- a/OpenDialog/windows.c +++ b/OpenDialog/windows.c @@ -1,5 +1,6 @@ #include #include +#include #include "open_dialog.h" static char *wc_to_utf8_alloc(const wchar_t *wide) @@ -66,23 +67,18 @@ char *do_save_recording_dialog(unsigned frequency) { OPENFILENAMEW dialog; wchar_t filename[MAX_PATH + 5] = L"recording.wav"; + static wchar_t filter[] = L"RIFF WAVE\0*.wav\0Apple AIFF\0*.aiff;*.aif;*.aifc\0Raw PCM (Stereo _______Hz, 16-bit LE)\0*.raw;*.pcm;\0All files\0*.*\0\0"; memset(&dialog, 0, sizeof(dialog)); dialog.lStructSize = sizeof(dialog); dialog.lpstrFile = filename; dialog.nMaxFile = MAX_PATH; - switch (frequency) { - case 96000: - dialog.lpstrFilter = L"RIFF WAVE\0*.wav\0Apple AIFF\0*.aiff;*.aif;*.aifc\0Raw PCM (Stereo 96000Hz, 16-bit LE)\0*.raw;*.pcm;\0All files\0*.*\0\0"; - break; - case 48000: - dialog.lpstrFilter = L"RIFF WAVE\0*.wav\0Apple AIFF\0*.aiff;*.aif;*.aifc\0Raw PCM (Stereo 48000Hz, 16-bit LE)\0*.raw;*.pcm;\0All files\0*.*\0\0"; - break; - case 44100: - default: - dialog.lpstrFilter = L"RIFF WAVE\0*.wav\0Apple AIFF\0*.aiff;*.aif;*.aifc\0Raw PCM (Stereo 44100Hz, 16-bit LE)\0*.raw;*.pcm;\0All files\0*.*\0\0"; - break; - } + dialog.lpstrFilter = filter; + swprintf(filter + sizeof("RIFF WAVE\0*.wav\0Apple AIFF\0*.aiff;*.aif;*.aifc\0Raw PCM (Stereo ") - 1, + sizeof("_______Hz, 16-bit LE)"), + L"%dHz, 16-bit LE) ", + frequency); + dialog.nFilterIndex = 1; dialog.lpstrInitialDir = NULL; dialog.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; diff --git a/SDL/audio/xaudio2.c b/SDL/audio/xaudio2.c index f738a4e..b1ffe26 100644 --- a/SDL/audio/xaudio2.c +++ b/SDL/audio/xaudio2.c @@ -1,8 +1,10 @@ +#define COBJMACROS #include "audio.h" #include #include +#include -#define AUDIO_FREQUENCY 96000 +static unsigned audio_frequency = 48000; static IXAudio2 *xaudio2 = NULL; static IXAudio2MasteringVoice *master_voice = NULL; static IXAudio2SourceVoice *source_voice = NULL; @@ -12,11 +14,9 @@ static unsigned pos = 0; #define BATCH_SIZE 256 -static const WAVEFORMATEX wave_format = { +static WAVEFORMATEX wave_format = { .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 2, - .nSamplesPerSec = AUDIO_FREQUENCY, - .nAvgBytesPerSec = AUDIO_FREQUENCY * 4, .nBlockAlign = 4, .wBitsPerSample = 16, .cbSize = 0 @@ -47,9 +47,45 @@ static void _audio_set_paused(bool paused) } + +#define _DEFINE_PROPERTYKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) static const PROPERTYKEY name = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid } +_DEFINE_PROPERTYKEY(_PKEY_AudioEngine_DeviceFormat, 0xf19f064d, 0x82c, 0x4e27, 0xbc, 0x73, 0x68, 0x82, 0xa1, 0xbb, 0x8e, 0x4c, 0); + + +static void update_frequency(void) +{ + HRESULT hr; + IMMDevice *device = NULL; + IMMDeviceEnumerator *enumerator = NULL; + IPropertyStore *store = NULL; + PWAVEFORMATEX deviceFormatProperties; + PROPVARIANT prop; + + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, (LPVOID *)&enumerator); + if (FAILED(hr)) return; + + // get default audio endpoint + + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(enumerator, eRender, eMultimedia, &device); + if (FAILED(hr)) return; + + hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &store); + if (FAILED(hr)) return; + + hr = IPropertyStore_GetValue(store, &_PKEY_AudioEngine_DeviceFormat, &prop); + if (FAILED(hr)) return; + + deviceFormatProperties = (PWAVEFORMATEX)prop.blob.pBlobData; + audio_frequency = deviceFormatProperties->nSamplesPerSec; + if (audio_frequency < 8000 || audio_frequency > 192000) { + // Bogus value, revert to 48KHz + audio_frequency = 48000; + } +} + static unsigned _audio_get_frequency(void) { - return AUDIO_FREQUENCY; + return audio_frequency; } static size_t _audio_get_queue_length(void) @@ -88,9 +124,11 @@ static bool _audio_init(void) return false; } + update_frequency(); + hr = IXAudio2_CreateMasteringVoice(xaudio2, &master_voice, 2, // 2 channels - AUDIO_FREQUENCY, + audio_frequency, 0, // Flags 0, // Device index NULL, // Effect chain @@ -101,6 +139,8 @@ static bool _audio_init(void) return false; } + wave_format.nSamplesPerSec = audio_frequency; + wave_format.nAvgBytesPerSec = audio_frequency * 4; hr = IXAudio2_CreateSourceVoice(xaudio2, &source_voice, &wave_format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, NULL, NULL, NULL); if (FAILED(hr)) { @@ -111,4 +151,4 @@ static bool _audio_init(void) return true; } -GB_AUDIO_DRIVER(XAudio2); \ No newline at end of file +GB_AUDIO_DRIVER(XAudio2); diff --git a/SDL/audio/xaudio2_7.c b/SDL/audio/xaudio2_7.c index 6cc163d..788ba1c 100644 --- a/SDL/audio/xaudio2_7.c +++ b/SDL/audio/xaudio2_7.c @@ -1,8 +1,10 @@ +#define COBJMACROS #include "xaudio2_7.h" #include "audio.h" +#include -#define AUDIO_FREQUENCY 96000 +static unsigned audio_frequency = 48000; static IXAudio2 *xaudio2 = NULL; static IXAudio2MasteringVoice *master_voice = NULL; static IXAudio2SourceVoice *source_voice = NULL; @@ -13,11 +15,9 @@ static unsigned pos = 0; #define BATCH_SIZE 256 -static const WAVEFORMATEX wave_format = { +static WAVEFORMATEX wave_format = { .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 2, - .nSamplesPerSec = AUDIO_FREQUENCY, - .nAvgBytesPerSec = AUDIO_FREQUENCY * 4, .nBlockAlign = 4, .wBitsPerSample = 16, .cbSize = 0 @@ -69,9 +69,44 @@ static void _audio_set_paused(bool paused) } +#define _DEFINE_PROPERTYKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) static const PROPERTYKEY name = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid } +_DEFINE_PROPERTYKEY(_PKEY_AudioEngine_DeviceFormat, 0xf19f064d, 0x82c, 0x4e27, 0xbc, 0x73, 0x68, 0x82, 0xa1, 0xbb, 0x8e, 0x4c, 0); + + +static void update_frequency(void) +{ + HRESULT hr; + IMMDevice *device = NULL; + IMMDeviceEnumerator *enumerator = NULL; + IPropertyStore *store = NULL; + PWAVEFORMATEX deviceFormatProperties; + PROPVARIANT prop; + + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, (LPVOID *)&enumerator); + if (FAILED(hr)) return; + + // get default audio endpoint + + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(enumerator, eRender, eMultimedia, &device); + if (FAILED(hr)) return; + + hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &store); + if (FAILED(hr)) return; + + hr = IPropertyStore_GetValue(store, &_PKEY_AudioEngine_DeviceFormat, &prop); + if (FAILED(hr)) return; + + deviceFormatProperties = (PWAVEFORMATEX)prop.blob.pBlobData; + audio_frequency = deviceFormatProperties->nSamplesPerSec; + if (audio_frequency < 8000 || audio_frequency > 192000) { + // Bogus value, revert to 48KHz + audio_frequency = 48000; + } +} + static unsigned _audio_get_frequency(void) { - return AUDIO_FREQUENCY; + return audio_frequency; } static size_t _audio_get_queue_length(void) @@ -110,9 +145,11 @@ static bool _audio_init(void) return false; } + update_frequency(); + hr = IXAudio2_CreateMasteringVoice(xaudio2, &master_voice, 2, // 2 channels - AUDIO_FREQUENCY, + audio_frequency, 0, // Flags 0, // Device index NULL // Effect chain @@ -122,6 +159,8 @@ static bool _audio_init(void) return false; } + wave_format.nSamplesPerSec = audio_frequency; + wave_format.nAvgBytesPerSec = audio_frequency * 4; hr = IXAudio2_CreateSourceVoice(xaudio2, &source_voice, &wave_format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, NULL, NULL, NULL); if (FAILED(hr)) { diff --git a/SDL/audio/xaudio2_7.h b/SDL/audio/xaudio2_7.h index c436d2e..2987156 100644 --- a/SDL/audio/xaudio2_7.h +++ b/SDL/audio/xaudio2_7.h @@ -90,6 +90,7 @@ DEFINE_GUID(IID_##interfaceName, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, DEFINE_CLSID(XAudio2, 5a508685, a254, 4fba, 9b, 82, 9a, 24, b0, 03, 06, af); DEFINE_IID(IXAudio2, 8bcf1f58, 9fe7, 4583, 8a, c6, e2, ad, c4, 65, c8, bb); + #define IXAudio2SourceVoice_Start(This,Flags,OperationSet) ((This)->lpVtbl->Start(This,Flags,OperationSet)) #define IXAudio2SourceVoice_Stop(This,Flags,OperationSet) ((This)->lpVtbl->Stop(This,Flags,OperationSet)) #define IXAudio2SourceVoice_SubmitSourceBuffer(This,pBuffer,pBufferWMA) ((This)->lpVtbl->SubmitSourceBuffer(This,pBuffer,pBufferWMA)) @@ -100,4 +101,8 @@ DEFINE_IID(IXAudio2, 8bcf1f58, 9fe7, 4583, 8a, c6, e2, ad, c4, 65, c8, bb); #define XAUDIO2_COMMIT_NOW 0 #define XAUDIO2_DEFAULT_PROCESSOR 0xffffffff -#define XAUDIO2_DEFAULT_FREQ_RATIO 2.0f \ No newline at end of file +#define XAUDIO2_DEFAULT_FREQ_RATIO 2.0f + +// WASAPI extras. This is a hack, but Windows itself is a hack so I don't care +DEFINE_CLSID(MMDeviceEnumerator, bcde0395, e52f, 467c, 8e, 3d, c4, 57, 92, 91, 69, 2e); +DEFINE_IID(IMMDeviceEnumerator, a95664d2, 9614, 4f35, a7, 46, de, 8d, b6, 36, 17, e6);