Merge pull request #9796 from marcelofg55/2.1

[2.1] Updated OS X audio driver with improvements from 3.0
This commit is contained in:
Rémi Verschelde 2017-07-24 08:08:14 +02:00 committed by GitHub
commit 48007d8ec6
3 changed files with 105 additions and 25 deletions

View File

@ -31,11 +31,15 @@
#include "audio_driver_osx.h" #include "audio_driver_osx.h"
Error AudioDriverOSX::init() { static OSStatus outputDeviceAddressCB(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *__nullable inClientData) {
AudioDriverOSX *driver = (AudioDriverOSX *)inClientData;
active = false; driver->reopen();
channels = 2;
return noErr;
}
Error AudioDriverOSX::initDevice() {
AudioStreamBasicDescription strdesc; AudioStreamBasicDescription strdesc;
strdesc.mFormatID = kAudioFormatLinearPCM; strdesc.mFormatID = kAudioFormatLinearPCM;
strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
@ -43,12 +47,10 @@ Error AudioDriverOSX::init() {
strdesc.mSampleRate = 44100; strdesc.mSampleRate = 44100;
strdesc.mFramesPerPacket = 1; strdesc.mFramesPerPacket = 1;
strdesc.mBitsPerChannel = 16; strdesc.mBitsPerChannel = 16;
strdesc.mBytesPerFrame = strdesc.mBytesPerFrame = strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8;
strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8; strdesc.mBytesPerPacket = strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
strdesc.mBytesPerPacket =
strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
OSStatus result = noErr; OSStatus result;
AURenderCallbackStruct callback; AURenderCallbackStruct callback;
AudioComponentDescription desc; AudioComponentDescription desc;
AudioComponent comp = NULL; AudioComponent comp = NULL;
@ -58,40 +60,99 @@ Error AudioDriverOSX::init() {
zeromem(&desc, sizeof(desc)); zeromem(&desc, sizeof(desc));
desc.componentType = kAudioUnitType_Output; desc.componentType = kAudioUnitType_Output;
desc.componentSubType = 0; /* !!! FIXME: ? */ desc.componentSubType = kAudioUnitSubType_HALOutput;
comp = AudioComponentFindNext(NULL, &desc);
desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentManufacturer = kAudioUnitManufacturer_Apple;
comp = AudioComponentFindNext(NULL, &desc);
ERR_FAIL_COND_V(comp == NULL, FAILED);
result = AudioComponentInstanceNew(comp, &audio_unit); result = AudioComponentInstanceNew(comp, &audio_unit);
ERR_FAIL_COND_V(result != noErr, FAILED); ERR_FAIL_COND_V(result != noErr, FAILED);
ERR_FAIL_COND_V(comp == NULL, FAILED);
result = AudioUnitSetProperty(audio_unit, result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, scope, bus, &strdesc, sizeof(strdesc));
kAudioUnitProperty_StreamFormat,
scope, bus, &strdesc, sizeof(strdesc));
ERR_FAIL_COND_V(result != noErr, FAILED); ERR_FAIL_COND_V(result != noErr, FAILED);
zeromem(&callback, sizeof(AURenderCallbackStruct)); zeromem(&callback, sizeof(AURenderCallbackStruct));
callback.inputProc = &AudioDriverOSX::output_callback; callback.inputProc = &AudioDriverOSX::output_callback;
callback.inputProcRefCon = this; callback.inputProcRefCon = this;
result = AudioUnitSetProperty(audio_unit, result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, scope, bus, &callback, sizeof(callback));
kAudioUnitProperty_SetRenderCallback,
scope, bus, &callback, sizeof(callback));
ERR_FAIL_COND_V(result != noErr, FAILED); ERR_FAIL_COND_V(result != noErr, FAILED);
result = AudioUnitInitialize(audio_unit); result = AudioUnitInitialize(audio_unit);
ERR_FAIL_COND_V(result != noErr, FAILED); ERR_FAIL_COND_V(result != noErr, FAILED);
result = AudioOutputUnitStart(audio_unit); return OK;
}
Error AudioDriverOSX::finishDevice() {
OSStatus result;
if (active) {
result = AudioOutputUnitStop(audio_unit);
ERR_FAIL_COND_V(result != noErr, FAILED);
active = false;
}
result = AudioUnitUninitialize(audio_unit);
ERR_FAIL_COND_V(result != noErr, FAILED);
return OK;
}
Error AudioDriverOSX::init() {
OSStatus result;
active = false;
channels = 2;
outputDeviceAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
outputDeviceAddress.mScope = kAudioObjectPropertyScopeGlobal;
outputDeviceAddress.mElement = kAudioObjectPropertyElementMaster;
result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &outputDeviceAddress, &outputDeviceAddressCB, this);
ERR_FAIL_COND_V(result != noErr, FAILED); ERR_FAIL_COND_V(result != noErr, FAILED);
const int samples = 1024; const int samples = 1024;
samples_in = memnew_arr(int32_t, samples); // whatever samples_in = memnew_arr(int32_t, samples); // whatever
buffer_frames = samples / channels; buffer_frames = samples / channels;
return OK; return initDevice();
}; };
Error AudioDriverOSX::reopen() {
Error err;
bool restart = false;
lock();
if (active) {
restart = true;
}
err = finishDevice();
if (err != OK) {
ERR_PRINT("finishDevice failed");
unlock();
return err;
}
err = initDevice();
if (err != OK) {
ERR_PRINT("initDevice failed");
unlock();
return err;
}
if (restart) {
start();
}
unlock();
return OK;
}
OSStatus AudioDriverOSX::output_callback(void *inRefCon, OSStatus AudioDriverOSX::output_callback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags, AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp, const AudioTimeStamp *inTimeStamp,
@ -149,7 +210,14 @@ OSStatus AudioDriverOSX::output_callback(void *inRefCon,
}; };
void AudioDriverOSX::start() { void AudioDriverOSX::start() {
if (!active) {
OSStatus result = AudioOutputUnitStart(audio_unit);
if (result != noErr) {
ERR_PRINT("AudioOutputUnitStart failed");
} else {
active = true; active = true;
}
}
}; };
int AudioDriverOSX::get_mix_rate() const { int AudioDriverOSX::get_mix_rate() const {
@ -161,18 +229,23 @@ AudioDriverSW::OutputFormat AudioDriverOSX::get_output_format() const {
}; };
void AudioDriverOSX::lock() { void AudioDriverOSX::lock() {
if (active && mutex) if (mutex)
mutex->lock(); mutex->lock();
}; };
void AudioDriverOSX::unlock() { void AudioDriverOSX::unlock() {
if (active && mutex) if (mutex)
mutex->unlock(); mutex->unlock();
}; };
void AudioDriverOSX::finish() { void AudioDriverOSX::finish() {
OSStatus result;
if (active) finishDevice();
AudioOutputUnitStop(audio_unit);
result = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &outputDeviceAddress, &outputDeviceAddressCB, this);
if (result != noErr) {
ERR_PRINT("AudioObjectRemovePropertyListener failed");
}
memdelete_arr(samples_in); memdelete_arr(samples_in);
}; };

