Skip to content

Commit 97e772f

Browse files
authored
Merge pull request #17 from Falcosoft/master
Fixed Cubase and non-48kHz devices related problems
2 parents 1790172 + 0f4798f commit 97e772f

2 files changed

Lines changed: 59 additions & 51 deletions

File tree

Source/Driver/ASIO2WASAPI.cpp

Lines changed: 56 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -694,20 +694,20 @@ ASIO2WASAPI::ASIO2WASAPI (LPUNKNOWN pUnk, HRESULT *phr)
694694
: CUnknown("ASIO2WASAPI", pUnk, phr)
695695
{
696696
clearState();
697-
readFromRegistry();
697+
readFromRegistry();
698698
}
699699

700700
ASIO2WASAPI::~ASIO2WASAPI ()
701701
{
702-
shutdown();
702+
shutdown();
703703
}
704704

705705
void ASIO2WASAPI::shutdown()
706706
{
707707
IMMDeviceEnumerator* pEnumerator = NULL;
708708
HRESULT hr = S_OK;
709709

710-
stop();
710+
//stop(); rdundant disposeuffers calls stop()
711711
disposeBuffers();
712712

713713
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
@@ -732,7 +732,12 @@ void ASIO2WASAPI::shutdown()
732732
delete(pNotificationClient);
733733
pNotificationClient = NULL;
734734
}
735-
735+
736+
if (eventDrivenEvent)
737+
{
738+
CloseHandle(eventDrivenEvent);
739+
eventDrivenEvent = NULL;
740+
}
736741
}
737742

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

13101315
hr = CoInitialize(NULL);
1311-
RETURN_ON_ERROR(hr)
1312-
1313-
// Create an event handle and register it for
1314-
// buffer-event notifications.
1315-
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
1316-
CHandleCloser cl(hEvent);
1317-
1318-
hr = pAudioClient->SetEventHandle(hEvent);
1319-
RETURN_ON_ERROR(hr)
1316+
RETURN_ON_ERROR(hr)
1317+
1318+
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.
1319+
{
1320+
pDriver->eventDrivenEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
1321+
hr = pAudioClient->SetEventHandle(pDriver->eventDrivenEvent);
1322+
RETURN_ON_ERROR(hr)
1323+
}
1324+
if (pDriver->eventDrivenEvent) ResetEvent(pDriver->eventDrivenEvent); //make sure event is not signaled AudioClient start is called
13201325

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

13361341
UINT32 bufferFrameCount;
1342+
UINT32 numFramesPadding;
13371343
hr = pAudioClient->GetBufferSize(&bufferFrameCount);
1344+
hr = pAudioClient->GetCurrentPadding(&numFramesPadding);
13381345
RETURN_ON_ERROR(hr)
13391346

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

1353+
if (startFrames > (bufferFrameCount - numFramesPadding)) startFrames = bufferFrameCount - numFramesPadding;
1354+
13461355
hr = pRenderClient->GetBuffer(startFrames, &pData);
13471356
RETURN_ON_ERROR(hr)
13481357
//memset(pData, 0, bufferFrameCount * pDriver->m_waveFormat.Format.nBlockAlign);
@@ -1361,12 +1370,11 @@ void ASIO2WASAPI::PlayThreadProcShared(LPVOID pThis)
13611370
//char convTxt[11] = { 0 };
13621371

