new audio engine backend for native CoreAudio audio I/O, and PortMIDI for MIDI.

Code builds, runs and functions. Full code review still pending, and some possibly changes to organization of code within the backend is possible
This commit is contained in:
Paul Davis 2014-02-24 14:39:10 -05:00
parent 0a6af1420f
commit 1de00ab6bb
84 changed files with 21936 additions and 0 deletions

View file

@ -0,0 +1,49 @@
/*
Copyright (C) 2013 Waves Audio Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __IncludeWindows_h__
#define __IncludeWindows_h__
#ifdef _WINDOWS
/* Copy to include
#include "IncludeWindows.h"
*/
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0601 // Windows 7
#endif
#ifndef WINVER
#define WINVER 0x0601 // Windows 7
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX // DO NOT REMOVE NOMINMAX - DOING SO CAUSES CONFLICTS WITH STD INCLUDES (<limits> ...)
#endif
#include <WinSock2.h>
#include <Windows.h>
#include <objbase.h>
#endif // #if _WINDOWS
#endif // #ifndef __IncludeWindows_h__

View file

@ -0,0 +1,743 @@
/*
Copyright (C) 2013 Waves Audio Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
//----------------------------------------------------------------------------------
//
//
//! \file WCMRAudioDeviceManager.cpp
//!
//! WCMRAudioDeviceManager and related class declarations
//!
//---------------------------------------------------------------------------------*/
#include "WCMRAudioDeviceManager.h"
//**********************************************************************************************
// WCMRAudioDevice::WCMRAudioDevice
//
//! Constructor for the audio device. The derived classes will need to do more actual work, such
//! as determining supported sampling rates, buffer sizes, and channel counts. Connection
//! and streaming will also be provided by the derived implementations.
//!
//! \param *pManager : The audio device manager that's managing this device.
//!
//! \return Nothing.
//!
//**********************************************************************************************
WCMRAudioDevice::WCMRAudioDevice (WCMRAudioDeviceManager *pManager)
{
m_pMyManager = pManager;
m_DeviceName = "Unknown";
m_ConnectionStatus = DeviceDisconnected;
m_IsActive = false;
m_IsStreaming = false;
m_CurrentSamplingRate = -1;
m_CurrentBufferSize = 0;
m_LeftMonitorChannel = -1;
m_RightMonitorChannel = -1;
m_MonitorGain = 1.0f;
}
//**********************************************************************************************
// WCMRAudioDevice::~WCMRAudioDevice
//
//! Destructor for the audio device. It release all the connections that were created.
//!
//! \param none
//!
//! \return Nothing.
//!
//**********************************************************************************************
WCMRAudioDevice::~WCMRAudioDevice ()
{
AUTO_FUNC_DEBUG;
try
{
}
catch (...)
{
//destructors should absorb exceptions, no harm in logging though!!
DEBUG_MSG ("Exception during destructor");
}
}
//**********************************************************************************************
// WCMRAudioDevice::DeviceName
//
//! Retrieves Device's name.
//!
//! \param none
//!
//! \return The device name.
//!
//**********************************************************************************************
const std::string& WCMRAudioDevice::DeviceName () const
{
return (m_DeviceName);
}
//**********************************************************************************************
// WCMRAudioDevice::InputChannels
//
//! Retrieves Input Channel information. Note that the list may be changed at run-time.
//!
//! \param none
//!
//! \return A vector with Input Channel Names.
//!
//**********************************************************************************************
const std::vector<std::string>& WCMRAudioDevice::InputChannels ()
{
return (m_InputChannels);
}
//**********************************************************************************************
// WCMRAudioDevice::OutputChannels
//
//! Retrieves Output Channel Information. Note that the list may be changed at run-time.
//!
//! \param none
//!
//! \return A vector with Output Channel Names.
//!
//**********************************************************************************************
const std::vector<std::string>& WCMRAudioDevice::OutputChannels ()
{
return (m_OutputChannels);
}
//**********************************************************************************************
// WCMRAudioDevice::SamplingRates
//
//! Retrieves supported sampling rate information.
//!
//! \param none
//!
//! \return A vector with supported sampling rates.
//!
//**********************************************************************************************
const std::vector<int>& WCMRAudioDevice::SamplingRates ()
{
return (m_SamplingRates);
}
//**********************************************************************************************
// WCMRAudioDevice::CurrentSamplingRate
//
//! The device's current sampling rate. This may be overridden, if the device needs to
//! query the driver for the current rate.
//!
//! \param none
//!
//! \return The device's current sampling rate. -1 on error.
//!
//**********************************************************************************************
int WCMRAudioDevice::CurrentSamplingRate ()
{
return (m_CurrentSamplingRate);
}
//**********************************************************************************************
// WCMRAudioDevice::SetCurrentSamplingRate
//
//! Change the sampling rate to be used by the device. This will most likely be overridden,
//! the base class simply updates the member variable.
//!
//! \param newRate : The rate to use (samples per sec).
//!
//! \return eNoErr always. The derived classes may return error codes.
//!
//**********************************************************************************************
WTErr WCMRAudioDevice::SetCurrentSamplingRate (int newRate)
{
//changes the status.
m_CurrentSamplingRate = newRate;
return (eNoErr);
}
//**********************************************************************************************
// WCMRAudioDevice::BufferSizes
//
//! Retrieves supported buffer size information.
//!
//! \param none
//!
//! \return A vector with supported buffer sizes.
//!
//**********************************************************************************************
const std::vector<int>& WCMRAudioDevice::BufferSizes ()
{
return (m_BufferSizes);
}
//**********************************************************************************************
// WCMRAudioDevice::CurrentBufferSize
//
//! The device's current buffer size in use. This may be overridden, if the device needs to
//! query the driver for the current size.
//!
//! \param none
//!
//! \return The device's current buffer size. 0 on error.
//!
//**********************************************************************************************
int WCMRAudioDevice::CurrentBufferSize ()
{
return (m_CurrentBufferSize);
}
//**********************************************************************************************
// WCMRAudioDevice::CurrentBlockSize
//
//! Device's block size we use for holding the audio samples.
//! Usually this is equal to the buffer size, but in some cases the buffer size holds additional
//! data other then the audio buffers, like frames info in SG, so it can be overriden
//!
//! \param none
//!
//! \return The device's current block size. 0 on error.
//!
//**********************************************************************************************
int WCMRAudioDevice::CurrentBlockSize()
{
// By default - return the buffer size
return CurrentBufferSize();
}
//**********************************************************************************************
// WCMRAudioDevice::SetCurrentBufferSize
//
//! Change the buffer size to be used by the device. This will most likely be overridden,
//! the base class simply updates the member variable.
//!
//! \param newSize : The buffer size to use (in sample-frames)
//!
//! \return eNoErr always. The derived classes may return error codes.
//!
//**********************************************************************************************
WTErr WCMRAudioDevice::SetCurrentBufferSize (int newSize)
{
//This will most likely be overridden, the base class simply
//changes the member.
m_CurrentBufferSize = newSize;
return (eNoErr);
}
//**********************************************************************************************
// WCMRAudioDevice::ConnectionStatus
//
//! Retrieves the device's current connection status. This will most likely be overridden,
//! in case some driver communication is required to query the status.
//!
//! \param none
//!
//! \return A ConnectionStates value.
//!
//**********************************************************************************************
WCMRAudioDevice::ConnectionStates WCMRAudioDevice::ConnectionStatus ()
{
return (m_ConnectionStatus);
}
//**********************************************************************************************
// WCMRAudioDevice::Active
//
//! Retrieves Device activation status.
//!
//! \param none
//!
//! \return true if device is active, false otherwise.
//!
//**********************************************************************************************
bool WCMRAudioDevice::Active ()
{
return (m_IsActive);
}
//**********************************************************************************************
// WCMRAudioDevice::SetActive
//
//! Sets the device's activation status.
//!
//! \param newState : Should be true to activate, false to deactivate. This roughly corresponds
//! to opening and closing the device handle/stream/audio unit.
//!
//! \return eNoErr always, the derived classes may return appropriate error code.
//!
//**********************************************************************************************
WTErr WCMRAudioDevice::SetActive (bool newState)
{
//This will most likely be overridden, the base class simply
//changes the member.
m_IsActive = newState;
return (eNoErr);
}
//**********************************************************************************************
// WCMRAudioDevice::Streaming
//
//! Retrieves Device streaming status.
//!
//! \param none
//!
//! \return true if device is streaming, false otherwise.
//!
//**********************************************************************************************
bool WCMRAudioDevice::Streaming ()
{
return (m_IsStreaming);
}
//**********************************************************************************************
// WCMRAudioDevice::SetStreaming
//
//! Sets the device's streaming status.
//!
//! \param newState : Should be true to start streaming, false to stop streaming. This roughly
//! corresponds to calling Start/Stop on the lower level interface.
//!
//! \return eNoErr always, the derived classes may return appropriate error code.
//!
//**********************************************************************************************
WTErr WCMRAudioDevice::SetStreaming (bool newState)
{
//This will most likely be overridden, the base class simply
//changes the member.
m_IsStreaming = newState;
return (eNoErr);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
// IsProcessActive - returns true if process code is running.
// A normal audio device should return the Streaming() value
///////////////////////////////////////////////////////////////////////////////////////////////////////
bool WCMRAudioDevice::IsProcessActive()
{
return Streaming();
}
//**********************************************************************************************
// WCMRAudioDevice::DoIdle
//
//! A place for doing idle time processing. The derived classes will probably do something
//! meaningful.
//!
//! \param none
//!
//! \return eNoErr always.
//!
//**********************************************************************************************
WTErr WCMRAudioDevice::DoIdle ()
{
//We don't need to do anything here...
//the derived classes may want to use this however.
return (eNoErr);
}
//**********************************************************************************************
// WCMRAudioDevice::InputLevels
//
//! Retrieve current input levels.
//!
//! \param none
//!
//! \return A vector (the same size as input channels list) that contains current input levels.
//!
//**********************************************************************************************
const std::vector<float>& WCMRAudioDevice::InputLevels ()
{
//The derived classes may override if they need to query
//the driver for the levels.
return (m_InputLevels);
}
//**********************************************************************************************
// WCMRAudioDevice::OutputLevels
//
//! Retrieve current output levels.
//!
//! \param none
//!
//! \return A vector (the same size as output channels list) that contains current output levels.
//!
//**********************************************************************************************
const std::vector<float>& WCMRAudioDevice::OutputLevels ()
{
//The derived classes may override if they need to query
//the driver for the levels.
return (m_OutputLevels);
}
//**********************************************************************************************
// WCMRAudioDevice::GetMonitorInfo
//
//! Retrieves current monitoring information.
//!
//! \param *pLeftChannel : Pointer to receive left monitor channel index.
//! \param *pRightChannel : Pointer to receive right monitor channel index.
//! \param *pGain : Pointer to receive the gain (linear) to be applied.
//!
//! \return Nothing.
//!
//**********************************************************************************************
void WCMRAudioDevice::GetMonitorInfo (int *pLeftChannel, int *pRightChannel, float *pGain)
{
if (pLeftChannel)
*pLeftChannel = m_LeftMonitorChannel;
if (pRightChannel)
*pRightChannel = m_RightMonitorChannel;
if (pGain)
*pGain = m_MonitorGain;
return;
}
//**********************************************************************************************
// WCMRAudioDevice::SetMonitorChannels
//
//! Used to set the channels to be used for monitoring.
//!
//! \param leftChannel : Left monitor channel index.
//! \param rightChannel : Right monitor channel index.
//!
//! \return eNoErr always, the derived classes may return appropriate errors.
//!
//**********************************************************************************************
WTErr WCMRAudioDevice::SetMonitorChannels (int leftChannel, int rightChannel)
{
//This will most likely be overridden, the base class simply
//changes the member.
m_LeftMonitorChannel = leftChannel;
m_RightMonitorChannel = rightChannel;
return (eNoErr);
}
//**********************************************************************************************
// WCMRAudioDevice::SetMonitorGain
//
//! Used to set monitor gain (or atten).
//!
//! \param newGain : The new gain or atten. value to use. Specified as a linear multiplier (not dB)
//!
//! \return eNoErr always, the derived classes may return appropriate errors.
//!
//**********************************************************************************************
WTErr WCMRAudioDevice::SetMonitorGain (float newGain)
{
//This will most likely be overridden, the base class simply
//changes the member.
m_MonitorGain = newGain;
return (eNoErr);
}
//**********************************************************************************************
// WCMRAudioDevice::ShowConfigPanel
//
//! Used to show device specific config/control panel. Some interfaces may not support it.
//! Some interfaces may require the device to be active before it can display a panel.
//!
//! \param pParam : A device/interface specific parameter - optional.
//!
//! \return eNoErr always, the derived classes may return errors.
//!
//**********************************************************************************************
WTErr WCMRAudioDevice::ShowConfigPanel (void *WCUNUSEDPARAM(pParam))
{
//This will most likely be overridden...
return (eNoErr);
}
//**********************************************************************************************
// WCMRAudioDevice::SendCustomCommand
//
//! Used to Send a custom command to the audiodevice. Some interfaces may require the device
//! to be active before it can do anything in this.
//!
//! \param customCommand : A device/interface specific command.
//! \param pCommandParam : A device/interface/command specific parameter - optional.
//!
//! \return eNoErr always, the derived classes may return errors.
//!
//**********************************************************************************************
WTErr WCMRAudioDevice::SendCustomCommand (int WCUNUSEDPARAM(customCommand), void *WCUNUSEDPARAM(pCommandParam))
{
//This will most likely be overridden...
return (eNoErr);
}
//**********************************************************************************************
// WCMRAudioDevice::GetLatency
//
//! Get Latency for device.
//!
//! Use 'kAudioDevicePropertyLatency' and 'kAudioDevicePropertySafetyOffset' + GetStreamLatencies
//!
//! \param isInput : Return latency for the input if isInput is true, otherwise the output latency
//! wiil be returned.
//! \return Latency in samples.
//!
//**********************************************************************************************
uint32_t WCMRAudioDevice::GetLatency (bool isInput)
{
//This will most likely be overridden...
return 0;
}
//**********************************************************************************************
// WCMRAudioDeviceManager::WCMRAudioDeviceManager
//
//! The constructuor, most of the work will be done in the derived class' constructor.
//!
//! \param *pTheClient :
//!
//! \return Nothing.
//!
//**********************************************************************************************
WCMRAudioDeviceManager::WCMRAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter)
: m_pTheClient (pTheClient)
, m_eAudioDeviceFilter(eCurAudioDeviceFilter)
{
//The derived classes will do lot more init!
return;
}
//**********************************************************************************************
// WCMRAudioDeviceManager::~WCMRAudioDeviceManager
//
//! It clears the device list, releasing each of the device.
//!
//! \param none
//!
//! \return Nothing.
//!
//**********************************************************************************************
WCMRAudioDeviceManager::~WCMRAudioDeviceManager()
{
AUTO_FUNC_DEBUG;
try
{
//Need to call release on our devices, and erase them from list
std::vector<WCMRAudioDevice*>::iterator deviceIter;
while (m_Devices.size())
{
WCMRAudioDevice *pDeviceToRelease = m_Devices.back();
m_Devices.pop_back();
if (pDeviceToRelease)
SAFE_RELEASE (pDeviceToRelease);
}
//The derived classes may want to do additional de-int!
}
catch (...)
{
//destructors should absorb exceptions, no harm in logging though!!
DEBUG_MSG ("Exception during destructor");
}
}
//**********************************************************************************************
// WCMRAudioDeviceManager::DoIdle_Private
//
//! Used for idle time processing. This calls each device's DoIdle so that it can perform it's own idle processing.
//!
//! \param none
//!
//! \return noErr if no devices have returned an error. An error code if any of the devices returned error.
//!
//**********************************************************************************************
WTErr WCMRAudioDeviceManager::DoIdle_Private()
{
WTErr retVal = eNoErr;
//Need to call DoIdle of all our devices...
std::vector<WCMRAudioDevice*>::iterator deviceIter;
for (deviceIter = m_Devices.begin(); deviceIter != m_Devices.end(); deviceIter++)
{
WTErr thisDeviceErr = (*deviceIter)->DoIdle();
if (thisDeviceErr != eNoErr)
retVal = thisDeviceErr;
}
return (retVal);
}
//**********************************************************************************************
// WCMRAudioDeviceManager::Devices_Private
//
//! Retrieve list of devices managed by this manager.
//!
//! \param none
//!
//! \return A vector containing the list of devices.
//!
//**********************************************************************************************
const WCMRAudioDeviceList& WCMRAudioDeviceManager::Devices_Private() const
{
return (m_Devices);
}
//**********************************************************************************************
// *WCMRAudioDeviceManager::GetDeviceByName_Private
//
//! Locates a device based on device name.
//!
//! \param nameToMatch : Device to look for.
//!
//! \return Pointer to the device object if found, NULL otherwise.
//!
//**********************************************************************************************
WCMRAudioDevice *WCMRAudioDeviceManager::GetDeviceByName_Private(const std::string& nameToMatch) const
{
//Need to check all our devices...
WCMRAudioDevice *pRetVal = NULL;
WCMRAudioDeviceListConstIter deviceIter;
for (deviceIter = m_Devices.begin(); deviceIter != m_Devices.end(); deviceIter++)
{
if ((*deviceIter)->DeviceName() == nameToMatch)
{
pRetVal = *deviceIter;
break;
}
}
return (pRetVal);
}
//**********************************************************************************************
// *WCMRAudioDeviceManager::GetDefaultDevice
//
//! Locates a device based on device name.
//!
//! \param nameToMatch : Device to look for.
//!
//! \return Pointer to the device object if found, NULL otherwise.
//!
//**********************************************************************************************
WCMRAudioDevice *WCMRAudioDeviceManager::GetDefaultDevice_Private()
{
//Need to check all our devices...
WCMRAudioDevice *pRetVal = NULL;
WCMRAudioDeviceListIter deviceIter = m_Devices.begin();
if(deviceIter != m_Devices.end())
{
pRetVal = *deviceIter;
}
return (pRetVal);
}
//**********************************************************************************************
// WCMRAudioDeviceManager::NotifyClient
//
//! A helper routine used to call the client for notification.
//!
//! \param forReason : The reason for notification.
//! \param *pParam : A parameter (if required) for notification.
//!
//! \return Nothing.
//!
//**********************************************************************************************
void WCMRAudioDeviceManager::NotifyClient (WCMRAudioDeviceManagerClient::NotificationReason forReason, void *pParam)
{
if (m_pTheClient)
m_pTheClient->AudioDeviceManagerNotification (forReason, pParam);
return;
}

