X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/blobdiff_plain/1059e1cc0c2ecfa237406949aa26155b6a5b9154..66f23d4fabf89ad09adbd4dfc15ac6b5b2b7da83:/interpretor/preprocessor/faust-0.9.47mr3/architecture/audio/coreaudio-dsp.h diff --git a/interpretor/preprocessor/faust-0.9.47mr3/architecture/audio/coreaudio-dsp.h b/interpretor/preprocessor/faust-0.9.47mr3/architecture/audio/coreaudio-dsp.h deleted file mode 100644 index e1b952c..0000000 --- a/interpretor/preprocessor/faust-0.9.47mr3/architecture/audio/coreaudio-dsp.h +++ /dev/null @@ -1,1157 +0,0 @@ -/************************************************************************ - - IMPORTANT NOTE : this file contains two clearly delimited sections : - the ARCHITECTURE section (in two parts) and the USER section. Each section - is governed by its own copyright and license. Please check individually - each section for license and copyright information. -*************************************************************************/ - -#ifndef __coreaudio_dsp__ -#define __coreaudio_dsp__ - -/*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/ - -/************************************************************************ - FAUST Architecture File - Copyright (C) 2003-2011 GRAME, Centre National de Creation Musicale - --------------------------------------------------------------------- - This Architecture section 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 3 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, see . - - EXCEPTION : As a special exception, you may create a larger work - that contains this FAUST architecture section and distribute - that work under terms of your choice, so long as this FAUST - architecture section is not modified. - - - ************************************************************************ - ************************************************************************/ - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "audio.h" -#include "dsp.h" - -using namespace std; - -/****************************************************************************** -******************************************************************************* - - COREAUDIO INTERFACE - -******************************************************************************* -*******************************************************************************/ - -//---------------------------------------------------------------------------- -// number of physical input and output channels of the CA device -//---------------------------------------------------------------------------- - -int gDevNumInChans; -int gDevNumOutChans; - -//---------------------------------------------------------------------------- -// tables of noninterleaved input and output channels for FAUST -//---------------------------------------------------------------------------- - -float* gInChannel[256]; -float* gOutChannel[256]; - -#define OPEN_ERR -1 -#define NO_ERR 0 - -#define WAIT_COUNTER 60 - -typedef UInt8 CAAudioHardwareDeviceSectionID; -#define kAudioDeviceSectionInput ((CAAudioHardwareDeviceSectionID)0x01) -#define kAudioDeviceSectionOutput ((CAAudioHardwareDeviceSectionID)0x00) -#define kAudioDeviceSectionGlobal ((CAAudioHardwareDeviceSectionID)0x00) -#define kAudioDeviceSectionWildcard ((CAAudioHardwareDeviceSectionID)0xFF) - -dsp * gDsp; - -class TCoreAudioRenderer -{ - private: - AudioBufferList* fInputData; - AudioDeviceID fDeviceID; - AudioUnit fAUHAL; - AudioObjectID fPluginID; // Used for aggregate device - bool fState; - - OSStatus GetDefaultDevice(int inChan, int outChan, int samplerate, AudioDeviceID* id); - - OSStatus CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, int samplerate, AudioDeviceID* outAggregateDevice); - OSStatus CreateAggregateDeviceAux(vector captureDeviceID, vector playbackDeviceID, int samplerate, AudioDeviceID* outAggregateDevice); - OSStatus DestroyAggregateDevice(); - - OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name); - - int SetupSampleRateAux(AudioDeviceID inDevice, int samplerate); - - static OSStatus Render(void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList *ioData); - - - static OSStatus SRNotificationCallback(AudioDeviceID inDevice, - UInt32 inChannel, - Boolean isInput, - AudioDevicePropertyID inPropertyID, - void* inClientData); - - public: - - TCoreAudioRenderer() - :fInputData(0),fDeviceID(0),fAUHAL(0),fPluginID(0),fState(false) - {} - virtual ~TCoreAudioRenderer() - {} - - long OpenDefault(long inChan, long outChan, long bufferSize, long sampleRate); - long Close(); - - long Start(); - long Stop(); - -}; - -typedef TCoreAudioRenderer * TCoreAudioRendererPtr; - -static void PrintStreamDesc(AudioStreamBasicDescription *inDesc) -{ - cout << "- - - - - - - - - - - - - - - - - - - -" << endl; - cout << " Sample Rate: " << inDesc->mSampleRate << endl; - cout << " Format ID:%.*s\n" << sizeof(inDesc->mFormatID) << (char*)&inDesc->mFormatID << endl; - cout << " Format Flags " << inDesc->mFormatFlags << endl; - cout << " Bytes per Packet: " << inDesc->mBytesPerPacket << endl; - cout << " Frames per Packet: " << inDesc->mFramesPerPacket << endl; - cout << " Bytes per Frame: " << inDesc->mBytesPerFrame << endl; - cout << " Channels per Frame: "<< inDesc->mChannelsPerFrame << endl; - cout << " Bits per Channel: " << inDesc->mBitsPerChannel << endl; - cout << "- - - - - - - - - - - - - - - - - - - -" << endl; -} - -static void printError(OSStatus err) -{ - switch (err) { - case kAudioHardwareNoError: - printf("error code : kAudioHardwareNoError\n"); - break; - case kAudioConverterErr_FormatNotSupported: - printf("error code : kAudioConverterErr_FormatNotSupported\n"); - break; - case kAudioConverterErr_OperationNotSupported: - printf("error code : kAudioConverterErr_OperationNotSupported\n"); - break; - case kAudioConverterErr_PropertyNotSupported: - printf("error code : kAudioConverterErr_PropertyNotSupported\n"); - break; - case kAudioConverterErr_InvalidInputSize: - printf("error code : kAudioConverterErr_InvalidInputSize\n"); - break; - case kAudioConverterErr_InvalidOutputSize: - printf("error code : kAudioConverterErr_InvalidOutputSize\n"); - break; - case kAudioConverterErr_UnspecifiedError: - printf("error code : kAudioConverterErr_UnspecifiedError\n"); - break; - case kAudioConverterErr_BadPropertySizeError: - printf("error code : kAudioConverterErr_BadPropertySizeError\n"); - break; - case kAudioConverterErr_RequiresPacketDescriptionsError: - printf("error code : kAudioConverterErr_RequiresPacketDescriptionsError\n"); - break; - case kAudioConverterErr_InputSampleRateOutOfRange: - printf("error code : kAudioConverterErr_InputSampleRateOutOfRange\n"); - break; - case kAudioConverterErr_OutputSampleRateOutOfRange: - printf("error code : kAudioConverterErr_OutputSampleRateOutOfRange\n"); - break; - case kAudioHardwareNotRunningError: - printf("error code : kAudioHardwareNotRunningError\n"); - break; - case kAudioHardwareUnknownPropertyError: - printf("error code : kAudioHardwareUnknownPropertyError\n"); - break; - case kAudioHardwareIllegalOperationError: - printf("error code : kAudioHardwareIllegalOperationError\n"); - break; - case kAudioHardwareBadDeviceError: - printf("error code : kAudioHardwareBadDeviceError\n"); - break; - case kAudioHardwareBadStreamError: - printf("error code : kAudioHardwareBadStreamError\n"); - break; - case kAudioDeviceUnsupportedFormatError: - printf("error code : kAudioDeviceUnsupportedFormatError\n"); - break; - case kAudioDevicePermissionsError: - printf("error code : kAudioDevicePermissionsError\n"); - break; - default: - printf("error code : unknown\n"); - break; - } -} - -OSStatus TCoreAudioRenderer::Render(void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32, - UInt32 inNumberFrames, - AudioBufferList *ioData) -{ - TCoreAudioRendererPtr renderer = (TCoreAudioRendererPtr)inRefCon; - AudioUnitRender(renderer->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, renderer->fInputData); - for (int i = 0; i < gDevNumInChans; i++) { - gInChannel[i] = (float*)renderer->fInputData->mBuffers[i].mData; - } - for (int i = 0; i < gDevNumOutChans; i++) { - gOutChannel[i] = (float*)ioData->mBuffers[i].mData; - } - gDsp->compute((int)inNumberFrames, gInChannel, gOutChannel); - return 0; -} - -static CFStringRef GetDeviceName(AudioDeviceID id) -{ - UInt32 size = sizeof(CFStringRef); - CFStringRef UIname; - OSStatus err = AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname); - return (err == noErr) ? UIname : NULL; -} - -OSStatus TCoreAudioRenderer::GetDeviceNameFromID(AudioDeviceID id, char* name) -{ - UInt32 size = 256; - return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name); -} - -OSStatus TCoreAudioRenderer::GetDefaultDevice(int inChan, int outChan, int samplerate, AudioDeviceID* id) -{ - UInt32 theSize = sizeof(UInt32); - AudioDeviceID inDefault; - AudioDeviceID outDefault; - OSStatus res; - - if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, - &theSize, &inDefault)) != noErr) - return res; - - if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, - &theSize, &outDefault)) != noErr) - return res; - - // Duplex mode - if (inChan > 0 && outChan > 0) { - // Get the device only if default input and output are the same - if (inDefault == outDefault) { - *id = inDefault; - return noErr; - } else { - printf("GetDefaultDevice : input = %ld and output = %ld are not the same, create aggregate device...\n", inDefault, outDefault); - if (CreateAggregateDevice(inDefault, outDefault, samplerate, id) != noErr) - return kAudioHardwareBadDeviceError; - } - } else if (inChan > 0) { - *id = inDefault; - return noErr; - } else if (outChan > 0) { - *id = outDefault; - return noErr; - } else { - return kAudioHardwareBadDeviceError; - } - - return noErr; -} - -OSStatus TCoreAudioRenderer::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, int samplerate, AudioDeviceID* outAggregateDevice) -{ - OSStatus err = noErr; - AudioObjectID sub_device[32]; - UInt32 outSize = sizeof(sub_device); - - err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); - vector captureDeviceIDArray; - - if (err != noErr) { - printf("Input device does not have subdevices\n"); - captureDeviceIDArray.push_back(captureDeviceID); - } else { - int num_devices = outSize / sizeof(AudioObjectID); - printf("Input device has %d subdevices\n", num_devices); - for (int i = 0; i < num_devices; i++) { - captureDeviceIDArray.push_back(sub_device[i]); - } - } - - err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); - vector playbackDeviceIDArray; - - if (err != noErr) { - printf("Output device does not have subdevices\n"); - playbackDeviceIDArray.push_back(playbackDeviceID); - } else { - int num_devices = outSize / sizeof(AudioObjectID); - printf("Output device has %d subdevices\n", num_devices); - for (int i = 0; i < num_devices; i++) { - playbackDeviceIDArray.push_back(sub_device[i]); - } - } - - return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice); -} - - -OSStatus TCoreAudioRenderer::SRNotificationCallback(AudioDeviceID inDevice, - UInt32 /*inChannel*/, - Boolean /*isInput*/, - AudioDevicePropertyID inPropertyID, - void* inClientData) -{ - TCoreAudioRenderer* driver = (TCoreAudioRenderer*)inClientData; - - switch (inPropertyID) { - - case kAudioDevicePropertyNominalSampleRate: { - printf("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate\n"); - driver->fState = true; - // Check new sample rate - Float64 sampleRate; - UInt32 outSize = sizeof(Float64); - OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate); - if (err != noErr) { - printf("Cannot get current sample rate\n"); - printError(err); - } else { - printf("SRNotificationCallback : checked sample rate = %f\n", sampleRate); - } - break; - } - } - - return noErr; -} - -int TCoreAudioRenderer::SetupSampleRateAux(AudioDeviceID inDevice, int samplerate) -{ - OSStatus err = noErr; - UInt32 outSize; - Float64 sampleRate; - - // Get sample rate - outSize = sizeof(Float64); - err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate); - if (err != noErr) { - printf("Cannot get current sample rate\n"); - printError(err); - return -1; - } else { - printf("Current sample rate = %f\n", sampleRate); - } - - // If needed, set new sample rate - if (samplerate != (int)sampleRate) { - sampleRate = (Float64)samplerate; - - // To get SR change notification - err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this); - if (err != noErr) { - printf("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate\n"); - printError(err); - return -1; - } - err = AudioDeviceSetProperty(inDevice, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate); - if (err != noErr) { - printf("Cannot set sample rate = %d\n", samplerate); - printError(err); - return -1; - } - - // Waiting for SR change notification - int count = 0; - while (!fState && count++ < WAIT_COUNTER) { - usleep(100000); - printf("Wait count = %d\n", count); - } - - // Check new sample rate - outSize = sizeof(Float64); - err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate); - if (err != noErr) { - printf("Cannot get current sample rate\n"); - printError(err); - } else { - printf("Checked sample rate = %f\n", sampleRate); - } - - // Remove SR change notification - AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback); - } - - return 0; -} - -OSStatus TCoreAudioRenderer::CreateAggregateDeviceAux(vector captureDeviceID, vector playbackDeviceID, int samplerate, AudioDeviceID* outAggregateDevice) -{ - OSStatus osErr = noErr; - UInt32 outSize; - Boolean outWritable; - - bool fClockDriftCompensate = true; - - // Prepare sub-devices for clock drift compensation - // Workaround for bug in the HAL : until 10.6.2 - AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; - AudioObjectPropertyAddress theAddressDrift = { kAudioSubDevicePropertyDriftCompensation, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; - UInt32 theQualifierDataSize = sizeof(AudioObjectID); - AudioClassID inClass = kAudioSubDeviceClassID; - void* theQualifierData = &inClass; - UInt32 subDevicesNum = 0; - - //--------------------------------------------------------------------------- - // Setup SR of both devices otherwise creating AD may fail... - //--------------------------------------------------------------------------- - UInt32 keptclockdomain = 0; - UInt32 clockdomain = 0; - outSize = sizeof(UInt32); - bool need_clock_drift_compensation = false; - - for (UInt32 i = 0; i < captureDeviceID.size(); i++) { - if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) { - printf("TCoreAudioRenderer::CreateAggregateDevice : cannot set SR of input device\n"); - } else { - // Check clock domain - osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); - if (osErr != 0) { - printf("TCoreAudioRenderer::CreateAggregateDevice : kAudioDevicePropertyClockDomain error\n"); - printError(osErr); - } else { - keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; - printf("TCoreAudioRenderer::CreateAggregateDevice : input clockdomain = %d\n", clockdomain); - if (clockdomain != 0 && clockdomain != keptclockdomain) { - printf("TCoreAudioRenderer::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...\n"); - need_clock_drift_compensation = true; - } - } - } - } - - for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { - if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) { - printf("TCoreAudioRenderer::CreateAggregateDevice : cannot set SR of output device\n"); - } else { - // Check clock domain - osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); - if (osErr != 0) { - printf("TCoreAudioRenderer::CreateAggregateDevice : kAudioDevicePropertyClockDomain error\n"); - printError(osErr); - } else { - keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; - printf("TCoreAudioRenderer::CreateAggregateDevice : output clockdomain = %d", clockdomain); - if (clockdomain != 0 && clockdomain != keptclockdomain) { - printf("TCoreAudioRenderer::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...\n"); - need_clock_drift_compensation = true; - } - } - } - } - - // If no valid clock domain was found, then assume we have to compensate... - if (keptclockdomain == 0) { - need_clock_drift_compensation = true; - } - - //--------------------------------------------------------------------------- - // Start to create a new aggregate by getting the base audio hardware plugin - //--------------------------------------------------------------------------- - - char device_name[256]; - for (UInt32 i = 0; i < captureDeviceID.size(); i++) { - GetDeviceNameFromID(captureDeviceID[i], device_name); - printf("Separated input = '%s' \n", device_name); - } - - for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { - GetDeviceNameFromID(playbackDeviceID[i], device_name); - printf("Separated output = '%s' \n", device_name); - } - - osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable); - if (osErr != noErr) { - printf("TCoreAudioRenderer::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error\n"); - printError(osErr); - return osErr; - } - - AudioValueTranslation pluginAVT; - - CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio"); - - pluginAVT.mInputData = &inBundleRef; - pluginAVT.mInputDataSize = sizeof(inBundleRef); - pluginAVT.mOutputData = &fPluginID; - pluginAVT.mOutputDataSize = sizeof(fPluginID); - - osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT); - if (osErr != noErr) { - printf("TCoreAudioRenderer::CreateAggregateDevice : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error\n"); - printError(osErr); - return osErr; - } - - //------------------------------------------------- - // Create a CFDictionary for our aggregate device - //------------------------------------------------- - - CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex"); - CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex"); - - // add the name of the device to the dictionary - CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef); - - // add our choice of UID for the aggregate device to the dictionary - CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef); - - // add a "private aggregate key" to the dictionary - int value = 1; - CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value); - - SInt32 system; - Gestalt(gestaltSystemVersion, &system); - - printf("TCoreAudioRenderer::CreateAggregateDevice : system version = %x limit = %x\n", system, 0x00001054); - - // Starting with 10.5.4 systems, the AD can be internal... (better) - if (system < 0x00001054) { - printf("TCoreAudioRenderer::CreateAggregateDevice : public aggregate device....\n"); - } else { - printf("TCoreAudioRenderer::CreateAggregateDevice : private aggregate device....\n"); - CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef); - } - - // Prepare sub-devices for clock drift compensation - CFMutableArrayRef subDevicesArrayClock = NULL; - - /* - if (fClockDriftCompensate) { - if (need_clock_drift_compensation) { - jack_info("Clock drift compensation activated..."); - subDevicesArrayClock = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - - for (UInt32 i = 0; i < captureDeviceID.size(); i++) { - CFStringRef UID = GetDeviceName(captureDeviceID[i]); - if (UID) { - CFMutableDictionaryRef subdeviceAggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceUIDKey), UID); - CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceDriftCompensationKey), AggregateDeviceNumberRef); - //CFRelease(UID); - CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict); - } - } - - for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { - CFStringRef UID = GetDeviceName(playbackDeviceID[i]); - if (UID) { - CFMutableDictionaryRef subdeviceAggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceUIDKey), UID); - CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceDriftCompensationKey), AggregateDeviceNumberRef); - //CFRelease(UID); - CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict); - } - } - - // add sub-device clock array for the aggregate device to the dictionary - CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceSubDeviceListKey), subDevicesArrayClock); - } else { - jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)"); - } - } - */ - - //------------------------------------------------- - // Create a CFMutableArray for our sub-device list - //------------------------------------------------- - - // we need to append the UID for each device to a CFMutableArray, so create one here - CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - - vector captureDeviceUID; - for (UInt32 i = 0; i < captureDeviceID.size(); i++) { - CFStringRef ref = GetDeviceName(captureDeviceID[i]); - if (ref == NULL) - return -1; - captureDeviceUID.push_back(ref); - // input sub-devices in this example, so append the sub-device's UID to the CFArray - CFArrayAppendValue(subDevicesArray, ref); - } - - vector playbackDeviceUID; - for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { - CFStringRef ref = GetDeviceName(playbackDeviceID[i]); - if (ref == NULL) - return -1; - playbackDeviceUID.push_back(ref); - // output sub-devices in this example, so append the sub-device's UID to the CFArray - CFArrayAppendValue(subDevicesArray, ref); - } - - //----------------------------------------------------------------------- - // Feed the dictionary to the plugin, to create a blank aggregate device - //----------------------------------------------------------------------- - - AudioObjectPropertyAddress pluginAOPA; - pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice; - pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; - pluginAOPA.mElement = kAudioObjectPropertyElementMaster; - UInt32 outDataSize; - - osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize); - if (osErr != noErr) { - printf("TCoreAudioRenderer::CreateAggregateDevice : AudioObjectGetPropertyDataSize error\n"); - printError(osErr); - goto error; - } - - osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice); - if (osErr != noErr) { - printf("TCoreAudioRenderer::CreateAggregateDevice : AudioObjectGetPropertyData error\n"); - printError(osErr); - goto error; - } - - // pause for a bit to make sure that everything completed correctly - // this is to work around a bug in the HAL where a new aggregate device seems to disappear briefly after it is created - CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); - - //------------------------- - // Set the sub-device list - //------------------------- - - pluginAOPA.mSelector = kAudioAggregateDevicePropertyFullSubDeviceList; - pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; - pluginAOPA.mElement = kAudioObjectPropertyElementMaster; - outDataSize = sizeof(CFMutableArrayRef); - osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &subDevicesArray); - if (osErr != noErr) { - printf("TCoreAudioRenderer::CreateAggregateDevice : AudioObjectSetPropertyData for sub-device list error\n"); - printError(osErr); - goto error; - } - - // pause again to give the changes time to take effect - CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); - - //----------------------- - // Set the master device - //----------------------- - - // set the master device manually (this is the device which will act as the master clock for the aggregate device) - // pass in the UID of the device you want to use - pluginAOPA.mSelector = kAudioAggregateDevicePropertyMasterSubDevice; - pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; - pluginAOPA.mElement = kAudioObjectPropertyElementMaster; - outDataSize = sizeof(CFStringRef); - osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &captureDeviceUID[0]); // First apture is master... - if (osErr != noErr) { - printf("TCoreAudioRenderer::CreateAggregateDevice : AudioObjectSetPropertyData for master device error\n"); - printError(osErr); - goto error; - } - - // pause again to give the changes time to take effect - CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); - - // Prepare sub-devices for clock drift compensation - // Workaround for bug in the HAL : until 10.6.2 - - if (fClockDriftCompensate) { - if (need_clock_drift_compensation) { - printf("Clock drift compensation activated...\n"); - - // Get the property data size - osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize); - if (osErr != noErr) { - printf("TCoreAudioRenderer::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error\n"); - printError(osErr); - } - - // Calculate the number of object IDs - subDevicesNum = outSize / sizeof(AudioObjectID); - printf("TCoreAudioRenderer::CreateAggregateDevice clock drift compensation, number of sub-devices = %d\n", subDevicesNum); - AudioObjectID subDevices[subDevicesNum]; - outSize = sizeof(subDevices); - - osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices); - if (osErr != noErr) { - printf("TCoreAudioRenderer::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error\n"); - printError(osErr); - } - - // Set kAudioSubDevicePropertyDriftCompensation property... - for (UInt32 index = 0; index < subDevicesNum; ++index) { - UInt32 theDriftCompensationValue = 1; - osErr = AudioObjectSetPropertyData(subDevices[index], &theAddressDrift, 0, NULL, sizeof(UInt32), &theDriftCompensationValue); - if (osErr != noErr) { - printf("TCoreAudioRenderer::CreateAggregateDevice kAudioSubDevicePropertyDriftCompensation error\n"); - printError(osErr); - } - } - } else { - printf("Clock drift compensation was asked but is not needed (devices use the same clock domain)\n"); - } - } - - // pause again to give the changes time to take effect - CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); - - //---------- - // Clean up - //---------- - - // release the private AD key - CFRelease(AggregateDeviceNumberRef); - - // release the CF objects we have created - we don't need them any more - CFRelease(aggDeviceDict); - CFRelease(subDevicesArray); - - if (subDevicesArrayClock) - CFRelease(subDevicesArrayClock); - - // release the device UID - for (UInt32 i = 0; i < captureDeviceUID.size(); i++) { - CFRelease(captureDeviceUID[i]); - } - - for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) { - CFRelease(playbackDeviceUID[i]); - } - - printf("New aggregate device %d\n", *outAggregateDevice); - return noErr; - -error: - DestroyAggregateDevice(); - return -1; -} - -OSStatus TCoreAudioRenderer::DestroyAggregateDevice() -{ - OSStatus osErr = noErr; - AudioObjectPropertyAddress pluginAOPA; - pluginAOPA.mSelector = kAudioPlugInDestroyAggregateDevice; - pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; - pluginAOPA.mElement = kAudioObjectPropertyElementMaster; - UInt32 outDataSize; - - if (fPluginID > 0) { - - osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize); - if (osErr != noErr) { - printf("TCoreAudioRenderer::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error\n"); - printError(osErr); - return osErr; - } - - osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID); - if (osErr != noErr) { - printf("TCoreAudioRenderer::DestroyAggregateDevice : AudioObjectGetPropertyData error\n"); - printError(osErr); - return osErr; - } - - } - - return noErr; -} - - -long TCoreAudioRenderer::OpenDefault(long inChan, long outChan, long bufferSize, long samplerate) -{ - OSStatus err = noErr; - ComponentResult err1; - UInt32 outSize; - UInt32 enableIO; - Boolean isWritable; - AudioStreamBasicDescription srcFormat, dstFormat, sampleRate; - long in_nChannels, out_nChannels; - - printf("OpenDefault inChan = %ld outChan = %ld bufferSize = %ld samplerate = %ld\n", inChan, outChan, bufferSize, samplerate); - - SInt32 major; - SInt32 minor; - Gestalt(gestaltSystemVersionMajor, &major); - Gestalt(gestaltSystemVersionMinor, &minor); - - // Starting with 10.6 systems, the HAL notification thread is created internally - if (major == 10 && minor >= 6) { - CFRunLoopRef theRunLoop = NULL; - AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; - OSStatus osErr = AudioObjectSetPropertyData (kAudioObjectSystemObject, &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop); - if (osErr != noErr) { - printf("TCoreAudioRenderer::Open kAudioHardwarePropertyRunLoop error\n"); - printError(osErr); - } - } - - if (GetDefaultDevice(inChan, outChan, samplerate,&fDeviceID) != noErr) { - printf("Cannot open default device\n"); - return OPEN_ERR; - } - - // Setting buffer size - outSize = sizeof(UInt32); - err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &bufferSize); - if (err != noErr) { - printf("Cannot set buffer size %ld\n", bufferSize); - printError(err); - return OPEN_ERR; - } - - // Setting sample rate - outSize = sizeof(AudioStreamBasicDescription); - err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyStreamFormat, &outSize, &sampleRate); - if (err != noErr) { - printf("Cannot get current sample rate\n"); - printError(err); - return OPEN_ERR; - } - - if (samplerate != long(sampleRate.mSampleRate)) { - sampleRate.mSampleRate = (Float64)(samplerate); - err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyStreamFormat, outSize, &sampleRate); - if (err != noErr) { - printf("Cannot set sample rate = %ld\n", samplerate); - printError(err); - return OPEN_ERR; - } - } - - // AUHAL - ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0}; - Component HALOutput = FindNextComponent(NULL, &cd); - - err1 = OpenAComponent(HALOutput, &fAUHAL); - if (err1 != noErr) { - printf("Error calling OpenAComponent\n"); - printError(err1); - goto error; - } - - err1 = AudioUnitInitialize(fAUHAL); - if (err1 != noErr) { - printf("Cannot initialize AUHAL unit\n"); - printError(err1); - goto error; - } - - enableIO = 1; - err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); - if (err1 != noErr) { - printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output\n"); - printError(err1); - goto error; - } - - enableIO = 1; - err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); - if (err1 != noErr) { - printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input\n"); - printError(err1); - goto error; - } - - err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID)); - if (err1 != noErr) { - printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice\n"); - printError(err1); - goto error; - } - - err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&bufferSize, sizeof(UInt32)); - if (err1 != noErr) { - printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n"); - printError(err1); - goto error; - } - - err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&bufferSize, sizeof(UInt32)); - if (err1 != noErr) { - printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n"); - printError(err1); - goto error; - } - - err1 = AudioUnitGetPropertyInfo(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Input, 1, &outSize, &isWritable); - if (err1 != noErr) { - printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap-INFO 1\n"); - printError(err1); - } - - in_nChannels = (err1 == noErr) ? outSize / sizeof(SInt32) : 0; - printf("in_nChannels = %ld\n", in_nChannels); - - err1 = AudioUnitGetPropertyInfo(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, &outSize, &isWritable); - if (err1 != noErr) { - printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap-INFO 0\n"); - printError(err1); - } - - out_nChannels = (err1 == noErr) ? outSize / sizeof(SInt32) : 0; - printf("out_nChannels = %ld\n", out_nChannels); - - /* - Just ignore this case : seems to work without any further change... - - if (outChan > out_nChannels) { - printf("This device hasn't required output channels\n"); - goto error; - } - if (inChan > in_nChannels) { - printf("This device hasn't required input channels\n"); - goto error; - } - */ - - if (outChan < out_nChannels) { - SInt32 chanArr[out_nChannels]; - for (int i = 0; i < out_nChannels; i++) { - chanArr[i] = -1; - } - for (int i = 0; i < outChan; i++) { - chanArr[i] = i; - } - err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels); - if (err1 != noErr) { - printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0\n"); - printError(err1); - } - } - - if (inChan < in_nChannels) { - SInt32 chanArr[in_nChannels]; - for (int i = 0; i < in_nChannels; i++) { - chanArr[i] = -1; - } - for (int i = 0; i < inChan; i++) { - chanArr[i] = i; - } - AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels); - if (err1 != noErr) { - printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1\n"); - printError(err1); - } - } - - if (inChan > 0) { - outSize = sizeof(AudioStreamBasicDescription); - err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &outSize); - if (err1 != noErr) { - printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); - printError(err1); - } - PrintStreamDesc(&srcFormat); - - srcFormat.mSampleRate = samplerate; - srcFormat.mFormatID = kAudioFormatLinearPCM; - srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; - srcFormat.mBytesPerPacket = sizeof(float); - srcFormat.mFramesPerPacket = 1; - srcFormat.mBytesPerFrame = sizeof(float); - srcFormat.mChannelsPerFrame = inChan; - srcFormat.mBitsPerChannel = 32; - - PrintStreamDesc(&srcFormat); - - err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription)); - if (err1 != noErr) { - printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); - printError(err1); - } - } - - if (outChan > 0) { - outSize = sizeof(AudioStreamBasicDescription); - err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &outSize); - if (err1 != noErr) { - printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); - printError(err1); - } - PrintStreamDesc(&dstFormat); - - dstFormat.mSampleRate = samplerate; - dstFormat.mFormatID = kAudioFormatLinearPCM; - dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; - dstFormat.mBytesPerPacket = sizeof(float); - dstFormat.mFramesPerPacket = 1; - dstFormat.mBytesPerFrame = sizeof(float); - dstFormat.mChannelsPerFrame = outChan; - dstFormat.mBitsPerChannel = 32; - - PrintStreamDesc(&dstFormat); - - err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription)); - if (err1 != noErr) { - printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); - printError(err1); - } - } - - if (inChan > 0 && outChan == 0) { - AURenderCallbackStruct output; - output.inputProc = Render; - output.inputProcRefCon = this; - err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output)); - if (err1 != noErr) { - printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n"); - printError(err1); - goto error; - } - } else { - AURenderCallbackStruct output; - output.inputProc = Render; - output.inputProcRefCon = this; - err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output)); - if (err1 != noErr) { - printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n"); - printError(err1); - goto error; - } - } - - fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inChan * sizeof(AudioBuffer)); - if (fInputData == 0) { - printf("Cannot allocate memory for input buffers\n"); - goto error; - } - fInputData->mNumberBuffers = inChan; - - // Prepare buffers - for (int i = 0; i < inChan; i++) { - fInputData->mBuffers[i].mNumberChannels = 1; - fInputData->mBuffers[i].mData = malloc(bufferSize * sizeof(float)); - fInputData->mBuffers[i].mDataByteSize = bufferSize * sizeof(float); - } - - return NO_ERR; - -error: - AudioUnitUninitialize(fAUHAL); - CloseComponent(fAUHAL); - return OPEN_ERR; -} - -long TCoreAudioRenderer::Close() -{ - for (int i = 0; i < gDevNumInChans; i++) { - free(fInputData->mBuffers[i].mData); - } - free(fInputData); - AudioUnitUninitialize(fAUHAL); - CloseComponent(fAUHAL); - DestroyAggregateDevice(); - return NO_ERR; -} - -long TCoreAudioRenderer::Start() -{ - OSStatus err = AudioOutputUnitStart(fAUHAL); - - if (err != noErr) { - printf("Error while opening device : device open error \n"); - return OPEN_ERR; - } else { - return NO_ERR; - } -} - -long TCoreAudioRenderer::Stop() -{ - OSStatus err = AudioOutputUnitStop(fAUHAL); - - if (err != noErr) { - printf("Error while closing device : device close error \n"); - return OPEN_ERR; - } else { - return NO_ERR; - } -} - - - -/****************************************************************************** -******************************************************************************* - - CORE AUDIO INTERFACE - -******************************************************************************* -*******************************************************************************/ -class coreaudio : public audio { - - TCoreAudioRenderer audio_device; - long fSampleRate, fFramesPerBuf; - - public: - coreaudio(long srate, long fpb) : fSampleRate(srate), fFramesPerBuf(fpb) {} - virtual ~coreaudio() {} - - virtual bool init(const char* /*name*/, dsp* DSP) { - gDsp = DSP; - DSP->init (fSampleRate); - gDevNumInChans = DSP->getNumInputs(); - gDevNumOutChans = DSP->getNumOutputs(); - if (audio_device.OpenDefault(gDevNumInChans, gDevNumOutChans, fFramesPerBuf, fSampleRate) < 0) { - printf("Cannot open CoreAudio device\n"); - return false; - } - return true; - } - - virtual bool start() { - if (audio_device.Start() < 0) { - printf("Cannot start CoreAudio device\n"); - return false; - } - return true; - } - - virtual void stop() { - audio_device.Stop(); - audio_device.Close(); - } - -}; - -#endif - -/********************END ARCHITECTURE SECTION (part 2/2)****************/ - -