13631372
DWORD retval = 0;
1364-
HANDLE events[2] = { pDriver->m_hStopPlayThreadEvent, hEvent };
1373+
HANDLE events[2] = { pDriver->m_hStopPlayThreadEvent, pDriver->eventDrivenEvent };
13651374
while ((retval = WaitForMultipleObjects(2, events, FALSE, INFINITE)) == (WAIT_OBJECT_0 + 1))
13661375
{//the hEvent is signalled and m_hStopPlayThreadEvent is not
1367-
// Grab the next empty buffer from the audio device.
1368-
1369-
UINT32 numFramesPadding;
1376+
// Grab the next empty buffer from the audio device.
1377+
13701378
hr = pAudioClient->GetCurrentPadding(&numFramesPadding);
13711379
if (pDriver->m_bufferSize > (int)(bufferFrameCount - numFramesPadding))
13721380
{
@@ -1422,13 +1430,13 @@ void ASIO2WASAPI::PlayThreadProc(LPVOID pThis)
14221430
hr = CoInitialize(NULL);
14231431
RETURN_ON_ERROR(hr)
14241432

1425-
// Create an event handle and register it for
1426-
// buffer-event notifications.
1427-
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
1428-
CHandleCloser cl(hEvent);
1429-
1430-
hr = pAudioClient->SetEventHandle(hEvent);
1431-
RETURN_ON_ERROR(hr)
1433+
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.
1434+
{
1435+
pDriver->eventDrivenEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
1436+
hr = pAudioClient->SetEventHandle(pDriver->eventDrivenEvent);
1437+
RETURN_ON_ERROR(hr)
1438+
}
1439+
if (pDriver->eventDrivenEvent) ResetEvent(pDriver->eventDrivenEvent); //make sure event is not signaled AudioClient start is called
14321440

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

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

16381647
HRESULT hr=S_OK;
16391648
IMMDeviceEnumerator *pEnumerator = NULL;
@@ -1696,25 +1705,21 @@ ASIOBool ASIO2WASAPI::init(void* sysRef)
16961705
BOOL rc = FindStreamFormat(m_pDevice, m_nChannels, m_nSampleRate, m_nBufferSize, m_wasapiExclusiveMode, m_wasapiEnableResampling, m_wasapiLowLatencySharedMode, &m_waveFormat, &m_pAudioClient);
16971706
if (!rc)
16981707
{
1699-
if (!m_wasapiExclusiveMode && !m_wasapiEnableResampling)
1708+
IAudioClient* pAudioClient = NULL;
1709+
hr = m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pAudioClient);
1710+
CReleaser r(pAudioClient);
1711+
1712+
WAVEFORMATEX* devFormat;
1713+
hr = pAudioClient->GetMixFormat(&devFormat);
1714+
if (SUCCEEDED(hr))
17001715
{
1701-
IAudioClient* pAudioClient = NULL;
1702-
hr = m_pDevice->Activate(
1703-
IID_IAudioClient, CLSCTX_ALL,
1704-
NULL, (void**)&pAudioClient);
1705-
CReleaser r(pAudioClient);
1706-
1707-
WAVEFORMATEX* devFormat;
1708-
hr = pAudioClient->GetMixFormat(&devFormat);
1709-
if (SUCCEEDED(hr))
1710-
{
1711-
m_nChannels = devFormat->nChannels;
1712-
m_nSampleRate = devFormat->nSamplesPerSec;
1713-
CoTaskMemFree(devFormat);
1714-
}
1715-
FindStreamFormat(m_pDevice, m_nChannels, m_nSampleRate, m_nBufferSize, m_wasapiExclusiveMode, m_wasapiEnableResampling, m_wasapiLowLatencySharedMode, &m_waveFormat, &m_pAudioClient);
1716-
}
1717-
else
1716+
m_nChannels = !m_wasapiExclusiveMode ? devFormat->nChannels : 2;
1717+
m_nSampleRate = devFormat->nSamplesPerSec;
1718+
CoTaskMemFree(devFormat);
1719+
rc = FindStreamFormat(m_pDevice, m_nChannels, m_nSampleRate, m_nBufferSize, m_wasapiExclusiveMode, m_wasapiEnableResampling, m_wasapiLowLatencySharedMode, &m_waveFormat, &m_pAudioClient);
1720+
}
1721+
1722+
if (!rc)
17181723
{//go through all devices and try to find the one that works for 16/48K
17191724
SAFE_RELEASE(m_pDevice)
17201725
setMostReliableFormat();
@@ -1815,23 +1820,25 @@ ASIOError ASIO2WASAPI::setSampleRate (ASIOSampleRate sampleRate)
18151820

18161821
ASIOError err = canSampleRate(sampleRate);
18171822
if (err != ASE_OK)
1818-
return err;
1823+
return err;
18191824

1820-
int nPrevSampleRate = m_nSampleRate;
1821-
m_nSampleRate = (int)sampleRate;
1822-
writeToRegistry();
18231825
if (m_callbacks)
18241826
{//ask the host ro reset us
1827+
int nPrevSampleRate = m_nSampleRate;
1828+
m_nSampleRate = (int)sampleRate;
1829+
writeToRegistry();
18251830
m_nSampleRate = nPrevSampleRate;
1826-
m_callbacks->asioMessage(kAsioResetRequest,0,NULL,NULL);
1831+
m_callbacks->asioMessage(kAsioResetRequest, 0, NULL, NULL);
18271832
}
1828-
else
1833+
else return ASE_NoClock;
1834+
/* 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.
18291835
{//reinitialize us with the new sample rate
18301836
HWND hAppWindowHandle = m_hAppWindowHandle;
18311837
shutdown();
18321838
readFromRegistry();
18331839
init(hAppWindowHandle);
18341840
}
1841+
*/
18351842

18361843
return ASE_OK;
18371844
}

Source/Driver/ASIO2WASAPI.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ class ASIO2WASAPI : public IASIO, public CUnknown
144144
void setUseDefaultDevice(bool value) { m_useDefaultDevice = value; };
145145
private:
146146
//for default device changed notification
147-
CMMNotificationClient* pNotificationClient;
147+
CMMNotificationClient* pNotificationClient = NULL;
148+
HANDLE eventDrivenEvent = NULL;
148149

149150
static void PlayThreadProc(LPVOID pThis);
150151
static void PlayThreadProcShared(LPVOID pThis);
@@ -178,7 +179,7 @@ class ASIO2WASAPI : public IASIO, public CUnknown
178179
HWND m_hControlPanelHandle;
179180

180181
//WASAPI specific
181-
bool m_useDefaultDevice;
182+
bool m_useDefaultDevice = true;
182183
AUDCLNT_SHAREMODE m_wasapiExclusiveMode = AUDCLNT_SHAREMODE_EXCLUSIVE;
183184
BOOL m_wasapiEnableResampling = FALSE;
184185
BOOL m_wasapiLowLatencySharedMode = FALSE;

0 commit comments

Comments
 (0)