View file

@ -0,0 +1,266 @@
/*
Copyright (C) 2013 Waves Audio Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
//----------------------------------------------------------------------------------
//
//
//! \file WCMRAudioDeviceManager.h
//!
//! WCMRAudioDeviceManager and related class declarations
//!
//---------------------------------------------------------------------------------*/
#ifndef __WCMRAudioDeviceManager_h_
#define __WCMRAudioDeviceManager_h_
/* Copy to include
#include "WCMRAudioDeviceManager.h"
*/
#define AUTO_FUNC_DEBUG
#define DEBUG_MSG(a)
#define ASSERT_ERROR(a, b)
#define TRACE_MSG(a)
#include <string>
#include <vector>
#include <map>
#include "WCRefManager.h"
#include "BasicTypes/WUTypes.h"
#include "WUErrors.h"
#define WCUNUSEDPARAM(a)
//forward decl.
class WCMRAudioConnection;
class WCMRAudioDevice;
class WCMRAudioDeviceManager;
typedef std::vector<WCMRAudioDevice *> WCMRAudioDeviceList; ///< Vector for audio devices
typedef std::vector<WCMRAudioDevice *>::iterator WCMRAudioDeviceListIter; ///< Vector iterator for audio devices
typedef std::vector<WCMRAudioDevice *>::const_iterator WCMRAudioDeviceListConstIter; ///< Vector iterator for audio devices
typedef std::vector<WCMRAudioConnection *> WCMRAudioConnectionsList; ///< Vector for audio devices
/// for notification... A client must derive it's class from us.
class WCMRAudioDeviceManagerClient
{
public:
enum NotificationReason
{
DeviceListChanged,
Dropout,
RequestReset,
RequestResync,
SamplingRateChanged, //param has new SR, or -1 if not known
SamplingRateChangedSilent, //To indicate sampling rate changed but no need to notify user
BufferSizeChanged,
ClockSourceChanged,
DeviceStoppedStreaming,
DeviceDroppedSamples,
DeviceConnectionLost,
DeviceGenericError,
DeviceStatusChanged,
DeviceStatisticsUpdated,
DeviceDebugInfo, //param has c string
DeviceProgressInfo, //param has c string
MIDIData,
MIDINodeUp,
MIDINodeDown,
DeviceSampleRateMisMatch,
SystemSamplingRateChangedInfoOnly,
LostClockSource,
IODeviceDisconnected,
ChannelCountModified,
MasterUp,
MasterDown,
AudioDropFound,
ReflasherEvent,
AGDeviceSamplingRateChangedInfoOnly,
IODeviceNameChanged,
SetDisplayNameFromIOModule,
IOMStateChanged, ///< This is used when IOM state is changed.
AudioCallback // VKamyshniy: param is AudioCallbackDataData*
};
WCMRAudioDeviceManagerClient () {}
virtual ~WCMRAudioDeviceManagerClient () {}
// VKamyshniy: This is a structure to call the client's AudioDeviceManagerNotification
// every AudioCallback time
struct AudioCallbackData
{
const float *acdInputBuffer;
float *acdOutputBuffer;
size_t acdFrames;
uint32_t acdSampleTime;
uint64_t acdCycleStartTimeNanos;
};
virtual void AudioDeviceManagerNotification (NotificationReason WCUNUSEDPARAM(reason), void *WCUNUSEDPARAM(pParam)) {}
};
class WCMRAudioDevice : public WCRefManager
{
public:
enum ConnectionStates
{
DeviceAvailable,
DeviceDisconnected,
DeviceError
};
WCMRAudioDevice (WCMRAudioDeviceManager *pManager);///<Constructor
virtual ~WCMRAudioDevice ();///<Destructor
virtual const std::string& DeviceName() const;///<Name?
virtual const std::vector<std::string>& InputChannels();///<Current Input Channel List? - note that this may change with change in sampling rate.
virtual const std::vector<std::string>& OutputChannels();///<Current Output Channel List? - note that this may change with change in sampling rate.
virtual const std::vector<int>& SamplingRates();///<Supported Sampling Rate List?
virtual int CurrentSamplingRate(); ///<Current Sampling rate.?
virtual WTErr SetCurrentSamplingRate(int newRate);///<Change Current Sampling Rate : This is a requset, might not be successful at run time!
virtual const std::vector<int>& BufferSizes();///<Supported Buffer Size List? - note that this may change with change in sampling rate.
virtual int CurrentBufferSize();///<Current Buffer Size.? - note that this may change with change in sampling rate.
virtual WTErr SetCurrentBufferSize (int newSize);///<Change Current Buffer Size : This is a requset, might not be successful at run time!
virtual int CurrentBlockSize();
virtual ConnectionStates ConnectionStatus();///< Connection Status - device available, gone, disconnected
virtual bool Active();///<Active status - mainly significant for ASIO, as certain ops can only be performed on active devices!
virtual WTErr SetActive (bool newState);///<Prepare/Activate device.
virtual bool Streaming();///<Streaming Status?
virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
virtual bool IsProcessActive();
virtual WTErr DoIdle();///<Do Idle Processing
virtual const std::vector<float>& InputLevels();///<Retrieve Input Levels (for VU display)?
virtual const std::vector<float>& OutputLevels();///<Retrieve Output Levels (for VU display)?
void GetMonitorInfo (int *pLeftChannel = NULL, int *pRightChannel = NULL, float *pGain = NULL);///<Retrieve current monitor channel pair and gain - optional, will not be available with AG
virtual WTErr SetMonitorChannels (int leftChannel, int rightChannel);///<Set monitor channels. - optional, will not be available with AG
virtual WTErr SetMonitorGain (float newGain);///<Set monitor gain. - optional, will not be available with AG
virtual WTErr ShowConfigPanel (void *pParam);///< Show Control Panel - in case of ASIO this will work only with Active device!
virtual WTErr SendCustomCommand (int customCommand, void *pCommandParam); ///< Send a custom command to the audiodevice...
virtual uint32_t GetLatency (bool isInput); ///Get latency.
protected:
WCMRAudioDeviceManager *m_pMyManager; ///< The manager who's managing this device, can be used for sending notifications!
std::string m_DeviceName; ///< Name of the device.
std::vector<std::string> m_InputChannels; ///< List of input channel names.
std::vector<std::string> m_OutputChannels; ///< List of output channel names.
std::vector<int> m_SamplingRates; ///< List of available sampling rates.
std::vector<int> m_BufferSizes; ///< List of available buffer sizes.
int m_CurrentSamplingRate; ///< Currently selected sampling rate.
int m_CurrentBufferSize; ///< Currently selected buffer size.
ConnectionStates m_ConnectionStatus; ///< Status of device connection
bool m_IsActive; ///< Flag for teh active status.
bool m_IsStreaming; ///< Flag for streaming status.
std::vector<float> m_InputLevels; ///< List of input levels.
std::vector<float> m_OutputLevels; ///< List of output levels.
int m_LeftMonitorChannel; ///< The device channel to use for monitoring left channel data.
int m_RightMonitorChannel; ///< The device channel to use for monitoring right channel data.
float m_MonitorGain; ///< Amount of gain to apply for monitoring signal.
};
// This enum is for choosing filter for audio devices scan
typedef enum eAudioDeviceFilter
{
eAllDevices = 0, // Choose all audio devices
eInputOnlyDevices, // Choose only input audio devices
eOutputOnlyDevices, // Choose only output audio devices
eFullDuplexDevices, // Choose audio devices that have both input and output channels on the same device
eMatchedDuplexDevices, // Match(aggregate) audio devices that have both input and output channels but are considered different audio devices (For mac)
eAudioDeviceFilterNum // Number of enums
} eAudioDeviceFilter;
//! WCMRAudioDeviceManager
/*! The Audio Device Manager class */
class WCMRAudioDeviceManager : public WCRefManager
{
private://< Private version of class functions which will be called by class's public function after mutex lock acquistion.
WCMRAudioDevice* GetDefaultDevice_Private();
WTErr DoIdle_Private();
const WCMRAudioDeviceList& Devices_Private() const;
WCMRAudioDevice* GetDeviceByName_Private(const std::string & nameToMatch) const;
public://< Public functions for the class.
WCMRAudioDevice* GetDefaultDevice()
{
//wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceManagerMutex);
return GetDefaultDevice_Private();
}
virtual WTErr DoIdle()
{
//wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceManagerMutex);
return DoIdle_Private();
}
const WCMRAudioDeviceList& Devices() const
{
//wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceManagerMutex);
return Devices_Private();
}
WCMRAudioDevice* GetDeviceByName(const std::string & nameToMatch) const
{
//wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceManagerMutex);
return GetDeviceByName_Private(nameToMatch);
}
public:
WCMRAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter
); ///< constructor
virtual ~WCMRAudioDeviceManager(void); ///< Destructor
virtual WTErr UpdateDeviceList () = 0; //has to be overridden!
//This is primarily for use by WCMRAudioDevice and it's descendants... We could have made it
//protected and made WCMRAudioDevice a friend, and then in some way found a way to extend
//the friendship to WCMRAudioDevice's descendants, but that would require a lot of extra
//effort!
void NotifyClient (WCMRAudioDeviceManagerClient::NotificationReason forReason, void *pParam = NULL);
virtual void EnableVerboseLogging(bool /*bEnable*/, const std::string& /*logFilePath*/) { };
protected:
//< NOTE : Mutex protection is commented, but wrapper classes are still there, in case they are required in future.
//wvNS::wvThread::ThreadMutex m_AudioDeviceManagerMutex; ///< Mutex for Audio device manager class function access.
WCMRAudioDeviceManagerClient *m_pTheClient; ///< The device manager's client, used to send notifications.
WCMRAudioDeviceList m_Devices; ///< List of all relevant devices devices
eAudioDeviceFilter m_eAudioDeviceFilter; // filter of 'm_Devices'
};
#endif //#ifndef __WCMRAudioDeviceManager_h_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,220 @@
/*
Copyright (C) 2013 Waves Audio Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
//----------------------------------------------------------------------------------
//
//
//! \file WCMRCoreAudioDeviceManager.h
//!
//! WCMRCoreAudioDeviceManager and related class declarations
//!
//---------------------------------------------------------------------------------*/
#ifndef __WCMRCoreAudioDeviceManager_h_
#define __WCMRCoreAudioDeviceManager_h_
#include "WCMRAudioDeviceManager.h"
#include "WCMRNativeAudio.h"
#include "Threads/WCThreadSafe.h"
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
#include <mach/mach.h>
#include <CoreAudio/CoreAudio.h>
//forward decl.
class WCMRCoreAudioDeviceManager;
#define WV_USE_TONE_GEN 0 ///! Set this to 1 to use a tone generator for input. See description at SetupToneGenerator for details.
// This enum is for choosing filter for audio devices scan
typedef enum eCABS_Method
{
eCABS_Simple = 0,
eCABS_DestructiveCache,
eCABS_CacheOnDeviceSet,
eCABS_MethodNum // Must be last
} eCABS_Method;
//! Manages a port audio device, providing information
//! about the device, and managing audio callbacks.
class WCMRCoreAudioDevice : public WCMRNativeAudioDevice
{
public:
WCMRCoreAudioDevice (WCMRCoreAudioDeviceManager *pManager, AudioDeviceID deviceID, bool useMultithreading = true, bool bNocopy = false);///<Constructor
virtual ~WCMRCoreAudioDevice ();///<Destructor
virtual const std::string& DeviceName() const;///<Name?
virtual const std::vector<std::string>& InputChannels();///<Current Input Channel List? - note that this may change with change in sampling rate.
virtual const std::vector<std::string>& OutputChannels();///<Current Output Channel List? - note that this may change with change in sampling rate.
virtual const std::vector<int>& SamplingRates();///<Supported Sampling Rate List?
virtual int CurrentSamplingRate(); ///<Current Sampling rate.?
virtual WTErr SetCurrentSamplingRate(int newRate);///<Change Current Sampling Rate : This is a requset, might not be successful at run time!
virtual const std::vector<int>& BufferSizes();///<Supported Buffer Size List? - note that this may change with change in sampling rate.
virtual int CurrentBufferSize();///<Current Buffer Size.? - note that this may change with change in sampling rate.
virtual WTErr SetCurrentBufferSize (int newSize);///<Change Current Buffer Size : This is a requset, might not be successful at run time!
virtual ConnectionStates ConnectionStatus();///< Connection Status - device available, gone, disconnected
virtual WTErr SetActive (bool newState);///<Prepare/Activate device.
virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
virtual WTErr DoIdle();///<Do Idle Processing
virtual WTErr SetMonitorChannels (int leftChannel, int rightChannel);///<Set monitor channels. - optional, will not be available with AG
virtual WTErr SetMonitorGain (float newGain);///<Set monitor gain. - optional, will not be available with AG
virtual WTErr ShowConfigPanel (void *pParam);///< Show Control Panel - in case of ASIO this will work only with Active device!
virtual int AudioCallback (float *pOutputBuffer, unsigned long framesPerBuffer, uint32_t inSampleTime, uint64_t inCycleStartTime);
AudioDeviceID DeviceID () {return m_DeviceID;}
virtual uint32_t GetLatency (bool isInput); ///< Get latency.
virtual OSStatus GetStreamLatency(AudioDeviceID deviceID, bool isInput, std::vector<int>& latencies);
protected:
AudioDeviceID m_DeviceID; ///< The CoreAudio device id
bool m_StopRequested; ///< should be set to true when want to stop, set to false otherwise.
float *m_pInputData; ///< This is what came in with the most recent callback.
int m_SampleCounter; ///< The current running sample counter, updated by the audio callback.
int m_SampleCountAtLastIdle; ///< What was the sample count last time we checked...
int m_StalledSampleCounter; ///< The number of idle calls with same sample count detected
int m_ChangeCheckCounter; ///< The number of idle calls passed since we checked the buffer size change.
wvNS::wvThread::timestamp m_LastCPULog; ///< The time when the last CPU details log was sent as a notification.
// unsigned int m_IOCyclesTimesTaken[MAX_IOCYCLE_TIMES]; ///< This stores the times taken by each IOCycle, in host-time units.
// int m_CurrentIOCycle; ///< The location in m_IOCyclesTymesTaken array, where the next cycle's value will go.
// int m_CyclesToAccumulate; ///< The number of cycles to accumulate the values for - maximum for last one second.
// unsigned int m_CyclePeriod; ///< The number of host time units for a cycle period - determined by buffer size and sampling rate
AudioBufferList m_InputAudioBufferList; ///< The buffer list used to get AHHAL to render input to.
AudioUnit m_AUHALAudioUnit;///< The AUHAL AudioUnit
int m_BufferSizeChangeRequested;
int m_BufferSizeChangeReported;
int m_ResetRequested;
int m_ResetReported;
int m_ResyncRequested;
int m_ResyncReported;
int m_SRChangeRequested;
int m_SRChangeReported;
int m_DropsDetected; ///< Number of times audio drops have been detected so far.
int m_DropsReported; ///< Number of times audio drops have been reported so far to the client.
bool m_IgnoreThisDrop; ///< Allows disregarding the first drop
thread_t m_IOProcThreadPort; ///< Thread handle to calculate CPU consumption.
int m_CPUCount; ///< Number of processors/core to normalize cpu consumption calculation.
#if WV_USE_TONE_GEN
//The Tone Generator...
float_t *m_pToneData;
uint32_t m_ToneDataSamples;
uint32_t m_NextSampleToUse;
#endif //WV_USE_TONE_GEN
WTErr UpdateDeviceInfo (bool updateSRSupported, bool updateBufferSizes);
WTErr UpdateDeviceName();
WTErr UpdateDeviceInputs();
WTErr UpdateDeviceOutputs();
WTErr UpdateDeviceSampleRates();
WTErr UpdateDeviceBufferSizes();
WTErr SetWorkingBufferSize(int newSize);
OSStatus SetBufferSizesByIO(int newSize);
WTErr SetAndCheckCurrentSamplingRate (int newRate);
WTErr EnableAudioUnitIO();
WTErr virtual EnableListeners();
WTErr virtual DisableListeners();
WTErr SetupAUHAL();
WTErr TearDownAUHAL();
#if WV_USE_TONE_GEN
void SetupToneGenerator ();
#endif //WV_USE_TONE_GEN
static OSStatus StaticAudioIOProc(void *inRefCon, AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
AudioBufferList *ioData);
OSStatus AudioIOProc(AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
AudioBufferList *ioData);
static OSStatus StaticPropertyChangeProc (AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput,
AudioDevicePropertyID inPropertyID, void *inClientData);
void PropertyChangeProc (AudioDevicePropertyID inPropertyID);
private:
};
//! WCMRCoreAudioDeviceManager
/*! The CoreAudio Device Manager class */
class WCMRCoreAudioDeviceManager : public WCMRAudioDeviceManager
{
public:
WCMRCoreAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter,
bool useMultithreading = true, eCABS_Method eCABS_method = eCABS_Simple, bool bNocopy = false); ///< constructor
virtual ~WCMRCoreAudioDeviceManager(void); ///< Destructor
virtual WTErr UpdateDeviceList() //has to be overridden!
{
//wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceManagerMutex);
return UpdateDeviceList_Private();
}
virtual eCABS_Method GetBufferSizeMethod()
{
//wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceManagerMutex);
return GetBufferSizeMethod_Private();
}
virtual WTErr DoIdle();
private:
WTErr UpdateDeviceList_Private();
eCABS_Method GetBufferSizeMethod_Private() { return m_eCABS_Method; }
protected:
int m_UpdateDeviceListRequested; ///< Number of times device list change has been detected.
int m_UpdateDeviceListProcessed; ///< Number of times device list change has been processed.
bool m_UseMultithreading; ///< Flag indicates whether to use multi-threading for audio processing.
bool m_bNoCopyAudioBuffer;
eCABS_Method m_eCABS_Method; // Type of core audio buffer size list method
static OSStatus StaticPropertyChangeProc (AudioHardwarePropertyID inPropertyID, void* inClientData);
OSStatus PropertyChangeProc (AudioHardwarePropertyID inPropertyID);
void remove_pattern(const std::string& original_str, const std::string& pattern_str, std::string& return_str);
};
#endif //#ifndef __WCMRCoreAudioDeviceManager_h_