View File

@ -35,10 +35,12 @@
#include "servers/audio/audio_server_sw.h" #include "servers/audio/audio_server_sw.h"
#include <AudioUnit/AudioUnit.h> #include <AudioUnit/AudioUnit.h>
#include <CoreAudio/AudioHardware.h>
class AudioDriverOSX : public AudioDriverSW { class AudioDriverOSX : public AudioDriverSW {
AudioComponentInstance audio_unit; AudioComponentInstance audio_unit;
AudioObjectPropertyAddress outputDeviceAddress;
bool active; bool active;
Mutex *mutex; Mutex *mutex;
@ -52,6 +54,9 @@ class AudioDriverOSX : public AudioDriverSW {
UInt32 inBusNumber, UInt32 inNumberFrames, UInt32 inBusNumber, UInt32 inNumberFrames,
AudioBufferList *ioData); AudioBufferList *ioData);
Error initDevice();
Error finishDevice();
public: public:
const char *get_name() const { const char *get_name() const {
return "AudioUnit"; return "AudioUnit";
@ -65,6 +70,8 @@ public:
virtual void unlock(); virtual void unlock();
virtual void finish(); virtual void finish();
Error reopen();
AudioDriverOSX(); AudioDriverOSX();
~AudioDriverOSX(); ~AudioDriverOSX();
}; };

View File

@ -84,7 +84,7 @@ def configure(env):
env.Append(LIBS=['pthread']) env.Append(LIBS=['pthread'])
#env.Append(CPPFLAGS=['-F/Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks', '-isysroot', '/Developer/SDKs/MacOSX10.4u.sdk', '-mmacosx-version-min=10.4']) #env.Append(CPPFLAGS=['-F/Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks', '-isysroot', '/Developer/SDKs/MacOSX10.4u.sdk', '-mmacosx-version-min=10.4'])
#env.Append(LINKFLAGS=['-mmacosx-version-min=10.4', '-isysroot', '/Developer/SDKs/MacOSX10.4u.sdk', '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk']) #env.Append(LINKFLAGS=['-mmacosx-version-min=10.4', '-isysroot', '/Developer/SDKs/MacOSX10.4u.sdk', '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk'])
env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit', '-lz', '-framework', 'IOKit', '-framework', 'ForceFeedback']) env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit', '-framework', 'CoreAudio', '-lz', '-framework', 'IOKit', '-framework', 'ForceFeedback'])
env.Append(LINKFLAGS=["-mmacosx-version-min=10.9"]) env.Append(LINKFLAGS=["-mmacosx-version-min=10.9"])
if (env["CXX"] == "clang++"): if (env["CXX"] == "clang++"):