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:
commit
48007d8ec6
|
@ -31,11 +31,15 @@
|
|||
|
||||
#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;
|
||||
channels = 2;
|
||||
driver->reopen();
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
Error AudioDriverOSX::initDevice() {
|
||||
AudioStreamBasicDescription strdesc;
|
||||
strdesc.mFormatID = kAudioFormatLinearPCM;
|
||||
strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
|
||||
|
@ -43,12 +47,10 @@ Error AudioDriverOSX::init() {
|
|||
strdesc.mSampleRate = 44100;
|
||||
strdesc.mFramesPerPacket = 1;
|
||||
strdesc.mBitsPerChannel = 16;
|
||||
strdesc.mBytesPerFrame =
|
||||
strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8;
|
||||
strdesc.mBytesPerPacket =
|
||||
strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
|
||||
strdesc.mBytesPerFrame = strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8;
|
||||
strdesc.mBytesPerPacket = strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
|
||||
|
||||
OSStatus result = noErr;
|
||||
OSStatus result;
|
||||
AURenderCallbackStruct callback;
|
||||
AudioComponentDescription desc;
|
||||
AudioComponent comp = NULL;
|
||||
|
@ -58,40 +60,99 @@ Error AudioDriverOSX::init() {
|
|||
|
||||
zeromem(&desc, sizeof(desc));
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
desc.componentSubType = 0; /* !!! FIXME: ? */
|
||||
comp = AudioComponentFindNext(NULL, &desc);
|
||||
desc.componentSubType = kAudioUnitSubType_HALOutput;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
|
||||
comp = AudioComponentFindNext(NULL, &desc);
|
||||
ERR_FAIL_COND_V(comp == NULL, FAILED);
|
||||
|
||||
result = AudioComponentInstanceNew(comp, &audio_unit);
|
||||
ERR_FAIL_COND_V(result != noErr, FAILED);
|
||||
ERR_FAIL_COND_V(comp == NULL, FAILED);
|
||||
|
||||
result = AudioUnitSetProperty(audio_unit,
|
||||
kAudioUnitProperty_StreamFormat,
|
||||
scope, bus, &strdesc, sizeof(strdesc));
|
||||
result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, scope, bus, &strdesc, sizeof(strdesc));
|
||||
ERR_FAIL_COND_V(result != noErr, FAILED);
|
||||
|
||||
zeromem(&callback, sizeof(AURenderCallbackStruct));
|
||||
callback.inputProc = &AudioDriverOSX::output_callback;
|
||||
callback.inputProcRefCon = this;
|
||||
result = AudioUnitSetProperty(audio_unit,
|
||||
kAudioUnitProperty_SetRenderCallback,
|
||||
scope, bus, &callback, sizeof(callback));
|
||||
result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, scope, bus, &callback, sizeof(callback));
|
||||
ERR_FAIL_COND_V(result != noErr, FAILED);
|
||||
|
||||
result = AudioUnitInitialize(audio_unit);
|
||||
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);
|
||||
|
||||
const int samples = 1024;
|
||||
samples_in = memnew_arr(int32_t, samples); // whatever
|
||||
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,
|
||||
AudioUnitRenderActionFlags *ioActionFlags,
|
||||
const AudioTimeStamp *inTimeStamp,
|
||||
|
@ -149,7 +210,14 @@ OSStatus AudioDriverOSX::output_callback(void *inRefCon,
|
|||
};
|
||||
|
||||
void AudioDriverOSX::start() {
|
||||
active = true;
|
||||
if (!active) {
|
||||
OSStatus result = AudioOutputUnitStart(audio_unit);
|
||||
if (result != noErr) {
|
||||
ERR_PRINT("AudioOutputUnitStart failed");
|
||||
} else {
|
||||
active = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int AudioDriverOSX::get_mix_rate() const {
|
||||
|
@ -161,18 +229,23 @@ AudioDriverSW::OutputFormat AudioDriverOSX::get_output_format() const {
|
|||
};
|
||||
|
||||
void AudioDriverOSX::lock() {
|
||||
if (active && mutex)
|
||||
if (mutex)
|
||||
mutex->lock();
|
||||
};
|
||||
void AudioDriverOSX::unlock() {
|
||||
if (active && mutex)
|
||||
if (mutex)
|
||||
mutex->unlock();
|
||||
};
|
||||
|
||||
void AudioDriverOSX::finish() {
|
||||
OSStatus result;
|
||||
|
||||
if (active)
|
||||
AudioOutputUnitStop(audio_unit);
|
||||
finishDevice();
|
||||
|
||||
result = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &outputDeviceAddress, &outputDeviceAddressCB, this);
|
||||
if (result != noErr) {
|
||||
ERR_PRINT("AudioObjectRemovePropertyListener failed");
|
||||
}
|
||||
|
||||
memdelete_arr(samples_in);
|
||||
};
|
||||
|
|
|
@ -35,10 +35,12 @@
|
|||
#include "servers/audio/audio_server_sw.h"
|
||||
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
#include <CoreAudio/AudioHardware.h>
|
||||
|
||||
class AudioDriverOSX : public AudioDriverSW {
|
||||
|
||||
AudioComponentInstance audio_unit;
|
||||
AudioObjectPropertyAddress outputDeviceAddress;
|
||||
bool active;
|
||||
Mutex *mutex;
|
||||
|
||||
|
@ -52,6 +54,9 @@ class AudioDriverOSX : public AudioDriverSW {
|
|||
UInt32 inBusNumber, UInt32 inNumberFrames,
|
||||
AudioBufferList *ioData);
|
||||
|
||||
Error initDevice();
|
||||
Error finishDevice();
|
||||
|
||||
public:
|
||||
const char *get_name() const {
|
||||
return "AudioUnit";
|
||||
|
@ -65,6 +70,8 @@ public:
|
|||
virtual void unlock();
|
||||
virtual void finish();
|
||||
|
||||
Error reopen();
|
||||
|
||||
AudioDriverOSX();
|
||||
~AudioDriverOSX();
|
||||
};
|
||||
|
|
|
@ -84,7 +84,7 @@ def configure(env):
|
|||
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(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"])
|
||||
|
||||
if (env["CXX"] == "clang++"):
|
||||
|
|
Loading…
Reference in New Issue