[Summary] Improved backend workflow, added synchronization for cases when device reset happens on device parameter change

This commit is contained in:
Greg Zharun 2014-08-31 13:42:18 +03:00
parent 295f361f5e
commit 91fcacd150
12 changed files with 348 additions and 299 deletions

View file

@ -12,14 +12,16 @@
#include "UMicroseconds.h"
#include <sstream>
#include <algorithm>
#include <list>
using namespace wvNS;
#include "IncludeWindows.h"
#include <MMSystem.h>
#include "pa_asio.h"
#include "asio.h"
#define PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS 200
#define PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS 500
#define PROPERTY_CHANGE_TIMEOUT_SECONDS 2
#define PROPERTY_CHANGE_RETRIES 3
///< Supported Sample rates
static const double gAllSampleRates[] =
@ -307,14 +309,12 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
//update name.
m_DeviceName = pDeviceInfo->name;
std::cout << "API::Device " << m_DeviceName << " Getting device info " << std::endl;
//following parameters are needed opening test stream and for sample rates validation
PaStreamParameters inputParameters, outputParameters;
PaStreamParameters *pInS = NULL, *pOutS = NULL;
inputParameters.device = m_DeviceID;
inputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxInputChannels);
inputParameters.channelCount = pDeviceInfo->maxInputChannels;
inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
inputParameters.hostApiSpecificStreamInfo = 0;
@ -323,7 +323,7 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
pInS = &inputParameters;
outputParameters.device = m_DeviceID;
outputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxOutputChannels);
outputParameters.channelCount = pDeviceInfo->maxOutputChannels;
outputParameters.sampleFormat = paFloat32;
outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
outputParameters.hostApiSpecificStreamInfo = 0;
@ -331,7 +331,6 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
if (outputParameters.channelCount)
pOutS = &outputParameters;
std::cout << "API::Device" << m_DeviceName << " Updating sample rates " << std::endl;
////////////////////////////////////////////////////////////////////////////////////
//update list of supported SRs...
m_SamplingRates.clear();
@ -347,54 +346,27 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
}
}
std::cout << "API::Device" << m_DeviceName << " Updating buffer sizes" << std::endl;
///////////////////////////////////////////////////////////////////////////////////
//update buffer sizes
m_BufferSizes.clear();
bool useDefaultBuffers = true;
PaError paErr = paNoError;
//sometimes devices change buffer size if sample rate changes
//it updates buffer size during stream opening
//we need to find out how device would behave with current sample rate
//try opening test stream to load device driver for current sample rate and buffer size
//(skip this step if the device is Active)
if ( !Active() )
{
if (paNoError != testStateValidness(m_CurrentSamplingRate, m_CurrentBufferSize) )
{
//buffer size did change
Pa_Terminate();
Pa_Initialize();
// test validness with current sample rate and device prefered buffer size
paErr = testStateValidness(m_CurrentSamplingRate, 0);
}
}
if (paErr == paNoError)
{
// In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel
long minSize, maxSize, preferredSize, granularity;
paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
// In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel
long minSize, maxSize, preferredSize, granularity;
PaError err = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
if (paErr == paNoError)
{
std::cout << "API::Device " << m_DeviceName << " Buffers: " << minSize << " " << maxSize << " " << preferredSize << std::endl;
if (err == paNoError)
{
std::cout << "API::Device " << m_DeviceName << " Buffers: " << minSize << " " << maxSize << " " << preferredSize << std::endl;
m_BufferSizes.push_back (preferredSize);
useDefaultBuffers = false;
}
else
{
std::cout << "API::Device" << m_DeviceName << " Preffered buffer size is not supported" << std::endl;
}
m_BufferSizes.push_back (preferredSize);
useDefaultBuffers = false;
}
else
{
std::cout << "API::Device" << m_DeviceName << " Device does not start with sample rate: "<< m_CurrentSamplingRate << " and default buffer size" << std::endl;
std::cout << "API::Device" << m_DeviceName << " Preffered buffer size is not supported" << std::endl;
}
if (useDefaultBuffers)
{
std::cout << "API::Device" << m_DeviceName << " Using default buffer sizes " <<std::endl;
@ -475,18 +447,18 @@ PaError WCMRPortAudioDevice::testStateValidness(int sampleRate, int bufferSize)
PaStreamParameters *pInS = NULL, *pOutS = NULL;
inputParameters.device = m_DeviceID;
inputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxInputChannels);
inputParameters.channelCount = pDeviceInfo->maxInputChannels;
inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
inputParameters.suggestedLatency = 0;
inputParameters.hostApiSpecificStreamInfo = 0;
if (inputParameters.channelCount)
pInS = &inputParameters;
outputParameters.device = m_DeviceID;
outputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxOutputChannels);
outputParameters.channelCount = pDeviceInfo->maxOutputChannels;
outputParameters.sampleFormat = paFloat32;
outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
outputParameters.suggestedLatency = 0;
outputParameters.hostApiSpecificStreamInfo = 0;
if (outputParameters.channelCount)
@ -498,7 +470,7 @@ PaError WCMRPortAudioDevice::testStateValidness(int sampleRate, int bufferSize)
//it updates buffer size during stream opening
//we need to find out how device would behave with current sample rate
//try opening test stream to load device driver for current sample rate and buffer size
paErr = Pa_OpenStream (&portAudioStream, pInS, pOutS, m_CurrentSamplingRate, m_CurrentBufferSize, paDitherOff, NULL, NULL);
paErr = Pa_OpenStream (&portAudioStream, pInS, pOutS, sampleRate, bufferSize, paDitherOff, NULL, NULL);
if (portAudioStream)
{
@ -627,35 +599,17 @@ WTErr WCMRPortAudioDevice::SetCurrentSamplingRate (int newRate)
return (retVal);
}
if (oldActive)
{
//Deactivate it for the change...
SetActive (false);
}
//make the change...
m_CurrentSamplingRate = newRate;
PaError paErr = PaAsio_SetStreamSampleRate (m_PortAudioStream, m_CurrentSamplingRate);
// Before reactivating the device: opening stream we should try getting buffer size update from the device
// because for new sampling rate some devices may change buffer size as well
int oldBufferSize = m_CurrentBufferSize;
retVal = ResetDevice();
//reactivate it.
if (oldActive && retVal == eNoErr)
if (paErr != paNoError)
{
retVal = SetActive (true);
}
std::cout << "Sample rate change failed, cannot start with error: " << Pa_GetErrorText (paErr) << std::endl;
if (paErr == paUnanticipatedHostError)
std::cout << "Details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
if (retVal != eNoErr)
{
//revert changes if the device was not activated
m_CurrentSamplingRate = oldRate;
m_CurrentBufferSize = oldBufferSize;
int bufferSize = m_CurrentBufferSize;
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
retVal = eCommandLineParameter;
retVal = eWrongObjectState;
}
return (retVal);
@ -704,6 +658,15 @@ WTErr WCMRPortAudioDevice::SetCurrentBufferSize (int newSize)
if (oldSize == newSize)
return (retVal);
if (Streaming())
{
//Can't change, perhaps use an "in use" type of error
retVal = eGenericErr;
return (retVal);
}
std::cout << "Setting buffer: " << newSize << std::endl;
//see if this is one of our supported rates...
intIter = find(m_BufferSizes.begin(), m_BufferSizes.end(), newSize);
if (intIter == m_BufferSizes.end())
@ -713,10 +676,12 @@ WTErr WCMRPortAudioDevice::SetCurrentBufferSize (int newSize)
{
// we have only one aloved buffer size which is preffered by PA
// this is the only value which could be set
m_CurrentBufferSize = m_BufferSizes[0];
int bufferSize = m_CurrentBufferSize;
newSize = m_BufferSizes[0];
int bufferSize = newSize;
// notify client to update sample rate after us
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
return retVal;
} else {
// more then one buffer size value is available
//Can't change, perhaps use an "invalid param" type of error
@ -725,13 +690,6 @@ WTErr WCMRPortAudioDevice::SetCurrentBufferSize (int newSize)
}
}
if (Streaming())
{
//Can't change, perhaps use an "in use" type of error
retVal = eGenericErr;
return (retVal);
}
if (oldActive)
{
//Deactivate it for the change...
@ -788,6 +746,59 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
// if device is not active activate it
if (!Active() )
{
std::list<long> buffersSizes;
buffersSizes.push_back(m_CurrentBufferSize);
long minSize, maxSize, preferredSize, granularity;
PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
if (paErr == paNoError)
{
buffersSizes.push_front(preferredSize);
/*
size_t amountOfBuffers = sizeof(gAllBufferSizes)/sizeof(*gAllBufferSizes);
for (int i = 0; i < amountOfBuffers; ++i)
{
if (minSize <= gAllBufferSizes[i] <= maxSize)
{
buffersSizes.push_back(gAllBufferSizes[i]);
}
}*/
}
/*
// test validness with current sample rate and device prefered buffer size
if (paNoError != (paErr = testStateValidness(m_CurrentSamplingRate, m_CurrentBufferSize) ) )
{
std::cout << "State has changed, cannot start with error: " << Pa_GetErrorText (paErr) << std::endl;
if (paErr == paUnanticipatedHostError)
std::cout << "Details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
std::cout << "Updating state... " << std::endl;
// update device info
updateDeviceInfo();
// pick up buffers we'll need to try
long minSize, maxSize, preferredSize, granularity;
PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
if (paErr == paNoError)
{
buffersSizes.push_front(preferredSize);
size_t amountOfBuffers = sizeof(gAllBufferSizes)/sizeof(*gAllBufferSizes);
for (int i = 0; i < amountOfBuffers; ++i)
{
if (minSize <= gAllBufferSizes[i] <= maxSize)
{
buffersSizes.push_back(gAllBufferSizes[i]);
}
}
}
}
std::cout << "**********Tested VALIDNESS*********** " << Pa_GetErrorText (paErr) << std::endl;*/
PaStreamParameters inputParameters, outputParameters;
PaStreamParameters *pInS = NULL, *pOutS = NULL;
@ -811,12 +822,13 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
if (outputParameters.channelCount)
pOutS = &outputParameters;
std::cout << "API::Device" << m_DeviceName << " Opening device stream " << std::endl;
std::cout << "Sample rate: " << m_CurrentSamplingRate << " buffer size: " << m_CurrentBufferSize << std::endl;
int tryAgain = ((PROPERTY_CHANGE_TIMEOUT_SECONDS * 1000) / PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS) ;
while (tryAgain) {
// try opening stream with current buffer and the rest if not successful
std::list<long>::const_iterator bufferIter = buffersSizes.begin();
for (; bufferIter != buffersSizes.end(); ++bufferIter) {
std::cout << "API::Device" << m_DeviceName << " Opening device stream " << std::endl;
std::cout << "Sample rate: " << m_CurrentSamplingRate << " buffer size: " << *bufferIter << std::endl;
paErr = Pa_OpenStream(&m_PortAudioStream,
pInS,
pOutS,
@ -825,20 +837,37 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
paDitherOff,
WCMRPortAudioDevice::TheCallback,
this);
if(paErr == paNoError)
{
break;
}
std::cout << "Cannot open streamm sleeping for "<< PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS << "msec and trying again" << std::endl;
// sleep and try again
wvThread::sleep_milliseconds (PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS);
--tryAgain;
std::cout << "Cannot open streamm with buffer: "<< *bufferIter << " Error: " << Pa_GetErrorText (paErr) << std::endl;
if (paErr == paUnanticipatedHostError)
std::cout << "Error details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
}
if(paErr == paNoError)
{
std::cout << "***************Stream has been opened ****************************"<< std::endl;
long minSize, maxSize, preferredSize, granularity;
PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
if (paErr == paNoError && m_CurrentBufferSize != preferredSize)
{
std::cout << "***************Buffer changed ****************************"<< std::endl;
m_CurrentBufferSize = preferredSize;
m_BufferSizes.clear();
m_BufferSizes.push_back(preferredSize);
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&preferredSize);
} else
{
std::cout << "***************Buffer DIDn't changed ****************************"<< std::endl;
}
m_DropsDetected = 0;
m_DropsReported = 0;
m_IgnoreThisDrop = true;
@ -860,8 +889,8 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
else
{
//failed, do not update device state
std::cout << "Failed to open pa stream " << paErr << std::endl;
DEBUG_MSG( "Failed to open pa stream " << paErr );
std::cout << "Failed to open pa stream: " << Pa_GetErrorText (paErr) << std::endl;
DEBUG_MSG( "Failed to open pa stream: " << Pa_GetErrorText (paErr) );
m_ConnectionStatus = DeviceErrors;
m_lastErr = eAsioFailed;
}
@ -921,8 +950,8 @@ void WCMRPortAudioDevice::deactivateDevice (bool callerIsWaiting/*=false*/)
else
{
//failed, do not update device state
std::cout << "Failed to close pa stream stream " << paErr << std::endl;
DEBUG_MSG( "Failed to open pa stream stream " << paErr );
std::cout << "Failed to close pa stream stream " << Pa_GetErrorText (paErr) << std::endl;
DEBUG_MSG( "Failed to open pa stream stream " << Pa_GetErrorText (paErr) );
m_ConnectionStatus = DeviceErrors;
m_lastErr = eAsioFailed;
}
@ -953,17 +982,25 @@ void WCMRPortAudioDevice::startStreaming (bool callerIsWaiting/*=false*/)
m_SampleCounter = 0;
std::cout << "API::Device" << m_DeviceName << " Starting device stream" << std::endl;
//get device info
const PaDeviceInfo *pDeviceInfo = Pa_GetDeviceInfo(m_DeviceID);
unsigned int inChannelCount = pDeviceInfo->maxInputChannels;
unsigned int outChannelCount = pDeviceInfo->maxOutputChannels;
paErr = Pa_StartStream( m_PortAudioStream );
if(paErr == paNoError)
{
// if the stream was started successfully
m_IsStreaming = true;
std::cout << "API::Device" << m_DeviceName << " Device is streaming" << std::endl;
}
else
{
std::cout << "Failed to start PA stream: " << paErr << std::endl;
DEBUG_MSG( "Failed to start PA stream: " << paErr );
std::cout << "Failed to start PA stream: " << Pa_GetErrorText (paErr) << std::endl;
DEBUG_MSG( "Failed to start PA stream: " << Pa_GetErrorText (paErr) );
m_lastErr = eGenericErr;
}
}
@ -1001,8 +1038,8 @@ void WCMRPortAudioDevice::stopStreaming (bool callerIsWaiting/*=false*/)
}
else
{
std::cout << "Failed to stop PA stream: " << paErr << std::endl;
DEBUG_MSG( "Failed to stop PA stream " << paErr );
std::cout << "Failed to stop PA stream: " << Pa_GetErrorText (paErr) << std::endl;
DEBUG_MSG( "Failed to stop PA stream " << Pa_GetErrorText (paErr) );
m_lastErr = eGenericErr;
}
}
@ -1027,6 +1064,8 @@ void WCMRPortAudioDevice::resetDevice (bool callerIsWaiting /*=false*/ )
{
std::cout << "API::Device" << m_DeviceName << "Reseting device" << std::endl;
PaError paErr = paNoError;
// Keep device sates
bool wasStreaming = Streaming();
bool wasActive = Active();
@ -1035,49 +1074,72 @@ void WCMRPortAudioDevice::resetDevice (bool callerIsWaiting /*=false*/ )
stopStreaming();
deactivateDevice();
// Reinitialize PA
Pa_Terminate();
Pa_Initialize();
updateDeviceInfo();
// Cache device buffer size as it might be changed during reset
int oldBufferSize = m_CurrentBufferSize;
// In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel
// Backend should always use preffered buffer size value in this case
long minSize, maxSize, preferredSize, granularity;
PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
// Now, validate the state and update device info if required
unsigned int retry = PROPERTY_CHANGE_RETRIES;
while (retry-- )
{
// Reinitialize PA
Pa_Terminate();
Pa_Initialize();
std::cout << "Updating device state... " << std::endl;
// update device info
updateDeviceInfo();
// take up buffers
long minSize, maxSize, preferredSize, granularity;
PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
if (paErr != paNoError)
{
continue;
}
m_CurrentBufferSize = preferredSize;
paErr = testStateValidness(m_CurrentSamplingRate, m_CurrentBufferSize);
if (paNoError == paErr)
{
std::cout << "Device state is valid" << std::endl;
break;
}
std::cout << "Cannot start with current state: sr: " << m_CurrentSamplingRate << " bs:" << m_CurrentBufferSize \
<< "\nReason: " << Pa_GetErrorText (paErr) << std::endl;
if (paErr == paUnanticipatedHostError)
std::cout << "Details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
std::cout << "Will try again in " << PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS << "msec" << std::endl;
Pa_Sleep(PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS);
}
if (paErr == paNoError)
{
m_CurrentBufferSize = preferredSize;
}
else
{
// if we can't get device buffer sizes, use the first one among supported
if (m_BufferSizes.size() != 0)
m_CurrentBufferSize = m_BufferSizes.front();
}
// Notify the Application about device setting changes
if (oldBufferSize != m_CurrentBufferSize)
{
std::cout << "API::Device" << m_DeviceName << " buffer size changed" << std::endl;
int bufferSize = m_CurrentBufferSize;
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
}
// Notify the Application about device setting changes
if (oldBufferSize != m_CurrentBufferSize)
{
std::cout << "API::Device" << m_DeviceName << " buffer size changed" << std::endl;
int bufferSize = m_CurrentBufferSize;
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
}
// Activate the device if it was active before
if (wasActive)
activateDevice();
// Activate the device if it was active before
if (wasActive)
activateDevice();
// Resume streaming if the device was streaming before
if(wasStreaming)
{
// Notify the Application to prepare for the stream start
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming);
startStreaming();
// Resume streaming if the device was streaming before
if(wasStreaming && m_lastErr == eNoErr && m_ConnectionStatus == DeviceAvailable)
{
// Notify the Application to prepare for the stream start
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming);
startStreaming();
}
} else {
m_ConnectionStatus = DeviceErrors;
m_lastErr = eWrongObjectState;
}
if (callerIsWaiting)
@ -1553,6 +1615,8 @@ WTErr WCMRPortAudioDeviceManager::getDeviceAvailableSampleRates(DeviceID deviceI
sampleRates.push_back ((int)gAllSampleRates[sr]);
}
}
return eNoErr;
}
@ -1695,6 +1759,12 @@ WTErr WCMRPortAudioDeviceManager::getDeviceSampleRatesImpl(const std::string & d
WTErr retVal = eNoErr;
if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() )
{
sampleRates.assign(m_CurrentDevice->SamplingRates().begin(), m_CurrentDevice->SamplingRates().end() );
return retVal;
}
DeviceInfo devInfo;
retVal = GetDeviceInfoByName(deviceName, devInfo);
@ -1715,28 +1785,23 @@ WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & d
{
WTErr retVal = eNoErr;
std::cout << "API::PortAudioDeviceManager::GetBufferSizes: getting buffer size for device: "<< deviceName << std::endl;
buffers.clear();
//first check if the request has been made for None device
if (deviceName == m_NoneDevice->DeviceName() )
{
buffers = m_NoneDevice->BufferSizes();
buffers.assign(m_NoneDevice->BufferSizes().begin(), m_NoneDevice->BufferSizes().end() );
return retVal;
}
if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() )
{
buffers.assign(m_CurrentDevice->BufferSizes().begin(), m_CurrentDevice->BufferSizes().end() );
return retVal;
}
//if we have current device initialized and it's PA device, reset it
//this procedure will reset PA corrently and update info for all PA devices as well
bool paLocalInit = false;
WCMRPortAudioDevice* portaudioDevice = dynamic_cast<WCMRPortAudioDevice*>(m_CurrentDevice);
if (portaudioDevice)
{
portaudioDevice->ResetDevice();
}
else
{
//initialize PA to get buffers for the device
Pa_Initialize();
paLocalInit = true;
}
Pa_Initialize();
DeviceInfo devInfo;
retVal = GetDeviceInfoByName(deviceName, devInfo);
@ -1755,7 +1820,7 @@ WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & d
else
{
retVal = eAsioFailed;
std::cout << "API::PortAudioDeviceManager::GetBufferSizes: error: " << paErr << " getting buffer size fo device: "<< deviceName << std::endl;
std::cout << "API::PortAudioDeviceManager::GetBufferSizes: error: " << Pa_GetErrorText (paErr) << " getting buffer size fo device: "<< deviceName << std::endl;
}
}
else
@ -1763,9 +1828,7 @@ WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & d
std::cout << "API::PortAudioDeviceManager::GetBufferSizes: Device not found: "<< deviceName << std::endl;
}
//deinitialize PA now
if (paLocalInit)
Pa_Terminate();
Pa_Terminate();
return retVal;
}