Skip to content

Commit

Permalink
Merge pull request #17 from Falcosoft/master
Browse files Browse the repository at this point in the history
Fixed Cubase and non-48kHz devices related problems
  • Loading branch information
Falcosoft authored Dec 12, 2023
2 parents 1790172 + 0f4798f commit 97e772f
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 51 deletions.
105 changes: 56 additions & 49 deletions Source/Driver/ASIO2WASAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -694,20 +694,20 @@ ASIO2WASAPI::ASIO2WASAPI (LPUNKNOWN pUnk, HRESULT *phr)
: CUnknown("ASIO2WASAPI", pUnk, phr)
{
clearState();
readFromRegistry();
readFromRegistry();
}

ASIO2WASAPI::~ASIO2WASAPI ()
{
shutdown();
shutdown();
}

void ASIO2WASAPI::shutdown()
{
IMMDeviceEnumerator* pEnumerator = NULL;
HRESULT hr = S_OK;

stop();
//stop(); rdundant disposeuffers calls stop()
disposeBuffers();

HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
Expand All @@ -732,7 +732,12 @@ void ASIO2WASAPI::shutdown()
delete(pNotificationClient);
pNotificationClient = NULL;
}


if (eventDrivenEvent)
{
CloseHandle(eventDrivenEvent);
eventDrivenEvent = NULL;
}
}

void ASIO2WASAPI::initInputFields(IMMDevice* pDevice, ASIO2WASAPI* pDriver, const HWND hwndDlg)
Expand Down Expand Up @@ -1308,15 +1313,15 @@ void ASIO2WASAPI::PlayThreadProcShared(LPVOID pThis)
BYTE* pData = NULL;

hr = CoInitialize(NULL);
RETURN_ON_ERROR(hr)

// Create an event handle and register it for
// buffer-event notifications.
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
CHandleCloser cl(hEvent);

hr = pAudioClient->SetEventHandle(hEvent);
RETURN_ON_ERROR(hr)
RETURN_ON_ERROR(hr)
if (!pDriver->eventDrivenEvent)// In Cubase 5 multiple start/stop cycles can occur without releasing AudioClient. And in shared mode AudioClient->SetEventHandle fails the 2nd time. So private eventDrivenEvent added as a global event.
{
pDriver->eventDrivenEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
hr = pAudioClient->SetEventHandle(pDriver->eventDrivenEvent);
RETURN_ON_ERROR(hr)
}
if (pDriver->eventDrivenEvent) ResetEvent(pDriver->eventDrivenEvent); //make sure event is not signaled AudioClient start is called