View file

@ -0,0 +1,270 @@
/*
Copyright (C) 2013 Waves Audio Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
//----------------------------------------------------------------------------------
//
//
//! \file WCMRNativeAudio.cpp
//!
//! WCMRNativeAudioConnection and related class defienitions
//!
//---------------------------------------------------------------------------------*/
#if defined(__MACOS__)
#include <CoreAudio/CoreAudio.h>
#endif
#include "WCMRNativeAudio.h"
#include "MiscUtils/safe_delete.h"
#include <sstream>
#include <boost/assign/list_of.hpp>
#define NONE_DEVICE_NAME "None"
#define NONE_DEVICE_INPUT_NAMES "Input "
#define NONE_DEVICE_OUTPUT_NAMES "Output "
//**********************************************************************************************
// WCMRNativeAudioNoneDevice::WCMRNativeAudioNoneDevice
//
//! Constructor for the dummy "None" device. This constructor simply adds supported SRs,
//! buffer sizes, and channels, so that it may look like a real native device to
//! the applications.
//!
//! \param pManager : The managing device manager - simply passed on to the base class.
//!
//!
//**********************************************************************************************
WCMRNativeAudioNoneDevice::WCMRNativeAudioNoneDevice (WCMRAudioDeviceManager *pManager)
: WCMRNativeAudioDevice (pManager, false /*useMultiThreading*/)
, m_SilenceThread(0)
#if defined (_WINDOWS)
, _waitableTimerForUsleep (CreateWaitableTimer(NULL, TRUE, NULL))
#endif
{
m_DeviceName = NONE_DEVICE_NAME;
m_SamplingRates = boost::assign::list_of (m_CurrentSamplingRate=44100)(48000)(88200)(96000);
m_BufferSizes = boost::assign::list_of (32)(64)(128)(m_CurrentBufferSize=256)(512)(1024);
for (int channel = 0; channel < __m_NumInputChannels; channel++)
{
std::stringstream name;
name << NONE_DEVICE_INPUT_NAMES;
name << (channel + 1);
m_InputChannels.push_back(name.str());
}
for (int channel = 0; channel < __m_NumOutputChannels; channel++)
{
std::stringstream name;
name << NONE_DEVICE_INPUT_NAMES;
name << (channel + 1);
m_OutputChannels.push_back(name.str());
}
_m_inputBuffer = new float[__m_NumInputChannels * m_BufferSizes.back()];
_m_outputBuffer = new float[__m_NumOutputChannels * m_BufferSizes.back()];
}
WCMRNativeAudioNoneDevice::~WCMRNativeAudioNoneDevice ()
{
#if defined (_WINDOWS)
if(_waitableTimerForUsleep) {
CloseHandle(_waitableTimerForUsleep);
}
#endif
}
WTErr WCMRNativeAudioNoneDevice::SetActive (bool newState)
{
//This will most likely be overridden, the base class simply
//changes the member.
if (Active() == newState)
{
return (eNoErr);
}
if (Active() && Streaming())
{
SetStreaming(false);
}
return WCMRAudioDevice::SetActive(newState);
}
WTErr WCMRNativeAudioNoneDevice::SetCurrentBufferSize (int newSize)
{
//changes the status.
int oldSize = CurrentBufferSize();
bool oldActive = Active();
//same size, nothing to do.
if (oldSize == newSize)
return eNoErr;
//see if this is one of our supported rates...
std::vector<int>::iterator intIter = find(m_BufferSizes.begin(), m_BufferSizes.end(), newSize);
if (intIter == m_BufferSizes.end())
{
//Can't change, perhaps use an "invalid param" type of error
return eCommandLineParameter;
}
if (Streaming())
{
//Can't change, perhaps use an "in use" type of error
return eGenericErr;
}
return WCMRAudioDevice::SetCurrentBufferSize(newSize);
}
WTErr WCMRNativeAudioNoneDevice::SetStreaming (bool newState)
{
if (Streaming() == newState)
{
return (eNoErr);
}
WCMRAudioDevice::SetStreaming(newState);
if(Streaming())
{
if (m_SilenceThread)
std::cerr << "\t\t\t\t\t !!!!!!!!!!!!!!! Warning: the inactive NONE-DEVICE was streaming!" << std::endl;
pthread_attr_t attributes;
size_t stack_size = 100000;
#ifdef __MACOS__
stack_size = (((stack_size - 1) / PTHREAD_STACK_MIN) + 1) * PTHREAD_STACK_MIN;
#endif
if (pthread_attr_init (&attributes)) {
std::cerr << "WCMRNativeAudioNoneDevice::SetStreaming (): pthread_attr_init () failed!" << std::endl;
return eGenericErr;
}
if (pthread_attr_setstacksize (&attributes, stack_size)) {
std::cerr << "WCMRNativeAudioNoneDevice::SetStreaming (): pthread_attr_setstacksize () failed!" << std::endl;
return eGenericErr;
}
if (pthread_create (&m_SilenceThread, &attributes, __SilenceThread, this)) {
m_SilenceThread = 0;
std::cerr << "WCMRNativeAudioNoneDevice::SetStreaming (): pthread_create () failed!" << std::endl;
return eGenericErr;
}
}
else
{
if (!m_SilenceThread)
{
std::cerr << "\t\t\t\t\t !!!!!!!!!!!!!!! Warning: the active NONE-DEVICE was NOT streaming!" << std::endl;
}
while (m_SilenceThread)
{
_usleep(1); //now wait for ended thread;
}
}
return eNoErr;
}
void WCMRNativeAudioNoneDevice::_SilenceThread()
{
#if defined(_WINDOWS)
float* theInpBuffers[__m_NumInputChannels];
for(int i = 0; i < __m_NumInputChannels; ++i)
{
theInpBuffers[i] = _m_inputBuffer + m_BufferSizes.back() * i;
}
#else
float* theInpBuffers = _m_inputBuffer;
#endif
uint32_t currentSampleTime = 0;
const size_t buffer_size = CurrentBufferSize();
const uint64_t cyclePeriodNanos = (1000000000.0 * buffer_size) / CurrentSamplingRate();
struct WCMRAudioDeviceManagerClient::AudioCallbackData audioCallbackData =
{
(const float*)theInpBuffers,
_m_outputBuffer,
buffer_size,
0,
0
};
audioCallbackData.acdCycleStartTimeNanos =__get_time_nanos();
// VERY ROUGH IMPLEMENTATION:
while(Streaming()) {
uint64_t cycleEndTimeNanos = audioCallbackData.acdCycleStartTimeNanos + cyclePeriodNanos;
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::AudioCallback, (void *)&audioCallbackData);
currentSampleTime += buffer_size;
int64_t timeToSleepUsecs = ((int64_t)cycleEndTimeNanos - (int64_t)__get_time_nanos())/1000;
if (timeToSleepUsecs > 0) {
_usleep (timeToSleepUsecs);
}
audioCallbackData.acdCycleStartTimeNanos = cycleEndTimeNanos+1;
}
m_SilenceThread = 0;
}
void* WCMRNativeAudioNoneDevice::__SilenceThread(void *This)
{
((WCMRNativeAudioNoneDevice*)This)->_SilenceThread();
return 0;
}
#if defined(_WINDOWS)
void WCMRNativeAudioNoneDevice::_usleep(uint64_t duration_usec)
{
LARGE_INTEGER ft;
ft.QuadPart = -(10*duration_usec); // Convert to 100 nanosecond interval, negative value indicates relative time
SetWaitableTimer(_waitableTimerForUsleep, &ft, 0, NULL, NULL, 0);
WaitForSingleObject(_waitableTimerForUsleep, INFINITE);
}
#endif
uint64_t
WCMRNativeAudioNoneDevice::__get_time_nanos ()
{
#ifdef __MACOS__
// here we exploit the time counting API which is used by the WCMRCoreAudioDeviceManager. However,
// the API should be a part of WCMRCoreAudioDeviceManager to give a chance of being tied to the
// audio device transport timeß.
return AudioConvertHostTimeToNanos (AudioGetCurrentHostTime ());
#elif _WINDOWS
LARGE_INTEGER Frequency, Count ;
QueryPerformanceFrequency (&Frequency) ;
QueryPerformanceCounter (&Count);
return uint64_t ((Count.QuadPart * 1000000000.0 / Frequency.QuadPart));
#endif
}

