Add window support for Windows.

This commit is contained in:
jamgroga 2021-10-31 13:04:48 +00:00
parent 5d32592126
commit c05b7b6315
27 changed files with 783 additions and 95 deletions

View file

@ -3,17 +3,24 @@ set(platform_HEADERS "")
set(platform_INCLUDES "")
if (UNIX)
find_package(ALSA REQUIRED)
list(APPEND platform_HEADERS
audio_interfaces/AlsaInterface.h
${ALSA_INCLUDE_DIRS}
)
list(APPEND platform_INCLUDES
audio_interfaces/AlsaInterface.cpp
)
list(APPEND platform_LIBS
${ALSA_LIBRARIES}
)
find_package(ALSA REQUIRED)
list(APPEND platform_HEADERS
audio_interfaces/AlsaInterface.h
${ALSA_INCLUDE_DIRS}
)
list(APPEND platform_INCLUDES
audio_interfaces/AlsaInterface.cpp
)
list(APPEND platform_LIBS
${ALSA_LIBRARIES}
)
else()
list(APPEND platform_HEADERS
audio_interfaces/WasapiInterface.h
)
list(APPEND platform_INCLUDES
audio_interfaces/WasapiInterface.cpp
)
endif (UNIX)
list(APPEND audio_HEADERS

View file

@ -0,0 +1,207 @@
#include "WasapiInterface.h"
#include "FileLogger.h"
#include "AudioSynth.h"
#include <vector>
#include <iostream>
#include <Windows.h>
#include <Audioclient.h>
#include <mmdeviceapi.h>
#include <Functiondiscoverykeys_devpkey.h>
WasapiInterface::WasapiInterface()
{
}
WasapiInterface::~WasapiInterface()
{
}
std::unique_ptr<WasapiInterface> WasapiInterface::Create()
{
return std::make_unique<WasapiInterface>();
}
void WasapiInterface::OpenDevice(const AudioDevicePtr& device)
{
}
void WasapiInterface::SetAccessType(const AudioDevicePtr& device)
{
}
void WasapiInterface::SetSampleFormat(const AudioDevicePtr& device)
{
}
void WasapiInterface::SetSampleRate(const AudioDevicePtr& device)
{
}
void WasapiInterface::SetPeriod(const AudioDevicePtr& device)
{
}
void WasapiInterface::SetBufferSize(const AudioDevicePtr& device)
{
}
void WasapiInterface::SetChannelNumber(const AudioDevicePtr& device)
{
}
// REFERENCE_TIME time units per second and per millisecond
#define REFTIMES_PER_SEC 10000000
#define REFTIMES_PER_MILLISEC 10000
#define EXIT_ON_ERROR(hres) \
if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk) \
if ((punk) != NULL) \
{ (punk)->Release(); (punk) = NULL; }
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
const IID IID_IAudioClient = __uuidof(IAudioClient);
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
void WasapiInterface::Play(const AudioDevicePtr& device)
{
std::cout << "Into wasapi play" << std::endl;
IMMDeviceEnumerator* pEnumerator = nullptr;
auto hr = CoCreateInstance(CLSID_MMDeviceEnumerator,
nullptr,
CLSCTX_ALL,
IID_IMMDeviceEnumerator,
(void**)&pEnumerator);
if (FAILED(hr))
{
std::cout << "Failed to create enumerator" << std::endl;
return;
}
IMMDevice* pDevice = nullptr;
hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
if (FAILED(hr))
{
return;
}
std::cout << "Got default endpoint" << std::endl;
IPropertyStore* pPropertyStore{ nullptr };
hr = pDevice->OpenPropertyStore(STGM_READ, &pPropertyStore);
DWORD propCount{ 0 };
pPropertyStore->GetCount(&propCount);
PROPVARIANT deviceName;
PropVariantInit(&deviceName);
// hr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &deviceName);
hr = pPropertyStore->GetValue(PKEY_DeviceInterface_FriendlyName, &deviceName);
//PKEY_Device_FriendlyName
std::cout << "Device name: " << deviceName.pwszVal << std::endl;
pPropertyStore->Release();
IAudioClient* pAudioClient = nullptr;
hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, (void**)&pAudioClient);
std::cout << "Activated audio device" << std::endl;
if (FAILED(hr))
{
return;
}
WAVEFORMATEX* pwfx = nullptr;
hr = pAudioClient->GetMixFormat(&pwfx);
if (FAILED(hr))
{
return;
}
std::cout << "formatTag: " << pwfx->wFormatTag << std::endl;
std::cout << "nChannels: " << pwfx->nChannels << std::endl;
std::cout << "nSamplesPerSec: " << pwfx->nSamplesPerSec << std::endl;
std::cout << "nAvgBytesPerSec: " << pwfx->nAvgBytesPerSec << std::endl; // nSamplesPerSec*nBlockAlign
std::cout << "nBlockAlign: " << pwfx->nBlockAlign << std::endl; //nChannels *wBitsPerSample/8 (bytes)
std::cout << "wBitsPerSample: " << pwfx->wBitsPerSample << std::endl;
std::cout << "cbSize: " << pwfx->cbSize << std::endl;
//REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;
//hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0,
// hnsRequestedDuration,
// 0, pwfx, nullptr);
//if (FAILED(hr))
//{
// return;
//}
//// Tell the audio source which format to use.
//// hr = pMySource->SetFormat(pwfx);
//// Get the actual size of the allocated buffer.
//UINT32 bufferFrameCount;
//hr = pAudioClient->GetBufferSize(&bufferFrameCount);
//IAudioRenderClient* pRenderClient = nullptr;
//hr = pAudioClient->GetService(IID_IAudioRenderClient, (void**)&pRenderClient);
//// Grab the entire buffer for the initial fill operation.
//BYTE* pData;
//hr = pRenderClient->GetBuffer(bufferFrameCount, &pData);
//// Load the initial data into the shared buffer.
//DWORD flags = 0;
//// hr = pMySource->LoadData(bufferFrameCount, pData, &flags);
//hr = pRenderClient->ReleaseBuffer(bufferFrameCount, flags);
//// Calculate the actual duration of the allocated buffer.
//auto hnsActualDuration = (double)REFTIMES_PER_SEC * bufferFrameCount / pwfx->nSamplesPerSec;
//hr = pAudioClient->Start(); // Start playing.
//// Each loop fills about half of the shared buffer.
//while (flags != AUDCLNT_BUFFERFLAGS_SILENT)
//{
// // Sleep for half the buffer duration.
// Sleep((DWORD)(hnsActualDuration / REFTIMES_PER_MILLISEC / 2));
// // See how much buffer space is available.
// UINT32 numFramesPadding;
// hr = pAudioClient->GetCurrentPadding(&numFramesPadding);
// auto numFramesAvailable = bufferFrameCount - numFramesPadding;
// // Grab all the available space in the shared buffer.
// hr = pRenderClient->GetBuffer(numFramesAvailable, &pData);
// // Get next 1/2-second of data from the audio source.
// // hr = pMySource->LoadData(numFramesAvailable, pData, &flags);
// hr = pRenderClient->ReleaseBuffer(numFramesAvailable, flags);
//}
//
//// Wait for last data in buffer to play before stopping.
//Sleep((DWORD)(hnsActualDuration / REFTIMES_PER_MILLISEC / 2));
//hr = pAudioClient->Stop(); // Stop playing.
//CoTaskMemFree(pwfx);
//SAFE_RELEASE(pEnumerator)
//SAFE_RELEASE(pDevice)
//SAFE_RELEASE(pAudioClient)
//SAFE_RELEASE(pRenderClient)
return;
}

View file

@ -0,0 +1,36 @@
#pragma once
#include "IAudioInterface.h"
#include "AudioDevice.h"
#include <memory>
class WasapiInterface : public IAudioInterface
{
public:
WasapiInterface();
~WasapiInterface();
static std::unique_ptr<WasapiInterface> Create();
void OpenDevice(const AudioDevicePtr& device) override;
void SetAccessType(const AudioDevicePtr& device);
void SetSampleFormat(const AudioDevicePtr& device);
void SetSampleRate(const AudioDevicePtr& device);
void SetPeriod(const AudioDevicePtr& device);
void SetBufferSize(const AudioDevicePtr& device);
void SetChannelNumber(const AudioDevicePtr& device);
void Play(const AudioDevicePtr& device) override;
};
using AlsaInterfacePtr = std::shared_ptr<WasapiInterface>;