hr = pAudioClient->GetService(
IID_IAudioRenderClient,
Expand All @@ -1334,7 +1339,9 @@ void ASIO2WASAPI::PlayThreadProcShared(LPVOID pThis)
// Pre-load the first buffer with data

UINT32 bufferFrameCount;
UINT32 numFramesPadding;
hr = pAudioClient->GetBufferSize(&bufferFrameCount);
hr = pAudioClient->GetCurrentPadding(&numFramesPadding);
RETURN_ON_ERROR(hr)

UINT32 startFrames;
Expand All @@ -1343,6 +1350,8 @@ void ASIO2WASAPI::PlayThreadProcShared(LPVOID pThis)
else
startFrames = pDriver->m_bufferSize;

if (startFrames > (bufferFrameCount - numFramesPadding)) startFrames = bufferFrameCount - numFramesPadding;

hr = pRenderClient->GetBuffer(startFrames, &pData);
RETURN_ON_ERROR(hr)
//memset(pData, 0, bufferFrameCount * pDriver->m_waveFormat.Format.nBlockAlign);
Expand All @@ -1361,12 +1370,11 @@ void ASIO2WASAPI::PlayThreadProcShared(LPVOID pThis)
//char convTxt[11] = { 0 };

DWORD retval = 0;
HANDLE events[2] = { pDriver->m_hStopPlayThreadEvent, hEvent };
HANDLE events[2] = { pDriver->m_hStopPlayThreadEvent, pDriver->eventDrivenEvent };
while ((retval = WaitForMultipleObjects(2, events, FALSE, INFINITE)) == (WAIT_OBJECT_0 + 1))
{//the hEvent is signalled and m_hStopPlayThreadEvent is not
// Grab the next empty buffer from the audio device.

UINT32 numFramesPadding;
// Grab the next empty buffer from the audio device.

hr = pAudioClient->GetCurrentPadding(&numFramesPadding);
if (pDriver->m_bufferSize > (int)(bufferFrameCount - numFramesPadding))
{
Expand Down Expand Up @@ -1422,13 +1430,13 @@ void ASIO2WASAPI::PlayThreadProc(LPVOID pThis)
hr = CoInitialize(NULL);
RETURN_ON_ERROR(hr)

// Create an event handle and register it for
// buffer-event notifications.
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
CHandleCloser cl(hEvent);

hr = pAudioClient->SetEventHandle(hEvent);
RETURN_ON_ERROR(hr)
if (!pDriver->eventDrivenEvent) // In Cubase 5 multiple start/stop cycles can occur without releasing AudioClient. And in shared mode AudioClient->SetEventHandle fails the 2nd time. So private eventDrivenEvent added as a global event.
{
pDriver->eventDrivenEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
hr = pAudioClient->SetEventHandle(pDriver->eventDrivenEvent);
RETURN_ON_ERROR(hr)
}
if (pDriver->eventDrivenEvent) ResetEvent(pDriver->eventDrivenEvent); //make sure event is not signaled AudioClient start is called

hr = pAudioClient->GetService(
IID_IAudioRenderClient,
Expand Down Expand Up @@ -1472,7 +1480,7 @@ void ASIO2WASAPI::PlayThreadProc(LPVOID pThis)
//char convTxt[11] = { 0 };

DWORD retval = 0;
HANDLE events[2] = {pDriver->m_hStopPlayThreadEvent, hEvent };
HANDLE events[2] = {pDriver->m_hStopPlayThreadEvent, pDriver->eventDrivenEvent };
while ((retval = WaitForMultipleObjects(2,events,FALSE, INFINITE)) == (WAIT_OBJECT_0 + 1))
{//the hEvent is signalled and m_hStopPlayThreadEvent is not
// Grab the next empty buffer from the audio device.
Expand Down Expand Up @@ -1634,6 +1642,7 @@ ASIOBool ASIO2WASAPI::init(void* sysRef)
m_hAppWindowHandle = (HWND) sysRef;
m_hControlPanelHandle = 0;
pNotificationClient = NULL;
eventDrivenEvent = NULL;

HRESULT hr=S_OK;
IMMDeviceEnumerator *pEnumerator = NULL;
Expand Down Expand Up @@ -1696,25 +1705,21 @@ ASIOBool ASIO2WASAPI::init(void* sysRef)
BOOL rc = FindStreamFormat(m_pDevice, m_nChannels, m_nSampleRate, m_nBufferSize, m_wasapiExclusiveMode, m_wasapiEnableResampling, m_wasapiLowLatencySharedMode, &m_waveFormat, &m_pAudioClient);
if (!rc)
{
if (!m_wasapiExclusiveMode && !m_wasapiEnableResampling)
IAudioClient* pAudioClient = NULL;
hr = m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pAudioClient);
CReleaser r(pAudioClient);

WAVEFORMATEX* devFormat;
hr = pAudioClient->GetMixFormat(&devFormat);
if (SUCCEEDED(hr))
{
IAudioClient* pAudioClient = NULL;
hr = m_pDevice->Activate(
IID_IAudioClient, CLSCTX_ALL,
NULL, (void**)&pAudioClient);
CReleaser r(pAudioClient);

WAVEFORMATEX* devFormat;
hr = pAudioClient->GetMixFormat(&devFormat);
if (SUCCEEDED(hr))
{
m_nChannels = devFormat->nChannels;
m_nSampleRate = devFormat->nSamplesPerSec;
CoTaskMemFree(devFormat);
}
FindStreamFormat(m_pDevice, m_nChannels, m_nSampleRate, m_nBufferSize, m_wasapiExclusiveMode, m_wasapiEnableResampling, m_wasapiLowLatencySharedMode, &m_waveFormat, &m_pAudioClient);
}
else
m_nChannels = !m_wasapiExclusiveMode ? devFormat->nChannels : 2;
m_nSampleRate = devFormat->nSamplesPerSec;
CoTaskMemFree(devFormat);
rc = FindStreamFormat(m_pDevice, m_nChannels, m_nSampleRate, m_nBufferSize, m_wasapiExclusiveMode, m_wasapiEnableResampling, m_wasapiLowLatencySharedMode, &m_waveFormat, &m_pAudioClient);
}

if (!rc)
{//go through all devices and try to find the one that works for 16/48K
SAFE_RELEASE(m_pDevice)
setMostReliableFormat();
Expand Down Expand Up @@ -1815,23 +1820,25 @@ ASIOError ASIO2WASAPI::setSampleRate (ASIOSampleRate sampleRate)

ASIOError err = canSampleRate(sampleRate);
if (err != ASE_OK)
return err;
return err;

int nPrevSampleRate = m_nSampleRate;
m_nSampleRate = (int)sampleRate;
writeToRegistry();
if (m_callbacks)
{//ask the host ro reset us
int nPrevSampleRate = m_nSampleRate;
m_nSampleRate = (int)sampleRate;
writeToRegistry();
m_nSampleRate = nPrevSampleRate;
m_callbacks->asioMessage(kAsioResetRequest,0,NULL,NULL);
m_callbacks->asioMessage(kAsioResetRequest, 0, NULL, NULL);
}
else
else return ASE_NoClock;
/* In case of Cubase 5 getBufferSize has been called at this point and buffersize can change due to AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED which results in failed createBuffers thus no sound at all.
{//reinitialize us with the new sample rate
HWND hAppWindowHandle = m_hAppWindowHandle;
shutdown();
readFromRegistry();
init(hAppWindowHandle);
}
*/

return ASE_OK;
}
Expand Down
5 changes: 3 additions & 2 deletions Source/Driver/ASIO2WASAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ class ASIO2WASAPI : public IASIO, public CUnknown
void setUseDefaultDevice(bool value) { m_useDefaultDevice = value; };
private:
//for default device changed notification
CMMNotificationClient* pNotificationClient;
CMMNotificationClient* pNotificationClient = NULL;
HANDLE eventDrivenEvent = NULL;

static void PlayThreadProc(LPVOID pThis);
static void PlayThreadProcShared(LPVOID pThis);
Expand Down Expand Up @@ -178,7 +179,7 @@ class ASIO2WASAPI : public IASIO, public CUnknown
HWND m_hControlPanelHandle;

//WASAPI specific
bool m_useDefaultDevice;
bool m_useDefaultDevice = true;
AUDCLNT_SHAREMODE m_wasapiExclusiveMode = AUDCLNT_SHAREMODE_EXCLUSIVE;
BOOL m_wasapiEnableResampling = FALSE;
BOOL m_wasapiLowLatencySharedMode = FALSE;
Expand Down

0 comments on commit 97e772f

Please sign in to comment.