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,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_