mirror of https://github.com/encounter/SDL.git
coreaudio: Implemented audio capture for iOS.
This commit is contained in:
parent
f758483a28
commit
a9ef240cef
|
@ -268,6 +268,27 @@ device_list_changed(AudioObjectID systemObj, UInt32 num_addr, const AudioObjectP
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static int open_playback_devices = 0;
|
||||||
|
static int open_capture_devices = 0;
|
||||||
|
|
||||||
|
static void update_audio_session()
|
||||||
|
{
|
||||||
|
#if !MACOSX_COREAUDIO
|
||||||
|
/* !!! FIXME: move this to AVAudioSession. This is deprecated, and the new version is available as of (ancient!) iOS 3.0 */
|
||||||
|
UInt32 category;
|
||||||
|
if (open_playback_devices && open_capture_devices) {
|
||||||
|
category = kAudioSessionCategory_PlayAndRecord;
|
||||||
|
} else if (open_capture_devices) {
|
||||||
|
category = kAudioSessionCategory_RecordAudio;
|
||||||
|
} else { /* nothing open, or just playing audio. */
|
||||||
|
category = kAudioSessionCategory_AmbientSound;
|
||||||
|
}
|
||||||
|
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof (UInt32), &category);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* The CoreAudio callback */
|
/* The CoreAudio callback */
|
||||||
static OSStatus
|
static OSStatus
|
||||||
outputCallback(void *inRefCon,
|
outputCallback(void *inRefCon,
|
||||||
|
@ -416,6 +437,7 @@ static void
|
||||||
COREAUDIO_CloseDevice(_THIS)
|
COREAUDIO_CloseDevice(_THIS)
|
||||||
{
|
{
|
||||||
if (this->hidden != NULL) {
|
if (this->hidden != NULL) {
|
||||||
|
const int iscapture = this->iscapture;
|
||||||
if (this->hidden->audioUnitOpened) {
|
if (this->hidden->audioUnitOpened) {
|
||||||
#if MACOSX_COREAUDIO
|
#if MACOSX_COREAUDIO
|
||||||
/* Unregister our disconnect callback. */
|
/* Unregister our disconnect callback. */
|
||||||
|
@ -425,7 +447,6 @@ COREAUDIO_CloseDevice(_THIS)
|
||||||
AURenderCallbackStruct callback;
|
AURenderCallbackStruct callback;
|
||||||
const AudioUnitElement output_bus = 0;
|
const AudioUnitElement output_bus = 0;
|
||||||
const AudioUnitElement input_bus = 1;
|
const AudioUnitElement input_bus = 1;
|
||||||
const int iscapture = this->iscapture;
|
|
||||||
const AudioUnitElement bus =
|
const AudioUnitElement bus =
|
||||||
((iscapture) ? input_bus : output_bus);
|
((iscapture) ? input_bus : output_bus);
|
||||||
|
|
||||||
|
@ -440,13 +461,19 @@ COREAUDIO_CloseDevice(_THIS)
|
||||||
AudioComponentInstanceDispose(this->hidden->audioUnit);
|
AudioComponentInstanceDispose(this->hidden->audioUnit);
|
||||||
this->hidden->audioUnitOpened = 0;
|
this->hidden->audioUnitOpened = 0;
|
||||||
|
|
||||||
#if MACOSX_COREAUDIO
|
|
||||||
SDL_free(this->hidden->captureBufferList.mBuffers[0].mData);
|
SDL_free(this->hidden->captureBufferList.mBuffers[0].mData);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
SDL_free(this->hidden->buffer);
|
SDL_free(this->hidden->buffer);
|
||||||
SDL_free(this->hidden);
|
SDL_free(this->hidden);
|
||||||
this->hidden = NULL;
|
this->hidden = NULL;
|
||||||
|
|
||||||
|
if (iscapture) {
|
||||||
|
open_capture_devices--;
|
||||||
|
} else {
|
||||||
|
open_playback_devices--;
|
||||||
|
}
|
||||||
|
update_audio_session();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,7 +571,6 @@ prepare_audiounit(_THIS, void *handle, int iscapture,
|
||||||
|
|
||||||
this->hidden->audioUnitOpened = 1;
|
this->hidden->audioUnitOpened = 1;
|
||||||
|
|
||||||
#if MACOSX_COREAUDIO
|
|
||||||
if (iscapture) { /* have to do EnableIO only for capture devices. */
|
if (iscapture) { /* have to do EnableIO only for capture devices. */
|
||||||
UInt32 enable = 1;
|
UInt32 enable = 1;
|
||||||
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||||
|
@ -563,6 +589,7 @@ prepare_audiounit(_THIS, void *handle, int iscapture,
|
||||||
("AudioUnitSetProperty (kAudioOutputUnitProperty_EnableIO output bus)");
|
("AudioUnitSetProperty (kAudioOutputUnitProperty_EnableIO output bus)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MACOSX_COREAUDIO
|
||||||
/* this is always on the output_bus, even for capture devices. */
|
/* this is always on the output_bus, even for capture devices. */
|
||||||
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||||
kAudioOutputUnitProperty_CurrentDevice,
|
kAudioOutputUnitProperty_CurrentDevice,
|
||||||
|
@ -581,14 +608,13 @@ prepare_audiounit(_THIS, void *handle, int iscapture,
|
||||||
strdesc, sizeof (*strdesc));
|
strdesc, sizeof (*strdesc));
|
||||||
CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)");
|
CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)");
|
||||||
|
|
||||||
#if MACOSX_COREAUDIO
|
|
||||||
if (iscapture) { /* only need to do this for capture devices. */
|
if (iscapture) { /* only need to do this for capture devices. */
|
||||||
void *ptr;
|
void *ptr;
|
||||||
UInt32 framesize = 0;
|
UInt32 framesize = 0;
|
||||||
UInt32 propsize = sizeof (UInt32);
|
UInt32 propsize = sizeof (UInt32);
|
||||||
|
|
||||||
result = AudioUnitGetProperty(this->hidden->audioUnit,
|
result = AudioUnitGetProperty(this->hidden->audioUnit,
|
||||||
kAudioDevicePropertyBufferFrameSize,
|
kAudioUnitProperty_MaximumFramesPerSlice,
|
||||||
kAudioUnitScope_Global, output_bus,
|
kAudioUnitScope_Global, output_bus,
|
||||||
&framesize, &propsize);
|
&framesize, &propsize);
|
||||||
CHECK_RESULT
|
CHECK_RESULT
|
||||||
|
@ -601,13 +627,11 @@ prepare_audiounit(_THIS, void *handle, int iscapture,
|
||||||
SDL_OutOfMemory();
|
SDL_OutOfMemory();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->hidden->captureBufferList.mNumberBuffers = 1;
|
this->hidden->captureBufferList.mNumberBuffers = 1;
|
||||||
this->hidden->captureBufferList.mBuffers[0].mNumberChannels = this->spec.channels;
|
this->hidden->captureBufferList.mBuffers[0].mNumberChannels = this->spec.channels;
|
||||||
this->hidden->captureBufferList.mBuffers[0].mDataByteSize = framesize;
|
this->hidden->captureBufferList.mBuffers[0].mDataByteSize = framesize;
|
||||||
this->hidden->captureBufferList.mBuffers[0].mData = ptr;
|
this->hidden->captureBufferList.mBuffers[0].mData = ptr;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Set the audio callback */
|
/* Set the audio callback */
|
||||||
SDL_zero(callback);
|
SDL_zero(callback);
|
||||||
|
@ -616,7 +640,9 @@ prepare_audiounit(_THIS, void *handle, int iscapture,
|
||||||
|
|
||||||
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||||
iscapture ? kAudioOutputUnitProperty_SetInputCallback : kAudioUnitProperty_SetRenderCallback,
|
iscapture ? kAudioOutputUnitProperty_SetInputCallback : kAudioUnitProperty_SetRenderCallback,
|
||||||
kAudioUnitScope_Global, output_bus, &callback, sizeof(callback));
|
kAudioUnitScope_Global,
|
||||||
|
iscapture ? input_bus : output_bus,
|
||||||
|
&callback, sizeof (callback));
|
||||||
CHECK_RESULT
|
CHECK_RESULT
|
||||||
("AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback)");
|
("AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback)");
|
||||||
|
|
||||||
|
@ -668,6 +694,13 @@ COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
}
|
}
|
||||||
SDL_zerop(this->hidden);
|
SDL_zerop(this->hidden);
|
||||||
|
|
||||||
|
if (iscapture) {
|
||||||
|
open_capture_devices++;
|
||||||
|
} else {
|
||||||
|
open_playback_devices++;
|
||||||
|
}
|
||||||
|
update_audio_session();
|
||||||
|
|
||||||
/* Setup a AudioStreamBasicDescription with the requested format */
|
/* Setup a AudioStreamBasicDescription with the requested format */
|
||||||
SDL_zero(strdesc);
|
SDL_zero(strdesc);
|
||||||
strdesc.mFormatID = kAudioFormatLinearPCM;
|
strdesc.mFormatID = kAudioFormatLinearPCM;
|
||||||
|
@ -742,20 +775,22 @@ COREAUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||||
#if MACOSX_COREAUDIO
|
#if MACOSX_COREAUDIO
|
||||||
impl->DetectDevices = COREAUDIO_DetectDevices;
|
impl->DetectDevices = COREAUDIO_DetectDevices;
|
||||||
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
|
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
|
||||||
impl->HasCaptureSupport = 1;
|
|
||||||
#else
|
#else
|
||||||
impl->OnlyHasDefaultOutputDevice = 1;
|
impl->OnlyHasDefaultOutputDevice = 1;
|
||||||
|
impl->OnlyHasDefaultInputDevice = 1;
|
||||||
|
|
||||||
/* Set category to ambient sound so that other music continues playing.
|
/* Set category to ambient sound so that other music continues playing.
|
||||||
You can change this at runtime in your own code if you need different
|
You can change this at runtime in your own code if you need different
|
||||||
behavior. If this is common, we can add an SDL hint for this.
|
behavior. If this is common, we can add an SDL hint for this.
|
||||||
*/
|
*/
|
||||||
|
/* !!! FIXME: move this to AVAudioSession. This is deprecated, and the new version is available as of (ancient!) iOS 3.0 */
|
||||||
AudioSessionInitialize(NULL, NULL, NULL, nil);
|
AudioSessionInitialize(NULL, NULL, NULL, nil);
|
||||||
UInt32 category = kAudioSessionCategory_AmbientSound;
|
UInt32 category = kAudioSessionCategory_AmbientSound;
|
||||||
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(UInt32), &category);
|
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(UInt32), &category);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
impl->ProvidesOwnCallbackThread = 1;
|
impl->ProvidesOwnCallbackThread = 1;
|
||||||
|
impl->HasCaptureSupport = 1;
|
||||||
|
|
||||||
return 1; /* this audio target is available. */
|
return 1; /* this audio target is available. */
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,9 +48,9 @@ struct SDL_PrivateAudioData
|
||||||
void *buffer;
|
void *buffer;
|
||||||
UInt32 bufferOffset;
|
UInt32 bufferOffset;
|
||||||
UInt32 bufferSize;
|
UInt32 bufferSize;
|
||||||
|
AudioBufferList captureBufferList;
|
||||||
#if MACOSX_COREAUDIO
|
#if MACOSX_COREAUDIO
|
||||||
AudioDeviceID deviceID;
|
AudioDeviceID deviceID;
|
||||||
AudioBufferList captureBufferList;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue