First Stabs at Windows Sound (See winsoundcat.cpp)
This commit is contained in:
@@ -50,7 +50,8 @@ endif()
|
||||
target_link_libraries(ReMixer-Test PUBLIC ReMixer)
|
||||
|
||||
add_executable(pacat pacat_simple.cpp
|
||||
pacat_advanced.cpp)
|
||||
pacat_advanced.cpp
|
||||
src/windows/ReMixer.cpp)
|
||||
target_link_libraries(pacat pulse-simple pulse)
|
||||
|
||||
add_executable(vorbis_decode vorbis_decode.cpp)
|
||||
@@ -58,3 +59,8 @@ target_link_libraries(vorbis_decode vorbisfile vorbis)
|
||||
|
||||
add_executable(pacat_advanced pacat_advanced.cpp)
|
||||
target_link_libraries(pacat_advanced pulse)
|
||||
|
||||
if (WIN32)
|
||||
add_executable(winsoundcat winsoundcat.cpp)
|
||||
target_link_libraries(winsoundcat)
|
||||
endif()
|
3
src/windows/ReMixer.cpp
Normal file
3
src/windows/ReMixer.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
//
|
||||
// Created by Josh on 8/22/2024.
|
||||
//
|
280
winsoundcat.cpp
Normal file
280
winsoundcat.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
#include <iostream>
|
||||
|
||||
#define COBJMACROS
|
||||
#include <mmdeviceapi.h>
|
||||
#include <audioclient.h>
|
||||
|
||||
int enumerate_sound_devices()
|
||||
{
|
||||
// Initialize COM-interface subsystem
|
||||
CoInitializeEx(NULL, 0);
|
||||
|
||||
IMMDeviceEnumerator *enu;
|
||||
const GUID _CLSID_MMDeviceEnumerator = {0xbcde0395, 0xe52f, 0x467c, {0x8e,0x3d, 0xc4,0x57,0x92,0x91,0x69,0x2e}};
|
||||
const GUID _IID_IMMDeviceEnumerator = {0xa95664d2, 0x9614, 0x4f35, {0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6}};
|
||||
CoCreateInstance(_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, _IID_IMMDeviceEnumerator, (void**)&enu);
|
||||
|
||||
bool playback = true;
|
||||
|
||||
IMMDeviceCollection *dcoll;
|
||||
EDataFlow mode = (playback) ? eRender : eCapture;
|
||||
enu->EnumAudioEndpoints(mode, DEVICE_STATE_ACTIVE, &dcoll);
|
||||
|
||||
for (int i = 0; ; i++)
|
||||
{
|
||||
IMMDevice *dev;
|
||||
if (0 != dcoll->Item(i, &dev))
|
||||
break;
|
||||
|
||||
IPropertyStore *props;
|
||||
dev->OpenPropertyStore(STGM_READ, &props);
|
||||
|
||||
PROPVARIANT name;
|
||||
|
||||
PropVariantInit(&name);
|
||||
const PROPERTYKEY PKEY_Device_FriendlyName = {{0xa45c254e, 0xdf1c, 0x4efd, {0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0}}, 14};
|
||||
|
||||
props->GetValue(PKEY_Device_FriendlyName, &name);
|
||||
|
||||
const wchar_t *device_name = name.pwszVal;
|
||||
|
||||
|
||||
wchar_t* device_id = NULL;
|
||||
dev->GetId(&device_id);
|
||||
|
||||
IMMDevice *def_dev = NULL;
|
||||
enu->GetDefaultAudioEndpoint(mode, eConsole, &def_dev);
|
||||
|
||||
def_dev->Release();
|
||||
|
||||
CoTaskMemFree(device_id);
|
||||
|
||||
PropVariantClear(&name);
|
||||
|
||||
dev->Release();
|
||||
}
|
||||
|
||||
//IMMDeviceEnumerator_Release(enu);
|
||||
dcoll->Release();
|
||||
enu->Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int open_shared_buffer()
|
||||
{
|
||||
bool playback = true;
|
||||
|
||||
IMMDeviceEnumerator *enu;
|
||||
const GUID CLSID_MMDeviceEnumerator = {0xbcde0395, 0xe52f, 0x467c, {0x8e,0x3d, 0xc4,0x57,0x92,0x91,0x69,0x2e}};
|
||||
const GUID IID_IMMDeviceEnumerator = {0xa95664d2, 0x9614, 0x4f35, {0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6}};
|
||||
CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&enu);
|
||||
|
||||
|
||||
IMMDevice *dev;
|
||||
|
||||
wchar_t* device_id = NULL;
|
||||
if (device_id == NULL)
|
||||
{
|
||||
EDataFlow mode = (playback) ? eRender : eCapture;
|
||||
enu->GetDefaultAudioEndpoint(mode, eConsole, &dev);
|
||||
} else {
|
||||
enu->GetDevice(device_id, &dev);
|
||||
}
|
||||
|
||||
IAudioClient* client;
|
||||
const GUID IID_IAudioClient = {0x1cb9ad4c, 0xdbfa, 0x4c32, {0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2}};
|
||||
dev->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&client);
|
||||
|
||||
WAVEFORMATEX *wf;
|
||||
client->GetMixFormat(&wf);
|
||||
|
||||
int buffer_length_msec = 500;
|
||||
REFERENCE_TIME dur = buffer_length_msec * 1000 * 10;
|
||||
|
||||
AUDCLNT_SHAREMODE mode = AUDCLNT_SHAREMODE_SHARED;
|
||||
int aflags = 0;
|
||||
|
||||
client->Initialize(mode, aflags, dur, dur, wf, NULL);
|
||||
|
||||
u_int buf_frames;
|
||||
|
||||
client->GetBufferSize(&buf_frames);
|
||||
|
||||
buffer_length_msec = buf_frames * 1000 / wf->nSamplesPerSec;
|
||||
|
||||
CoTaskMemFree(wf);
|
||||
client->Release();
|
||||
dev->Release();
|
||||
enu->Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int record_shared()
|
||||
{
|
||||
bool playback = true;
|
||||
|
||||
IMMDeviceEnumerator *enu;
|
||||
const GUID CLSID_MMDeviceEnumerator = {0xbcde0395, 0xe52f, 0x467c, {0x8e,0x3d, 0xc4,0x57,0x92,0x91,0x69,0x2e}};
|
||||
const GUID IID_IMMDeviceEnumerator = {0xa95664d2, 0x9614, 0x4f35, {0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6}};
|
||||
CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&enu);
|
||||
|
||||
|
||||
IMMDevice *dev;
|
||||
|
||||
wchar_t* device_id = NULL;
|
||||
if (device_id == NULL)
|
||||
{
|
||||
EDataFlow mode = (playback) ? eRender : eCapture;
|
||||
enu->GetDefaultAudioEndpoint(mode, eConsole, &dev);
|
||||
} else {
|
||||
enu->GetDevice(device_id, &dev);
|
||||
}
|
||||
|
||||
IAudioClient* client;
|
||||
const GUID IID_IAudioClient = {0x1cb9ad4c, 0xdbfa, 0x4c32, {0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2}};
|
||||
dev->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&client);
|
||||
|
||||
WAVEFORMATEX *wf;
|
||||
client->GetMixFormat(&wf);
|
||||
|
||||
int buffer_length_msec = 500;
|
||||
REFERENCE_TIME dur = buffer_length_msec * 1000 * 10;
|
||||
|
||||
AUDCLNT_SHAREMODE mode = AUDCLNT_SHAREMODE_SHARED;
|
||||
int aflags = 0;
|
||||
|
||||
client->Initialize(mode, aflags, dur, dur, wf, NULL);
|
||||
|
||||
u_int buf_frames;
|
||||
|
||||
client->GetBufferSize(&buf_frames);
|
||||
|
||||
buffer_length_msec = buf_frames * 1000 / wf->nSamplesPerSec;
|
||||
|
||||
IAudioCaptureClient* capt;
|
||||
const GUID IID_IAudioCaptureClient = {0xc8adbd64, 0xe71e, 0x48a0, {0xa4,0xde, 0x18,0x5c,0x39,0x5c,0xd3,0x17}};
|
||||
client->GetService(IID_IAudioCaptureClient, (void**)&capt);
|
||||
|
||||
client->Start();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
u_char * data;
|
||||
u_int nframes;
|
||||
u_long flags;
|
||||
int r = capt->GetBuffer(&data, &nframes, &flags, NULL, NULL);
|
||||
|
||||
|
||||
if (r == AUDCLNT_S_BUFFER_EMPTY) {
|
||||
// Buffer is empty. Wait for more data/
|
||||
int period_ms = 100;
|
||||
Sleep(period_ms);
|
||||
continue;
|
||||
} else if (r != 0) {
|
||||
// error
|
||||
}
|
||||
|
||||
capt->ReleaseBuffer(nframes);
|
||||
}
|
||||
|
||||
CoTaskMemFree(wf);
|
||||
client->Release();
|
||||
dev->Release();
|
||||
enu->Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int play_shared()
|
||||
{
|
||||
bool playback = true;
|
||||
|
||||
IMMDeviceEnumerator *enu;
|
||||
const GUID CLSID_MMDeviceEnumerator = {0xbcde0395, 0xe52f, 0x467c, {0x8e,0x3d, 0xc4,0x57,0x92,0x91,0x69,0x2e}};
|
||||
const GUID IID_IMMDeviceEnumerator = {0xa95664d2, 0x9614, 0x4f35, {0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6}};
|
||||
CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&enu);
|
||||
|
||||
|
||||
IMMDevice *dev;
|
||||
|
||||
wchar_t* device_id = NULL;
|
||||
if (device_id == NULL)
|
||||
{
|
||||
EDataFlow mode = (playback) ? eRender : eCapture;
|
||||
enu->GetDefaultAudioEndpoint(mode, eConsole, &dev);
|
||||
} else {
|
||||
enu->GetDevice(device_id, &dev);
|
||||
}
|
||||
|
||||
IAudioClient* client;
|
||||
const GUID IID_IAudioClient = {0x1cb9ad4c, 0xdbfa, 0x4c32, {0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2}};
|
||||
dev->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&client);
|
||||
|
||||
WAVEFORMATEX *wf;
|
||||
client->GetMixFormat(&wf);
|
||||
|
||||
int buffer_length_msec = 500;
|
||||
REFERENCE_TIME dur = buffer_length_msec * 1000 * 10;
|
||||
|
||||
AUDCLNT_SHAREMODE mode = AUDCLNT_SHAREMODE_SHARED;
|
||||
int aflags = 0;
|
||||
|
||||
client->Initialize(mode, aflags, dur, dur, wf, NULL);
|
||||
|
||||
u_int buf_frames;
|
||||
|
||||
client->GetBufferSize(&buf_frames);
|
||||
|
||||
buffer_length_msec = buf_frames * 1000 / wf->nSamplesPerSec;
|
||||
|
||||
IAudioRenderClient *render;
|
||||
const GUID IID_IAudioRenderClient = {0xf294acfc, 0x3146, 0x4483, {0xa7,0xbf, 0xad,0xdc,0xa7,0xc2,0x60,0xe2}};
|
||||
client->GetService(IID_IAudioRenderClient, (void**)&render);
|
||||
|
||||
|
||||
u_int filled;
|
||||
client->GetCurrentPadding(&filled);
|
||||
|
||||
int n_free_frames = buf_frames - filled;
|
||||
|
||||
int started = 0;
|
||||
|
||||
if (!started)
|
||||
{
|
||||
client->Start();
|
||||
started = 1;
|
||||
}
|
||||
|
||||
u_char *data;
|
||||
render->GetBuffer(n_free_frames, &data);
|
||||
|
||||
// Drain the audio buffer
|
||||
for (;;)
|
||||
{
|
||||
u_int filled;
|
||||
client->GetCurrentPadding(&filled);
|
||||
if (filled == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
render->ReleaseBuffer(n_free_frames, 0);
|
||||
render->Release();
|
||||
CoTaskMemFree(wf);
|
||||
client->Release();
|
||||
dev->Release();
|
||||
enu->Release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
enumerate_sound_devices();
|
||||
open_shared_buffer();
|
||||
play_shared();
|
||||
|
||||
std::cout << "Windows Program" << std::endl;
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user