mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2024-12-22 17:55:37 +00:00
CoreAudio: sine wave example works
This commit is contained in:
parent
a774a72958
commit
df0ca8a772
|
@ -65,11 +65,16 @@ if(COREAUDIO_FOUND)
|
||||||
find_path(COREFOUNDATION_INCLUDE_DIR NAMES CoreFoundation.h)
|
find_path(COREFOUNDATION_INCLUDE_DIR NAMES CoreFoundation.h)
|
||||||
find_library(COREFOUNDATION_LIBRARY NAMES CoreFoundation)
|
find_library(COREFOUNDATION_LIBRARY NAMES CoreFoundation)
|
||||||
include_directories(${COREFOUNDATION_INCLUDE_DIR})
|
include_directories(${COREFOUNDATION_INCLUDE_DIR})
|
||||||
|
|
||||||
|
find_path(AUDIOUNIT_INCLUDE_DIR NAMES AudioUnit.h)
|
||||||
|
find_library(AUDIOUNIT_LIBRARY NAMES AudioUnit)
|
||||||
|
include_directories(${AUDIOUNIT_INCLUDE_DIR})
|
||||||
else()
|
else()
|
||||||
set(STATUS_COREAUDIO "not found")
|
set(STATUS_COREAUDIO "not found")
|
||||||
set(SOUNDIO_HAVE_COREAUDIO false)
|
set(SOUNDIO_HAVE_COREAUDIO false)
|
||||||
set(COREAUDIO_LIBRARY "")
|
set(COREAUDIO_LIBRARY "")
|
||||||
set(COREFOUNDATION_LIBRARY "")
|
set(COREFOUNDATION_LIBRARY "")
|
||||||
|
set(AUDIOUNIT_LIBRARY "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
@ -180,6 +185,7 @@ target_link_libraries(libsoundio_shared LINK_PUBLIC
|
||||||
${ALSA_LIBRARIES}
|
${ALSA_LIBRARIES}
|
||||||
${COREAUDIO_LIBRARY}
|
${COREAUDIO_LIBRARY}
|
||||||
${COREFOUNDATION_LIBRARY}
|
${COREFOUNDATION_LIBRARY}
|
||||||
|
${AUDIOUNIT_LIBRARY}
|
||||||
m
|
m
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
)
|
)
|
||||||
|
@ -235,6 +241,7 @@ target_link_libraries(unit_tests LINK_PUBLIC
|
||||||
${ALSA_LIBRARIES}
|
${ALSA_LIBRARIES}
|
||||||
${COREAUDIO_LIBRARY}
|
${COREAUDIO_LIBRARY}
|
||||||
${COREFOUNDATION_LIBRARY}
|
${COREFOUNDATION_LIBRARY}
|
||||||
|
${AUDIOUNIT_LIBRARY}
|
||||||
m
|
m
|
||||||
)
|
)
|
||||||
set_target_properties(unit_tests PROPERTIES
|
set_target_properties(unit_tests PROPERTIES
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
# COREAUDIO_INCLUDE_DIR
|
# COREAUDIO_INCLUDE_DIR
|
||||||
# COREAUDIO_LIBRARY
|
# COREAUDIO_LIBRARY
|
||||||
|
|
||||||
find_path(COREAUDIO_INCLUDE_DIR NAMES CoreAudio.h)
|
find_path(COREAUDIO_INCLUDE_DIR NAMES CoreAudio/CoreAudio.h)
|
||||||
|
|
||||||
find_library(COREAUDIO_LIBRARY NAMES CoreAudio)
|
find_library(COREAUDIO_LIBRARY NAMES CoreAudio)
|
||||||
|
|
||||||
|
|
|
@ -71,9 +71,11 @@ static void destroy_ca(struct SoundIoPrivate *si) {
|
||||||
soundio_destroy_devices_info(sica->ready_devices_info);
|
soundio_destroy_devices_info(sica->ready_devices_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO
|
||||||
static CFStringRef to_cf_string(const char *str) {
|
static CFStringRef to_cf_string(const char *str) {
|
||||||
return CFStringCreateWithCString(kCFAllocatorDefault, str, kCFStringEncodingUTF8);
|
return CFStringCreateWithCString(kCFAllocatorDefault, str, kCFStringEncodingUTF8);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Possible errors:
|
// Possible errors:
|
||||||
// * SoundIoErrorNoMem
|
// * SoundIoErrorNoMem
|
||||||
|
@ -354,8 +356,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
OSStatus os_err;
|
OSStatus os_err;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
RefreshDevices rd;
|
RefreshDevices rd = {0};
|
||||||
memset(&rd, 0, sizeof(RefreshDevices));
|
|
||||||
|
|
||||||
if (!(rd.devices_info = create<SoundIoDevicesInfo>())) {
|
if (!(rd.devices_info = create<SoundIoDevicesInfo>())) {
|
||||||
deinit_refresh_devices(&rd);
|
deinit_refresh_devices(&rd);
|
||||||
|
@ -415,7 +416,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int device_i = 0; device_i < device_count; device_i += 1) {
|
for (int device_i = 0; device_i < device_count; device_i += 1) {
|
||||||
AudioObjectID deviceID = rd.devices[device_i];
|
AudioObjectID device_id = rd.devices[device_i];
|
||||||
|
|
||||||
prop_address.mSelector = kAudioObjectPropertyName;
|
prop_address.mSelector = kAudioObjectPropertyName;
|
||||||
prop_address.mScope = kAudioObjectPropertyScopeGlobal;
|
prop_address.mScope = kAudioObjectPropertyScopeGlobal;
|
||||||
|
@ -425,7 +426,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
CFRelease(rd.string_ref);
|
CFRelease(rd.string_ref);
|
||||||
rd.string_ref = nullptr;
|
rd.string_ref = nullptr;
|
||||||
}
|
}
|
||||||
if ((os_err = AudioObjectGetPropertyData(deviceID, &prop_address,
|
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address,
|
||||||
0, nullptr, &io_size, &rd.string_ref)))
|
0, nullptr, &io_size, &rd.string_ref)))
|
||||||
{
|
{
|
||||||
deinit_refresh_devices(&rd);
|
deinit_refresh_devices(&rd);
|
||||||
|
@ -447,7 +448,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
CFRelease(rd.string_ref);
|
CFRelease(rd.string_ref);
|
||||||
rd.string_ref = nullptr;
|
rd.string_ref = nullptr;
|
||||||
}
|
}
|
||||||
if ((os_err = AudioObjectGetPropertyData(deviceID, &prop_address,
|
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address,
|
||||||
0, nullptr, &io_size, &rd.string_ref)))
|
0, nullptr, &io_size, &rd.string_ref)))
|
||||||
{
|
{
|
||||||
deinit_refresh_devices(&rd);
|
deinit_refresh_devices(&rd);
|
||||||
|
@ -469,7 +470,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
prop_address.mSelector = kAudioDevicePropertyStreamConfiguration;
|
prop_address.mSelector = kAudioDevicePropertyStreamConfiguration;
|
||||||
prop_address.mScope = aim_to_scope(aim);
|
prop_address.mScope = aim_to_scope(aim);
|
||||||
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
||||||
if ((os_err = AudioObjectGetPropertyDataSize(deviceID, &prop_address, 0, nullptr, &io_size))) {
|
if ((os_err = AudioObjectGetPropertyDataSize(device_id, &prop_address, 0, nullptr, &io_size))) {
|
||||||
deinit_refresh_devices(&rd);
|
deinit_refresh_devices(&rd);
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
|
@ -481,7 +482,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
return SoundIoErrorNoMem;
|
return SoundIoErrorNoMem;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((os_err = AudioObjectGetPropertyData(deviceID, &prop_address, 0, nullptr,
|
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, nullptr,
|
||||||
&io_size, rd.buffer_list)))
|
&io_size, rd.buffer_list)))
|
||||||
{
|
{
|
||||||
deinit_refresh_devices(&rd);
|
deinit_refresh_devices(&rd);
|
||||||
|
@ -501,6 +502,8 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
deinit_refresh_devices(&rd);
|
deinit_refresh_devices(&rd);
|
||||||
return SoundIoErrorNoMem;
|
return SoundIoErrorNoMem;
|
||||||
}
|
}
|
||||||
|
SoundIoDeviceCoreAudio *dca = &dev->backend_data.coreaudio;
|
||||||
|
dca->device_id = device_id;
|
||||||
assert(!rd.device);
|
assert(!rd.device);
|
||||||
rd.device = &dev->pub;
|
rd.device = &dev->pub;
|
||||||
rd.device->ref_count = 1;
|
rd.device->ref_count = 1;
|
||||||
|
@ -522,7 +525,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
prop_address.mSelector = kAudioDevicePropertyPreferredChannelLayout;
|
prop_address.mSelector = kAudioDevicePropertyPreferredChannelLayout;
|
||||||
prop_address.mScope = aim_to_scope(aim);
|
prop_address.mScope = aim_to_scope(aim);
|
||||||
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
||||||
if (!(os_err = AudioObjectGetPropertyDataSize(deviceID, &prop_address,
|
if (!(os_err = AudioObjectGetPropertyDataSize(device_id, &prop_address,
|
||||||
0, nullptr, &io_size)))
|
0, nullptr, &io_size)))
|
||||||
{
|
{
|
||||||
rd.audio_channel_layout = (AudioChannelLayout *)allocate<char>(io_size);
|
rd.audio_channel_layout = (AudioChannelLayout *)allocate<char>(io_size);
|
||||||
|
@ -530,7 +533,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
deinit_refresh_devices(&rd);
|
deinit_refresh_devices(&rd);
|
||||||
return SoundIoErrorNoMem;
|
return SoundIoErrorNoMem;
|
||||||
}
|
}
|
||||||
if ((os_err = AudioObjectGetPropertyData(deviceID, &prop_address, 0, nullptr,
|
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, nullptr,
|
||||||
&io_size, rd.audio_channel_layout)))
|
&io_size, rd.audio_channel_layout)))
|
||||||
{
|
{
|
||||||
deinit_refresh_devices(&rd);
|
deinit_refresh_devices(&rd);
|
||||||
|
@ -555,7 +558,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
prop_address.mScope = aim_to_scope(aim);
|
prop_address.mScope = aim_to_scope(aim);
|
||||||
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
||||||
io_size = sizeof(double);
|
io_size = sizeof(double);
|
||||||
if ((os_err = AudioObjectGetPropertyData(deviceID, &prop_address, 0, nullptr,
|
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, nullptr,
|
||||||
&io_size, &rd.device->sample_rate_current)))
|
&io_size, &rd.device->sample_rate_current)))
|
||||||
{
|
{
|
||||||
deinit_refresh_devices(&rd);
|
deinit_refresh_devices(&rd);
|
||||||
|
@ -565,7 +568,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
prop_address.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
|
prop_address.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
|
||||||
prop_address.mScope = aim_to_scope(aim);
|
prop_address.mScope = aim_to_scope(aim);
|
||||||
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
||||||
if ((os_err = AudioObjectGetPropertyDataSize(deviceID, &prop_address, 0, nullptr,
|
if ((os_err = AudioObjectGetPropertyDataSize(device_id, &prop_address, 0, nullptr,
|
||||||
&io_size)))
|
&io_size)))
|
||||||
{
|
{
|
||||||
deinit_refresh_devices(&rd);
|
deinit_refresh_devices(&rd);
|
||||||
|
@ -579,7 +582,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
return SoundIoErrorNoMem;
|
return SoundIoErrorNoMem;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((os_err = AudioObjectGetPropertyData(deviceID, &prop_address, 0, nullptr,
|
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, nullptr,
|
||||||
&io_size, rd.avr_array)))
|
&io_size, rd.avr_array)))
|
||||||
{
|
{
|
||||||
deinit_refresh_devices(&rd);
|
deinit_refresh_devices(&rd);
|
||||||
|
@ -601,7 +604,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
||||||
io_size = sizeof(UInt32);
|
io_size = sizeof(UInt32);
|
||||||
UInt32 buffer_frame_size;
|
UInt32 buffer_frame_size;
|
||||||
if ((os_err = AudioObjectGetPropertyData(deviceID, &prop_address, 0, nullptr,
|
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, nullptr,
|
||||||
&io_size, &buffer_frame_size)))
|
&io_size, &buffer_frame_size)))
|
||||||
{
|
{
|
||||||
deinit_refresh_devices(&rd);
|
deinit_refresh_devices(&rd);
|
||||||
|
@ -616,7 +619,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
prop_address.mElement = kAudioObjectPropertyElementMaster;
|
||||||
io_size = sizeof(AudioValueRange);
|
io_size = sizeof(AudioValueRange);
|
||||||
AudioValueRange avr;
|
AudioValueRange avr;
|
||||||
if ((os_err = AudioObjectGetPropertyData(deviceID, &prop_address, 0, nullptr,
|
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, nullptr,
|
||||||
&io_size, &avr)))
|
&io_size, &avr)))
|
||||||
{
|
{
|
||||||
deinit_refresh_devices(&rd);
|
deinit_refresh_devices(&rd);
|
||||||
|
@ -630,12 +633,12 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
||||||
SoundIoList<SoundIoDevice *> *device_list;
|
SoundIoList<SoundIoDevice *> *device_list;
|
||||||
if (rd.device->aim == SoundIoDeviceAimOutput) {
|
if (rd.device->aim == SoundIoDeviceAimOutput) {
|
||||||
device_list = &rd.devices_info->output_devices;
|
device_list = &rd.devices_info->output_devices;
|
||||||
if (deviceID == default_output_id)
|
if (device_id == default_output_id)
|
||||||
rd.devices_info->default_output_index = device_list->length;
|
rd.devices_info->default_output_index = device_list->length;
|
||||||
} else {
|
} else {
|
||||||
assert(rd.device->aim == SoundIoDeviceAimInput);
|
assert(rd.device->aim == SoundIoDeviceAimInput);
|
||||||
device_list = &rd.devices_info->input_devices;
|
device_list = &rd.devices_info->input_devices;
|
||||||
if (deviceID == default_input_id)
|
if (device_id == default_input_id)
|
||||||
rd.devices_info->default_input_index = device_list->length;
|
rd.devices_info->default_input_index = device_list->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -749,109 +752,160 @@ static void device_thread_run(void *arg) {
|
||||||
|
|
||||||
static void outstream_destroy_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
|
static void outstream_destroy_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
|
||||||
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
|
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
|
||||||
if (osca->device_uid_string_ref)
|
if (osca->output_instance)
|
||||||
CFRelease(osca->device_uid_string_ref);
|
AudioComponentInstanceDispose(osca->output_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus write_callback_ca(void *userdata, AudioUnitRenderActionFlags *io_action_flags,
|
||||||
|
const AudioTimeStamp *in_time_stamp, UInt32 in_bus_number, UInt32 in_number_frames,
|
||||||
|
AudioBufferList *io_data)
|
||||||
|
{
|
||||||
|
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *) userdata;
|
||||||
|
SoundIoOutStream *outstream = &os->pub;
|
||||||
|
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
|
||||||
|
|
||||||
|
osca->io_data = io_data;
|
||||||
|
osca->buffer_index = 0;
|
||||||
|
outstream->write_callback(outstream, in_number_frames);
|
||||||
|
osca->io_data = nullptr;
|
||||||
|
|
||||||
|
return noErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
@constant kAudioHardwarePropertyTranslateUIDToDevice
|
|
||||||
This property fetches the AudioObjectID that corresponds to the AudioDevice
|
|
||||||
that has the given UID. The UID is passed in via the qualifier as a CFString
|
|
||||||
while the AudioObjectID for the AudioDevice is returned to the caller as the
|
|
||||||
property's data. Note that an error is not returned if the UID doesn't refer
|
|
||||||
to any AudioDevices. Rather, this property will return kAudioObjectUnknown
|
|
||||||
as the value of the property.
|
|
||||||
*/
|
|
||||||
static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
|
static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
|
||||||
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
|
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
|
||||||
SoundIoOutStream *outstream = &os->pub;
|
SoundIoOutStream *outstream = &os->pub;
|
||||||
SoundIoDevice *device = outstream->device;
|
SoundIoDevice *device = outstream->device;
|
||||||
|
SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
|
||||||
|
SoundIoDeviceCoreAudio *dca = &dev->backend_data.coreaudio;
|
||||||
|
|
||||||
|
AudioComponentDescription desc;
|
||||||
|
desc.componentType = kAudioUnitType_Output;
|
||||||
|
desc.componentSubType = kAudioUnitSubType_HALOutput;
|
||||||
|
desc.componentFlags = 0;
|
||||||
|
desc.componentFlagsMask = 0;
|
||||||
|
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||||
|
|
||||||
|
AudioComponent output_comp = AudioComponentFindNext(nullptr, &desc);
|
||||||
|
if (!output_comp) {
|
||||||
|
soundio_panic("find next comp");
|
||||||
|
}
|
||||||
|
|
||||||
UInt32 io_size;
|
|
||||||
OSStatus os_err;
|
OSStatus os_err;
|
||||||
|
if ((os_err = AudioComponentInstanceNew(output_comp, &osca->output_instance))) {
|
||||||
|
soundio_panic("AudioComponentInstanceNew");
|
||||||
osca->device_uid_string_ref = to_cf_string(device->id);
|
|
||||||
if (!osca->device_uid_string_ref) {
|
|
||||||
outstream_destroy_ca(si, os);
|
|
||||||
return SoundIoErrorNoMem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioObjectPropertyAddress prop_address = {
|
if ((os_err = AudioUnitInitialize(osca->output_instance))) {
|
||||||
kAudioHardwarePropertyTranslateUIDToDevice,
|
soundio_panic("AudioUnitInitialize");
|
||||||
kAudioObjectPropertyScopeGlobal,
|
}
|
||||||
kAudioObjectPropertyElementMaster
|
|
||||||
};
|
AudioStreamBasicDescription format = {0};
|
||||||
io_size = sizeof(AudioDeviceID);
|
format.mSampleRate = outstream->sample_rate;
|
||||||
if ((os_err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop_address,
|
format.mFormatID = kAudioFormatLinearPCM;
|
||||||
sizeof(CFStringRef), osca->device_uid_string_ref,
|
format.mFormatFlags = kAudioFormatFlagIsFloat;
|
||||||
&io_size, &osca->device_id)))
|
format.mBytesPerPacket = outstream->bytes_per_frame;
|
||||||
|
format.mFramesPerPacket = 1;
|
||||||
|
format.mBytesPerFrame = outstream->bytes_per_frame;
|
||||||
|
format.mChannelsPerFrame = outstream->layout.channel_count;
|
||||||
|
format.mBitsPerChannel = 32;
|
||||||
|
|
||||||
|
if ((os_err = AudioUnitSetProperty(osca->output_instance, kAudioOutputUnitProperty_CurrentDevice,
|
||||||
|
kAudioUnitScope_Input, 0, &dca->device_id, sizeof(AudioDeviceID))))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "derpde derpdee derr\n");
|
soundio_panic("set device");
|
||||||
outstream_destroy_ca(si, os);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (osca->device_id == kAudioObjectUnknown) {
|
if ((os_err = AudioUnitSetProperty(osca->output_instance, kAudioUnitProperty_StreamFormat,
|
||||||
outstream_destroy_ca(si, os);
|
kAudioUnitScope_Input, 0, &format, sizeof(AudioStreamBasicDescription))))
|
||||||
return SoundIoErrorNoSuchDevice;
|
{
|
||||||
|
soundio_panic("AudioUnitSetProperty format %d", os_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "id: %ld\n", (long)osca->device_id);
|
AURenderCallbackStruct render_callback = {write_callback_ca, os};
|
||||||
|
if ((os_err = AudioUnitSetProperty(osca->output_instance, kAudioUnitProperty_SetRenderCallback,
|
||||||
|
kAudioUnitScope_Input, 0, &render_callback, sizeof(AURenderCallbackStruct))))
|
||||||
|
{
|
||||||
|
soundio_panic("AudioUnitSetProperty callback");
|
||||||
|
}
|
||||||
|
|
||||||
soundio_panic("TODO");
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int outstream_start_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
|
static int outstream_start_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
|
||||||
soundio_panic("TODO");
|
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
|
||||||
|
OSStatus os_err;
|
||||||
|
if ((os_err = AudioOutputUnitStart(osca->output_instance))) {
|
||||||
|
soundio_panic("audio outut unit start");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int outstream_begin_write_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
|
static int outstream_begin_write_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
|
||||||
SoundIoChannelArea **out_areas, int *frame_count)
|
SoundIoChannelArea **out_areas, int *out_frame_count)
|
||||||
{
|
{
|
||||||
soundio_panic("TODO");
|
SoundIoOutStream *outstream = &os->pub;
|
||||||
|
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
|
||||||
|
|
||||||
|
if (osca->buffer_index < osca->io_data->mNumberBuffers) {
|
||||||
|
AudioBuffer *audio_buffer = &osca->io_data->mBuffers[osca->buffer_index];
|
||||||
|
assert(audio_buffer->mNumberChannels == outstream->layout.channel_count);
|
||||||
|
*out_frame_count = audio_buffer->mDataByteSize / outstream->bytes_per_frame;
|
||||||
|
assert((audio_buffer->mDataByteSize % outstream->bytes_per_frame) == 0);
|
||||||
|
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
|
||||||
|
osca->areas[ch].ptr = ((char*)audio_buffer->mData) + outstream->bytes_per_sample * ch;
|
||||||
|
osca->areas[ch].step = outstream->bytes_per_frame;
|
||||||
|
}
|
||||||
|
*out_areas = osca->areas;
|
||||||
|
} else {
|
||||||
|
*out_areas = nullptr;
|
||||||
|
*out_frame_count = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int outstream_end_write_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
|
static int outstream_end_write_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, int)
|
||||||
int frame_count)
|
|
||||||
{
|
{
|
||||||
soundio_panic("TODO");
|
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
|
||||||
|
osca->buffer_index += 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int outstream_clear_buffer_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
|
static int outstream_clear_buffer_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
|
||||||
soundio_panic("TODO");
|
soundio_panic("TODO clear buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int outstream_pause_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, bool pause) {
|
static int outstream_pause_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, bool pause) {
|
||||||
soundio_panic("TODO");
|
soundio_panic("TODO pause");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int instream_open_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
static int instream_open_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
||||||
soundio_panic("TODO");
|
soundio_panic("TODO open");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void instream_destroy_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
static void instream_destroy_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
||||||
soundio_panic("TODO");
|
soundio_panic("TODO destroy");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int instream_start_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
static int instream_start_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
||||||
soundio_panic("TODO");
|
soundio_panic("TODO start");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int instream_begin_read_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is,
|
static int instream_begin_read_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is,
|
||||||
SoundIoChannelArea **out_areas, int *frame_count)
|
SoundIoChannelArea **out_areas, int *frame_count)
|
||||||
{
|
{
|
||||||
soundio_panic("TODO");
|
soundio_panic("TODO begin read");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int instream_end_read_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
static int instream_end_read_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
||||||
soundio_panic("TODO");
|
soundio_panic("TODO end read");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int instream_pause_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is, bool pause) {
|
static int instream_pause_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is, bool pause) {
|
||||||
soundio_panic("TODO");
|
soundio_panic("TODO pause");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
#include "soundio/os.h"
|
#include "soundio/os.h"
|
||||||
#include "atomics.hpp"
|
#include "atomics.hpp"
|
||||||
|
|
||||||
#include <CoreAudio.h>
|
#include <CoreAudio/CoreAudio.h>
|
||||||
|
#include <AudioUnit/AudioUnit.h>
|
||||||
|
|
||||||
int soundio_coreaudio_init(struct SoundIoPrivate *si);
|
int soundio_coreaudio_init(struct SoundIoPrivate *si);
|
||||||
|
|
||||||
struct SoundIoDeviceCoreAudio { };
|
struct SoundIoDeviceCoreAudio {
|
||||||
|
AudioDeviceID device_id;
|
||||||
|
};
|
||||||
|
|
||||||
struct SoundIoCoreAudio {
|
struct SoundIoCoreAudio {
|
||||||
SoundIoOsMutex *mutex;
|
SoundIoOsMutex *mutex;
|
||||||
|
@ -37,8 +40,10 @@ struct SoundIoCoreAudio {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SoundIoOutStreamCoreAudio {
|
struct SoundIoOutStreamCoreAudio {
|
||||||
CFStringRef device_uid_string_ref;
|
AudioComponentInstance output_instance;
|
||||||
AudioDeviceID device_id;
|
AudioBufferList *io_data;
|
||||||
|
int buffer_index;
|
||||||
|
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SoundIoInStreamCoreAudio {
|
struct SoundIoInStreamCoreAudio {
|
||||||
|
|
Loading…
Reference in a new issue