coreaudio: support more formats: S16LE, S32LE, and Float64LE

This commit is contained in:
Michael Maltese 2016-04-26 16:24:37 -07:00
parent 2e064bfca8
commit 8742fe215d

View file

@ -628,10 +628,15 @@ static int refresh_devices(struct SoundIoPrivate *si) {
rd.device->layout_count = 1;
rd.device->layouts = &rd.device->current_layout;
// in CoreAudio, format is always 32-bit native endian float
rd.device->format_count = 1;
rd.device->formats = &dev->prealloc_format;
rd.device->formats[0] = SoundIoFormatFloat32NE;
rd.device->format_count = 4;
rd.device->formats = ALLOCATE(enum SoundIoFormat, rd.device->format_count);
if (!rd.device->formats)
return SoundIoErrorNoMem;
rd.device->formats[0] = SoundIoFormatS16LE;
rd.device->formats[1] = SoundIoFormatS32LE;
rd.device->formats[2] = SoundIoFormatFloat32LE;
rd.device->formats[3] = SoundIoFormatFloat64LE;
prop_address.mSelector = kAudioDevicePropertyNominalSampleRate;
prop_address.mScope = aim_to_scope(aim);
@ -914,6 +919,30 @@ static OSStatus write_callback_ca(void *userdata, AudioUnitRenderActionFlags *io
return noErr;
}
static int set_ca_desc(enum SoundIoFormat fmt, AudioStreamBasicDescription *desc) {
switch (fmt) {
case SoundIoFormatFloat32LE:
desc->mFormatFlags = kAudioFormatFlagIsFloat;
desc->mBitsPerChannel = 32;
break;
case SoundIoFormatFloat64LE:
desc->mFormatFlags = kAudioFormatFlagIsFloat;
desc->mBitsPerChannel = 64;
break;
case SoundIoFormatS32LE:
desc->mFormatFlags = kAudioFormatFlagIsSignedInteger;
desc->mBitsPerChannel = 32;
break;
case SoundIoFormatS16LE:
desc->mFormatFlags = kAudioFormatFlagIsSignedInteger;
desc->mBitsPerChannel = 16;
break;
default:
return SoundIoErrorIncompatibleDevice;
}
return 0;
}
static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
struct SoundIoOutStream *outstream = &os->pub;
@ -954,12 +983,15 @@ static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamP
AudioStreamBasicDescription format = {0};
format.mSampleRate = outstream->sample_rate;
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kAudioFormatFlagIsFloat;
int err;
if ((err = set_ca_desc(outstream->format, &format))) {
outstream_destroy_ca(si, os);
return err;
}
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->instance, kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Input, OUTPUT_ELEMENT, &dca->device_id, sizeof(AudioDeviceID))))
@ -972,7 +1004,7 @@ static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamP
kAudioUnitScope_Input, OUTPUT_ELEMENT, &format, sizeof(AudioStreamBasicDescription))))
{
outstream_destroy_ca(si, os);
return SoundIoErrorOpeningDevice;
return SoundIoErrorIncompatibleDevice;
}
AURenderCallbackStruct render_callback = {write_callback_ca, os};
@ -1245,12 +1277,16 @@ static int instream_open_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPri
AudioStreamBasicDescription format = {0};
format.mSampleRate = instream->sample_rate;
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kAudioFormatFlagIsFloat;
format.mBytesPerPacket = instream->bytes_per_frame;
format.mFramesPerPacket = 1;
format.mBytesPerFrame = instream->bytes_per_frame;
format.mChannelsPerFrame = instream->layout.channel_count;
format.mBitsPerChannel = 32;
int err;
if ((err = set_ca_desc(instream->format, &format))) {
instream_destroy_ca(si, is);
return err;
}
if ((os_err = AudioUnitSetProperty(isca->instance, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output, INPUT_ELEMENT, &format, sizeof(AudioStreamBasicDescription))))