View file

@ -0,0 +1,90 @@
/*
Copyright (C) 2013 Waves Audio Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
//----------------------------------------------------------------------------------
//
//
//! \file WCMRNativeAudio.h
//!
//! WCMRNativeAudio and related class declarations
//!
//---------------------------------------------------------------------------------*/
#ifndef __WCMRNativeAudio_h_
#define __WCMRNativeAudio_h_
#if defined(_WINDOWS)
#include "windows.h"
#endif
#include "pthread.h"
#include "WCRefManager.h"
#include "WCMRAudioDeviceManager.h"
class WCMRNativeAudioDevice; //forward
class WCMRNativeAudioDevice : public WCMRAudioDevice
{
public:
WCMRNativeAudioDevice (WCMRAudioDeviceManager *pManager, bool useMultithreading = true, bool bNoCopy = false) : WCMRAudioDevice (pManager),
m_UseMultithreading (useMultithreading),
m_bNoCopyAudioBuffer(bNoCopy)
{}
virtual ~WCMRNativeAudioDevice () {}
protected:
bool m_UseMultithreading;
bool m_bNoCopyAudioBuffer; ///< This flag determines whether the audio callback performs a copy of audio, or the source/sink perform the copy. It should be true to let source/sink do the copies.
};
//! A dummy device to allow apps to choose "None" in case no real device connection is required.
class WCMRNativeAudioNoneDevice : public WCMRNativeAudioDevice
{
public:
WCMRNativeAudioNoneDevice (WCMRAudioDeviceManager *pManager);
virtual ~WCMRNativeAudioNoneDevice ();
virtual WTErr SetActive (bool newState);///<Prepare/Activate device.
virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
virtual WTErr SetCurrentBufferSize (int newSize);///<Change Current Buffer Size : This is a requset, might not be successful at run time!
private:
static void* __SilenceThread(void *This);
void _SilenceThread();
#if defined(_WINDOWS)
void _usleep(uint64_t usec);
#else
inline void _usleep(uint64_t usec) { ::usleep(usec); }
#endif
static const size_t __m_NumInputChannels = 32;
static const size_t __m_NumOutputChannels = 32;
pthread_t m_SilenceThread;
float *_m_inputBuffer;
float *_m_outputBuffer;
static uint64_t __get_time_nanos ();
#if defined (_WINDOWS)
HANDLE _waitableTimerForUsleep;
#endif
};
#endif //#ifndef __WCMRNativeAudio_h_