Merge pull request #71 from michaelmaltese/feature-more-coreaudio-formats

coreaudio: support more formats: S16LE, S32LE, and Float64LE
This commit is contained in:
Andrew Kelley 2016-04-26 16:46:31 -07:00
commit 45d5691254

View file

@ -631,10 +631,15 @@ static int refresh_devices(struct SoundIoPrivate *si) {
rd.device->layout_count = 1; rd.device->layout_count = 1;
rd.device->layouts = &rd.device->current_layout; rd.device->layouts = &rd.device->current_layout;
// in CoreAudio, format is always 32-bit native endian float
rd.device->format_count = 1; rd.device->format_count = 4;
rd.device->formats = &dev->prealloc_format; rd.device->formats = ALLOCATE(enum SoundIoFormat, rd.device->format_count);
rd.device->formats[0] = SoundIoFormatFloat32NE; 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.mSelector = kAudioDevicePropertyNominalSampleRate;
prop_address.mScope = aim_to_scope(aim); prop_address.mScope = aim_to_scope(aim);
@ -917,6 +922,30 @@ static OSStatus write_callback_ca(void *userdata, AudioUnitRenderActionFlags *io
return noErr; 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) { static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio; struct SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
struct SoundIoOutStream *outstream = &os->pub; struct SoundIoOutStream *outstream = &os->pub;
@ -957,12 +986,15 @@ static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamP
AudioStreamBasicDescription format = {0}; AudioStreamBasicDescription format = {0};
format.mSampleRate = outstream->sample_rate; format.mSampleRate = outstream->sample_rate;
format.mFormatID = kAudioFormatLinearPCM; 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.mBytesPerPacket = outstream->bytes_per_frame;
format.mFramesPerPacket = 1; format.mFramesPerPacket = 1;
format.mBytesPerFrame = outstream->bytes_per_frame; format.mBytesPerFrame = outstream->bytes_per_frame;
format.mChannelsPerFrame = outstream->layout.channel_count; format.mChannelsPerFrame = outstream->layout.channel_count;
format.mBitsPerChannel = 32;
if ((os_err = AudioUnitSetProperty(osca->instance, kAudioOutputUnitProperty_CurrentDevice, if ((os_err = AudioUnitSetProperty(osca->instance, kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Input, OUTPUT_ELEMENT, &dca->device_id, sizeof(AudioDeviceID)))) kAudioUnitScope_Input, OUTPUT_ELEMENT, &dca->device_id, sizeof(AudioDeviceID))))
@ -975,7 +1007,7 @@ static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamP
kAudioUnitScope_Input, OUTPUT_ELEMENT, &format, sizeof(AudioStreamBasicDescription)))) kAudioUnitScope_Input, OUTPUT_ELEMENT, &format, sizeof(AudioStreamBasicDescription))))
{ {
outstream_destroy_ca(si, os); outstream_destroy_ca(si, os);
return SoundIoErrorOpeningDevice; return SoundIoErrorIncompatibleDevice;
} }
AURenderCallbackStruct render_callback = {write_callback_ca, os}; AURenderCallbackStruct render_callback = {write_callback_ca, os};
@ -1248,12 +1280,16 @@ static int instream_open_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPri
AudioStreamBasicDescription format = {0}; AudioStreamBasicDescription format = {0};
format.mSampleRate = instream->sample_rate; format.mSampleRate = instream->sample_rate;
format.mFormatID = kAudioFormatLinearPCM; format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kAudioFormatFlagIsFloat;
format.mBytesPerPacket = instream->bytes_per_frame; format.mBytesPerPacket = instream->bytes_per_frame;
format.mFramesPerPacket = 1; format.mFramesPerPacket = 1;
format.mBytesPerFrame = instream->bytes_per_frame; format.mBytesPerFrame = instream->bytes_per_frame;
format.mChannelsPerFrame = instream->layout.channel_count; 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, if ((os_err = AudioUnitSetProperty(isca->instance, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output, INPUT_ELEMENT, &format, sizeof(AudioStreamBasicDescription)))) kAudioUnitScope_Output, INPUT_ELEMENT, &format, sizeof(AudioStreamBasicDescription))))