Query the system sample rate on Windows and use it, rather than hardcode 96KHz
This commit is contained in:
parent
88f5b22bf6
commit
0dbfaef4cf
@ -1,5 +1,6 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include "open_dialog.h"
|
#include "open_dialog.h"
|
||||||
|
|
||||||
static char *wc_to_utf8_alloc(const wchar_t *wide)
|
static char *wc_to_utf8_alloc(const wchar_t *wide)
|
||||||
@ -66,23 +67,18 @@ char *do_save_recording_dialog(unsigned frequency)
|
|||||||
{
|
{
|
||||||
OPENFILENAMEW dialog;
|
OPENFILENAMEW dialog;
|
||||||
wchar_t filename[MAX_PATH + 5] = L"recording.wav";
|
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));
|
memset(&dialog, 0, sizeof(dialog));
|
||||||
dialog.lStructSize = sizeof(dialog);
|
dialog.lStructSize = sizeof(dialog);
|
||||||
dialog.lpstrFile = filename;
|
dialog.lpstrFile = filename;
|
||||||
dialog.nMaxFile = MAX_PATH;
|
dialog.nMaxFile = MAX_PATH;
|
||||||
switch (frequency) {
|
dialog.lpstrFilter = filter;
|
||||||
case 96000:
|
swprintf(filter + sizeof("RIFF WAVE\0*.wav\0Apple AIFF\0*.aiff;*.aif;*.aifc\0Raw PCM (Stereo ") - 1,
|
||||||
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";
|
sizeof("_______Hz, 16-bit LE)"),
|
||||||
break;
|
L"%dHz, 16-bit LE) ",
|
||||||
case 48000:
|
frequency);
|
||||||
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.nFilterIndex = 1;
|
dialog.nFilterIndex = 1;
|
||||||
dialog.lpstrInitialDir = NULL;
|
dialog.lpstrInitialDir = NULL;
|
||||||
dialog.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
|
dialog.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
#define COBJMACROS
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <xaudio2.h>
|
#include <xaudio2.h>
|
||||||
|
#include <Mmdeviceapi.h>
|
||||||
|
|
||||||
#define AUDIO_FREQUENCY 96000
|
static unsigned audio_frequency = 48000;
|
||||||
static IXAudio2 *xaudio2 = NULL;
|
static IXAudio2 *xaudio2 = NULL;
|
||||||
static IXAudio2MasteringVoice *master_voice = NULL;
|
static IXAudio2MasteringVoice *master_voice = NULL;
|
||||||
static IXAudio2SourceVoice *source_voice = NULL;
|
static IXAudio2SourceVoice *source_voice = NULL;
|
||||||
@ -12,11 +14,9 @@ static unsigned pos = 0;
|
|||||||
|
|
||||||
#define BATCH_SIZE 256
|
#define BATCH_SIZE 256
|
||||||
|
|
||||||
static const WAVEFORMATEX wave_format = {
|
static WAVEFORMATEX wave_format = {
|
||||||
.wFormatTag = WAVE_FORMAT_PCM,
|
.wFormatTag = WAVE_FORMAT_PCM,
|
||||||
.nChannels = 2,
|
.nChannels = 2,
|
||||||
.nSamplesPerSec = AUDIO_FREQUENCY,
|
|
||||||
.nAvgBytesPerSec = AUDIO_FREQUENCY * 4,
|
|
||||||
.nBlockAlign = 4,
|
.nBlockAlign = 4,
|
||||||
.wBitsPerSample = 16,
|
.wBitsPerSample = 16,
|
||||||
.cbSize = 0
|
.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)
|
static unsigned _audio_get_frequency(void)
|
||||||
{
|
{
|
||||||
return AUDIO_FREQUENCY;
|
return audio_frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t _audio_get_queue_length(void)
|
static size_t _audio_get_queue_length(void)
|
||||||
@ -88,9 +124,11 @@ static bool _audio_init(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_frequency();
|
||||||
|
|
||||||
hr = IXAudio2_CreateMasteringVoice(xaudio2, &master_voice,
|
hr = IXAudio2_CreateMasteringVoice(xaudio2, &master_voice,
|
||||||
2, // 2 channels
|
2, // 2 channels
|
||||||
AUDIO_FREQUENCY,
|
audio_frequency,
|
||||||
0, // Flags
|
0, // Flags
|
||||||
0, // Device index
|
0, // Device index
|
||||||
NULL, // Effect chain
|
NULL, // Effect chain
|
||||||
@ -101,6 +139,8 @@ static bool _audio_init(void)
|
|||||||
return false;
|
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);
|
hr = IXAudio2_CreateSourceVoice(xaudio2, &source_voice, &wave_format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
#define COBJMACROS
|
||||||
#include "xaudio2_7.h"
|
#include "xaudio2_7.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
|
#include <Mmdeviceapi.h>
|
||||||
|
|
||||||
|
|
||||||
#define AUDIO_FREQUENCY 96000
|
static unsigned audio_frequency = 48000;
|
||||||
static IXAudio2 *xaudio2 = NULL;
|
static IXAudio2 *xaudio2 = NULL;
|
||||||
static IXAudio2MasteringVoice *master_voice = NULL;
|
static IXAudio2MasteringVoice *master_voice = NULL;
|
||||||
static IXAudio2SourceVoice *source_voice = NULL;
|
static IXAudio2SourceVoice *source_voice = NULL;
|
||||||
@ -13,11 +15,9 @@ static unsigned pos = 0;
|
|||||||
#define BATCH_SIZE 256
|
#define BATCH_SIZE 256
|
||||||
|
|
||||||
|
|
||||||
static const WAVEFORMATEX wave_format = {
|
static WAVEFORMATEX wave_format = {
|
||||||
.wFormatTag = WAVE_FORMAT_PCM,
|
.wFormatTag = WAVE_FORMAT_PCM,
|
||||||
.nChannels = 2,
|
.nChannels = 2,
|
||||||
.nSamplesPerSec = AUDIO_FREQUENCY,
|
|
||||||
.nAvgBytesPerSec = AUDIO_FREQUENCY * 4,
|
|
||||||
.nBlockAlign = 4,
|
.nBlockAlign = 4,
|
||||||
.wBitsPerSample = 16,
|
.wBitsPerSample = 16,
|
||||||
.cbSize = 0
|
.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)
|
static unsigned _audio_get_frequency(void)
|
||||||
{
|
{
|
||||||
return AUDIO_FREQUENCY;
|
return audio_frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t _audio_get_queue_length(void)
|
static size_t _audio_get_queue_length(void)
|
||||||
@ -110,9 +145,11 @@ static bool _audio_init(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_frequency();
|
||||||
|
|
||||||
hr = IXAudio2_CreateMasteringVoice(xaudio2, &master_voice,
|
hr = IXAudio2_CreateMasteringVoice(xaudio2, &master_voice,
|
||||||
2, // 2 channels
|
2, // 2 channels
|
||||||
AUDIO_FREQUENCY,
|
audio_frequency,
|
||||||
0, // Flags
|
0, // Flags
|
||||||
0, // Device index
|
0, // Device index
|
||||||
NULL // Effect chain
|
NULL // Effect chain
|
||||||
@ -122,6 +159,8 @@ static bool _audio_init(void)
|
|||||||
return false;
|
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);
|
hr = IXAudio2_CreateSourceVoice(xaudio2, &source_voice, &wave_format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -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_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_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_Start(This,Flags,OperationSet) ((This)->lpVtbl->Start(This,Flags,OperationSet))
|
||||||
#define IXAudio2SourceVoice_Stop(This,Flags,OperationSet) ((This)->lpVtbl->Stop(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))
|
#define IXAudio2SourceVoice_SubmitSourceBuffer(This,pBuffer,pBufferWMA) ((This)->lpVtbl->SubmitSourceBuffer(This,pBuffer,pBufferWMA))
|
||||||
@ -101,3 +102,7 @@ DEFINE_IID(IXAudio2, 8bcf1f58, 9fe7, 4583, 8a, c6, e2, ad, c4, 65, c8, bb);
|
|||||||
#define XAUDIO2_COMMIT_NOW 0
|
#define XAUDIO2_COMMIT_NOW 0
|
||||||
#define XAUDIO2_DEFAULT_PROCESSOR 0xffffffff
|
#define XAUDIO2_DEFAULT_PROCESSOR 0xffffffff
|
||||||
#define XAUDIO2_DEFAULT_FREQ_RATIO 2.0f
|
#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);
|
||||||
|
Loading…
Reference in New Issue
Block a user