aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Ning <yu.ning@intel.com>2015-04-24 17:47:45 +0800
committerYu Ning <yu.ning@intel.com>2015-04-28 17:59:54 +0800
commita931717d2d5ed5c65deb6f9d6bd184c0b75c7891 (patch)
treef68044a5f4e3a383fe0d253d47be51f9f739b231
parenta50f6cf6dd6e924cb1e5648176ff4e23af26834f (diff)
downloadqemu-android-a931717d2d5ed5c65deb6f9d6bd184c0b75c7891.tar.gz
coreaudio: Incorporate changes from the classic Android emulator
The current CoreAudio driver (audio/coreaudio.c) is missing an input voice and thus does not support audio input. Fortunately, its counterpart in the classic Android emulator has got this feature implemented. In order to enable audio input in qemu-android on Mac, merge audio/coreaudio.c from AOSP's external/qemu project at commit 6069b33 into this version. Changes from QEMU's latest CoreAudio-related commits (which postdate the classic emulator's version) are preserved. In addition, a few cosmetic changes are made to the imported code for coding style consistency. Change-Id: I09afe2845905e64b96031530844ff219042d3993 Signed-off-by: Yu Ning <yu.ning@intel.com>
-rw-r--r--audio/coreaudio.c655
1 files changed, 450 insertions, 205 deletions
diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index 5964c62eaf..d0de87785b 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -1,6 +1,7 @@
/*
* QEMU OS X CoreAudio audio driver
*
+ * Copyright (c) 2008 The Android Open Source Project
* Copyright (c) 2005 Mike Kronenberg
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -32,27 +33,33 @@
#define AUDIO_CAP "coreaudio"
#include "audio_int.h"
+#if 0
+# define D(...) fprintf(stderr, __VA_ARGS__)
+#else
+# define D(...) ((void)0)
+#endif
+
struct {
- int buffer_frames;
- int nbuffers;
+ int out_buffer_frames;
+ int out_nbuffers;
+ int in_buffer_frames;
+ int in_nbuffers;
int isAtexit;
} conf = {
- .buffer_frames = 512,
- .nbuffers = 4,
+ .out_buffer_frames = 512,
+ .out_nbuffers = 4,
+ .in_buffer_frames = 512,
+ .in_nbuffers = 4,
.isAtexit = 0
};
-typedef struct coreaudioVoiceOut {
- HWVoiceOut hw;
- pthread_mutex_t mutex;
- int isAtexit;
- AudioDeviceID outputDeviceID;
- UInt32 audioDevicePropertyBufferFrameSize;
- AudioStreamBasicDescription outputStreamBasicDescription;
- int live;
- int decr;
- int rpos;
-} coreaudioVoiceOut;
+/***************************************************************************************/
+/***************************************************************************************/
+/*** ***/
+/*** U T I L I T Y R O U T I N E S ***/
+/*** ***/
+/***************************************************************************************/
+/***************************************************************************************/
static void coreaudio_logstatus (OSStatus status)
{
@@ -144,13 +151,33 @@ static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 (
coreaudio_logstatus (status);
}
-static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
+/***************************************************************************************/
+/***************************************************************************************/
+/*** ***/
+/*** S H A R E D I N / O U T V O I C E ***/
+/*** ***/
+/***************************************************************************************/
+/***************************************************************************************/
+
+typedef struct coreAudioVoice {
+ pthread_mutex_t mutex;
+ AudioDeviceID deviceID;
+ Boolean isInput;
+ UInt32 bufferFrameSize;
+ AudioStreamBasicDescription streamBasicDescription;
+ AudioDeviceIOProc ioproc;
+ int live;
+ int decr;
+ int pos;
+} coreaudioVoice;
+
+static inline UInt32 coreaudio_voice_isPlaying (coreaudioVoice *core)
{
OSStatus status;
UInt32 result = 0;
- UInt32 propertySize = sizeof(outputDeviceID);
+ UInt32 propertySize = sizeof(core->deviceID);
status = AudioDeviceGetProperty(
- outputDeviceID, 0, 0,
+ core->deviceID, 0, core->isInput,
kAudioDevicePropertyDeviceIsRunning, &propertySize, &result);
if (status != kAudioHardwareNoError) {
coreaudio_logerr(status,
@@ -164,7 +191,7 @@ static void coreaudio_atexit (void)
conf.isAtexit = 1;
}
-static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
+static int coreaudio_voice_lock (coreaudioVoice *core, const char *fn_name)
{
int err;
@@ -177,7 +204,7 @@ static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
return 0;
}
-static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name)
+static int coreaudio_voice_unlock (coreaudioVoice *core, const char *fn_name)
{
int err;
@@ -190,111 +217,75 @@ static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name)
return 0;
}
-static int coreaudio_run_out (HWVoiceOut *hw, int live)
+static int coreaudio_voice_ctl (coreaudioVoice *core, int cmd)
{
- int decr;
- coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
+ OSStatus status;
- if (coreaudio_lock (core, "coreaudio_run_out")) {
- return 0;
- }
+ switch (cmd) {
+ case VOICE_ENABLE:
+ /* start playback */
+ D("%s: %s started\n", __FUNCTION__, core->isInput ? "input" : "output");
+ if (!coreaudio_voice_isPlaying(core)) {
+ status = AudioDeviceStart(core->deviceID, core->ioproc);
+ if (status != kAudioHardwareNoError) {
+ coreaudio_logerr (status, "Could not resume playback\n");
+ }
+ }
+ break;
- if (core->decr > live) {
- ldebug ("core->decr %d live %d core->live %d\n",
- core->decr,
- live,
- core->live);
+ case VOICE_DISABLE:
+ /* stop playback */
+ D("%s: %s stopped\n", __FUNCTION__, core->isInput ? "input" : "output");
+ if (!conf.isAtexit) {
+ if (coreaudio_voice_isPlaying(core)) {
+ status = AudioDeviceStop(core->deviceID, core->ioproc);
+ if (status != kAudioHardwareNoError) {
+ coreaudio_logerr (status, "Could not pause playback\n");
+ }
+ }
+ }
+ break;
}
-
- decr = audio_MIN (core->decr, live);
- core->decr -= decr;
-
- core->live = live - decr;
- hw->rpos = core->rpos;
-
- coreaudio_unlock (core, "coreaudio_run_out");
- return decr;
+ return 0;
}
-/* callback to feed audiooutput buffer */
-static OSStatus audioDeviceIOProc(
- AudioDeviceID inDevice,
- const AudioTimeStamp* inNow,
- const AudioBufferList* inInputData,
- const AudioTimeStamp* inInputTime,
- AudioBufferList* outOutputData,
- const AudioTimeStamp* inOutputTime,
- void* hwptr)
+static void coreaudio_voice_fini (coreaudioVoice *core)
{
- UInt32 frame, frameCount;
- float *out = outOutputData->mBuffers[0].mData;
- HWVoiceOut *hw = hwptr;
- coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr;
- int rpos, live;
- struct st_sample *src;
-#ifndef FLOAT_MIXENG
-#ifdef RECIPROCAL
- const float scale = 1.f / UINT_MAX;
-#else
- const float scale = UINT_MAX;
-#endif
-#endif
-
- if (coreaudio_lock (core, "audioDeviceIOProc")) {
- inInputTime = 0;
- return 0;
- }
+ OSStatus status;
+ int err;
- frameCount = core->audioDevicePropertyBufferFrameSize;
- live = core->live;
+ if (!conf.isAtexit) {
+ /* stop playback */
+ coreaudio_voice_ctl(core, VOICE_DISABLE);
- /* if there are not enough samples, set signal and return */
- if (live < frameCount) {
- inInputTime = 0;
- coreaudio_unlock (core, "audioDeviceIOProc(empty)");
- return 0;
+ /* remove callback */
+ status = AudioDeviceRemoveIOProc(core->deviceID, core->ioproc);
+ if (status != kAudioHardwareNoError) {
+ coreaudio_logerr (status, "Could not remove IOProc\n");
+ }
}
+ core->deviceID = kAudioDeviceUnknown;
- rpos = core->rpos;
- src = hw->mix_buf + rpos;
-
- /* fill buffer */
- for (frame = 0; frame < frameCount; frame++) {
-#ifdef FLOAT_MIXENG
- *out++ = src[frame].l; /* left channel */
- *out++ = src[frame].r; /* right channel */
-#else
-#ifdef RECIPROCAL
- *out++ = src[frame].l * scale; /* left channel */
- *out++ = src[frame].r * scale; /* right channel */
-#else
- *out++ = src[frame].l / scale; /* left channel */
- *out++ = src[frame].r / scale; /* right channel */
-#endif
-#endif
+ /* destroy mutex */
+ err = pthread_mutex_destroy(&core->mutex);
+ if (err) {
+ dolog("Could not destroy mutex\nReason: %s\n", strerror (err));
}
-
- rpos = (rpos + frameCount) % hw->samples;
- core->decr += frameCount;
- core->rpos = rpos;
-
- coreaudio_unlock (core, "audioDeviceIOProc");
- return 0;
}
-static int coreaudio_write (SWVoiceOut *sw, void *buf, int len)
-{
- return audio_pcm_sw_write (sw, buf, len);
-}
-static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int coreaudio_voice_init (coreaudioVoice *core, struct audsettings *as,
+ int frameSize, AudioDeviceIOProc ioproc,
+ void *hw, int input)
{
- OSStatus status;
- coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
- UInt32 propertySize;
- int err;
- const char *typ = "playback";
+ OSStatus status;
+ UInt32 propertySize;
+ int err;
+ int bits = 8;
AudioValueRange frameRange;
+ const char* typ = input ? "input" : "playback";
+
+ core->isInput = input ? true : false;
/* create mutex */
err = pthread_mutex_init(&core->mutex, NULL);
@@ -303,20 +294,28 @@ static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
return -1;
}
- audio_pcm_init_info (&hw->info, as);
+ if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) {
+ bits = 16;
+ }
+ // TODO: audio_pcm_init_info (&hw->info, as);
/* open default output device */
- propertySize = sizeof(core->outputDeviceID);
+ /* note: we use DefaultSystemOutputDevice because DefaultOutputDevice seems to
+ * always link to the internal speakers, and not the ones selected through system properties
+ * go figure...
+ */
+ propertySize = sizeof(core->deviceID);
status = AudioHardwareGetProperty(
- kAudioHardwarePropertyDefaultOutputDevice,
+ input ? kAudioHardwarePropertyDefaultInputDevice :
+ kAudioHardwarePropertyDefaultSystemOutputDevice,
&propertySize,
- &core->outputDeviceID);
+ &core->deviceID);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ,
- "Could not get default output Device\n");
+ "Could not get default %s device\n", typ);
return -1;
}
- if (core->outputDeviceID == kAudioDeviceUnknown) {
+ if (core->deviceID == kAudioDeviceUnknown) {
dolog ("Could not initialize %s - Unknown Audiodevice\n", typ);
return -1;
}
@@ -324,9 +323,9 @@ static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
/* get minimum and maximum buffer frame sizes */
propertySize = sizeof(frameRange);
status = AudioDeviceGetProperty(
- core->outputDeviceID,
- 0,
+ core->deviceID,
0,
+ core->isInput,
kAudioDevicePropertyBufferFrameSizeRange,
&propertySize,
&frameRange);
@@ -336,100 +335,101 @@ static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
return -1;
}
- if (frameRange.mMinimum > conf.buffer_frames) {
- core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum;
- dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum);
+ if (frameRange.mMinimum > frameSize) {
+ core->bufferFrameSize = (UInt32) frameRange.mMinimum;
+ dolog ("warning: Upsizing Output Buffer Frames to %f\n", frameRange.mMinimum);
}
- else if (frameRange.mMaximum < conf.buffer_frames) {
- core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum;
- dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum);
+ else if (frameRange.mMaximum < frameSize) {
+ core->bufferFrameSize = (UInt32) frameRange.mMaximum;
+ dolog ("warning: Downsizing Output Buffer Frames to %f\n", frameRange.mMaximum);
}
else {
- core->audioDevicePropertyBufferFrameSize = conf.buffer_frames;
+ core->bufferFrameSize = frameSize;
}
/* set Buffer Frame Size */
- propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
+ propertySize = sizeof(core->bufferFrameSize);
status = AudioDeviceSetProperty(
- core->outputDeviceID,
+ core->deviceID,
NULL,
0,
- false,
+ core->isInput,
kAudioDevicePropertyBufferFrameSize,
propertySize,
- &core->audioDevicePropertyBufferFrameSize);
+ &core->bufferFrameSize);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ,
"Could not set device buffer frame size %" PRIu32 "\n",
- (uint32_t)core->audioDevicePropertyBufferFrameSize);
+ (uint32_t)core->bufferFrameSize);
return -1;
}
/* get Buffer Frame Size */
- propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
+ propertySize = sizeof(core->bufferFrameSize);
status = AudioDeviceGetProperty(
- core->outputDeviceID,
+ core->deviceID,
0,
- false,
+ core->isInput,
kAudioDevicePropertyBufferFrameSize,
&propertySize,
- &core->audioDevicePropertyBufferFrameSize);
+ &core->bufferFrameSize);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ,
"Could not get device buffer frame size\n");
return -1;
}
- hw->samples = conf.nbuffers * core->audioDevicePropertyBufferFrameSize;
+ // TODO: hw->samples = *pNBuffers * core->bufferFrameSize;
/* get StreamFormat */
- propertySize = sizeof(core->outputStreamBasicDescription);
+ propertySize = sizeof(core->streamBasicDescription);
status = AudioDeviceGetProperty(
- core->outputDeviceID,
+ core->deviceID,
0,
- false,
+ core->isInput,
kAudioDevicePropertyStreamFormat,
&propertySize,
- &core->outputStreamBasicDescription);
+ &core->streamBasicDescription);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ,
"Could not get Device Stream properties\n");
- core->outputDeviceID = kAudioDeviceUnknown;
+ core->deviceID = kAudioDeviceUnknown;
return -1;
}
/* set Samplerate */
- core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
- propertySize = sizeof(core->outputStreamBasicDescription);
+ core->streamBasicDescription.mSampleRate = (Float64) as->freq;
+ propertySize = sizeof(core->streamBasicDescription);
status = AudioDeviceSetProperty(
- core->outputDeviceID,
- 0,
+ core->deviceID,
0,
0,
+ core->isInput,
kAudioDevicePropertyStreamFormat,
propertySize,
- &core->outputStreamBasicDescription);
+ &core->streamBasicDescription);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n",
as->freq);
- core->outputDeviceID = kAudioDeviceUnknown;
+ core->deviceID = kAudioDeviceUnknown;
return -1;
}
/* set Callback */
- status = AudioDeviceAddIOProc(core->outputDeviceID, audioDeviceIOProc, hw);
+ core->ioproc = ioproc;
+ status = AudioDeviceAddIOProc(core->deviceID, ioproc, hw);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ, "Could not set IOProc\n");
- core->outputDeviceID = kAudioDeviceUnknown;
+ core->deviceID = kAudioDeviceUnknown;
return -1;
}
/* start Playback */
- if (!isPlaying(core->outputDeviceID)) {
- status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
+ if (!input && !coreaudio_voice_isPlaying(core)) {
+ status = AudioDeviceStart(core->deviceID, core->ioproc);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ, "Could not start playback\n");
- AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc);
- core->outputDeviceID = kAudioDeviceUnknown;
+ AudioDeviceRemoveIOProc(core->deviceID, core->ioproc);
+ core->deviceID = kAudioDeviceUnknown;
return -1;
}
}
@@ -437,68 +437,295 @@ static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
return 0;
}
-static void coreaudio_fini_out (HWVoiceOut *hw)
+
+/***************************************************************************************/
+/***************************************************************************************/
+/*** ***/
+/*** O U T P U T V O I C E ***/
+/*** ***/
+/***************************************************************************************/
+/***************************************************************************************/
+
+typedef struct coreaudioVoiceOut {
+ HWVoiceOut hw;
+ coreaudioVoice core[1];
+} coreaudioVoiceOut;
+
+#define CORE_OUT(hw) ((coreaudioVoiceOut*)(hw))->core
+
+
+static int coreaudio_run_out (HWVoiceOut *hw, int live)
{
- OSStatus status;
+ int decr;
+ coreaudioVoice *core = CORE_OUT(hw);
+
+ if (coreaudio_voice_lock (core, "coreaudio_run_out")) {
+ return 0;
+ }
+
+ if (core->decr > live) {
+ ldebug ("core->decr %d live %d core->live %d\n",
+ core->decr,
+ live,
+ core->live);
+ }
+
+ decr = audio_MIN (core->decr, live);
+ core->decr -= decr;
+
+ core->live = live - decr;
+ hw->rpos = core->pos;
+
+ coreaudio_voice_unlock (core, "coreaudio_run_out");
+ return decr;
+}
+
+/* callback to feed audiooutput buffer */
+static OSStatus audioOutDeviceIOProc(
+ AudioDeviceID inDevice,
+ const AudioTimeStamp* inNow,
+ const AudioBufferList* inInputData,
+ const AudioTimeStamp* inInputTime,
+ AudioBufferList* outOutputData,
+ const AudioTimeStamp* inOutputTime,
+ void* hwptr)
+{
+ UInt32 frame, frameCount;
+ float *out = outOutputData->mBuffers[0].mData;
+ HWVoiceOut *hw = hwptr;
+ coreaudioVoice *core = CORE_OUT(hw);
+ int rpos, live;
+ struct st_sample *src;
+#ifndef FLOAT_MIXENG
+#ifdef RECIPROCAL
+ const float scale = 1.f / UINT_MAX;
+#else
+ const float scale = UINT_MAX;
+#endif
+#endif
+
+ if (coreaudio_voice_lock (core, "audioDeviceIOProc")) {
+ inInputTime = 0;
+ return 0;
+ }
+
+ frameCount = core->bufferFrameSize;
+ live = core->live;
+
+ /* if there are not enough samples, set signal and return */
+ if (live < (int)frameCount) {
+ inInputTime = 0;
+ coreaudio_voice_unlock (core, "audioDeviceIOProc(empty)");
+ return 0;
+ }
+
+ rpos = core->pos;
+ src = hw->mix_buf + rpos;
+
+ /* fill buffer */
+ for (frame = 0; frame < frameCount; frame++) {
+#ifdef FLOAT_MIXENG
+ *out++ = src[frame].l; /* left channel */
+ *out++ = src[frame].r; /* right channel */
+#else
+#ifdef RECIPROCAL
+ *out++ = src[frame].l * scale; /* left channel */
+ *out++ = src[frame].r * scale; /* right channel */
+#else
+ *out++ = src[frame].l / scale; /* left channel */
+ *out++ = src[frame].r / scale; /* right channel */
+#endif
+#endif
+ }
+
+ rpos = (rpos + frameCount) % hw->samples;
+ core->decr += frameCount;
+ core->pos = rpos;
+
+ coreaudio_voice_unlock (core, "audioDeviceIOProc");
+ return 0;
+}
+
+static int coreaudio_write (SWVoiceOut *sw, void *buf, int len)
+{
+ return audio_pcm_sw_write (sw, buf, len);
+}
+
+static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
+{
+ coreaudioVoice *core = CORE_OUT(hw);
int err;
- coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
- if (!conf.isAtexit) {
- /* stop playback */
- if (isPlaying(core->outputDeviceID)) {
- status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
- if (status != kAudioHardwareNoError) {
- coreaudio_logerr (status, "Could not stop playback\n");
- }
- }
+ audio_pcm_init_info (&hw->info, as);
- /* remove callback */
- status = AudioDeviceRemoveIOProc(core->outputDeviceID,
- audioDeviceIOProc);
- if (status != kAudioHardwareNoError) {
- coreaudio_logerr (status, "Could not remove IOProc\n");
- }
+ err = coreaudio_voice_init (core, as, conf.out_buffer_frames, audioOutDeviceIOProc, hw, 0);
+ if (err < 0)
+ return err;
+
+ hw->samples = core->bufferFrameSize * conf.out_nbuffers;
+ return 0;
+}
+
+static void coreaudio_fini_out (HWVoiceOut *hw)
+{
+ coreaudioVoice *core = CORE_OUT(hw);
+
+ coreaudio_voice_fini (core);
+}
+
+static int
+coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
+{
+ coreaudioVoice *core = CORE_OUT(hw);
+
+ return coreaudio_voice_ctl (core, cmd);
+}
+
+/***************************************************************************************/
+/***************************************************************************************/
+/*** ***/
+/*** I N P U T V O I C E ***/
+/*** ***/
+/***************************************************************************************/
+/***************************************************************************************/
+
+
+
+typedef struct coreaudioVoiceIn {
+ HWVoiceIn hw;
+ coreaudioVoice core[1];
+} coreaudioVoiceIn;
+
+#define CORE_IN(hw) ((coreaudioVoiceIn *) (hw))->core
+
+
+static int coreaudio_run_in (HWVoiceIn *hw)
+{
+ int decr;
+
+ coreaudioVoice *core = CORE_IN(hw);
+
+ if (coreaudio_voice_lock (core, "coreaudio_run_in")) {
+ return 0;
}
- core->outputDeviceID = kAudioDeviceUnknown;
+ D("%s: core.decr=%d core.pos=%d\n", __FUNCTION__, core->decr, core->pos);
+ decr = core->decr;
+ core->decr -= decr;
+ hw->wpos = core->pos;
- /* destroy mutex */
- err = pthread_mutex_destroy(&core->mutex);
- if (err) {
- dolog("Could not destroy mutex\nReason: %s\n", strerror (err));
+ coreaudio_voice_unlock (core, "coreaudio_run_in");
+ return decr;
+}
+
+
+/* callback to feed audiooutput buffer */
+static OSStatus audioInDeviceIOProc(
+ AudioDeviceID inDevice,
+ const AudioTimeStamp* inNow,
+ const AudioBufferList* inInputData,
+ const AudioTimeStamp* inInputTime,
+ AudioBufferList* outOutputData,
+ const AudioTimeStamp* inOutputTime,
+ void* hwptr)
+{
+ UInt32 frame, frameCount;
+ float *in = inInputData->mBuffers[0].mData;
+ HWVoiceIn *hw = hwptr;
+ coreaudioVoice *core = CORE_IN(hw);
+ int wpos, avail;
+ struct st_sample *dst;
+#ifndef FLOAT_MIXENG
+#ifdef RECIPROCAL
+ const float scale = 1.f / UINT_MAX;
+#else
+ const float scale = UINT_MAX;
+#endif
+#endif
+
+ if (coreaudio_voice_lock (core, "audioDeviceIOProc")) {
+ inInputTime = 0;
+ return 0;
}
+
+ frameCount = core->bufferFrameSize;
+ avail = hw->samples - hw->total_samples_captured - core->decr;
+
+ D("%s: enter avail=%d core.decr=%d core.pos=%d hw.samples=%d hw.total_samples_captured=%d frameCount=%d\n",
+ __FUNCTION__, avail, core->decr, core->pos, hw->samples, hw->total_samples_captured, (int)frameCount);
+
+ /* if there are not enough samples, set signal and return */
+ if (avail < (int)frameCount) {
+ inInputTime = 0;
+ coreaudio_voice_unlock (core, "audioDeviceIOProc(empty)");
+ return 0;
+ }
+
+ wpos = core->pos;
+ dst = hw->conv_buf + wpos;
+
+ /* fill buffer */
+ for (frame = 0; frame < frameCount; frame++) {
+#ifdef FLOAT_MIXENG
+ dst[frame].l = *in++; /* left channel */
+ dst[frame].r = *in++; /* right channel */
+#else
+#ifdef RECIPROCAL
+ dst[frame].l = *in++ * scale; /* left channel */
+ dst[frame].r = *in++ * scale; /* right channel */
+#else
+ dst[frame].l = *in++ / scale; /* left channel */
+ dst[frame].r = *in++ / scale; /* right channel */
+#endif
+#endif
+ }
+
+ wpos = (wpos + frameCount) % hw->samples;
+ core->decr += frameCount;
+ core->pos = wpos;
+
+ D("exit: core.decr=%d core.pos=%d\n", core->decr, core->pos);
+ coreaudio_voice_unlock (core, "audioDeviceIOProc");
+ return 0;
}
-static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
+static int coreaudio_read (SWVoiceIn *sw, void *buf, int len)
{
- OSStatus status;
- coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
+ int result = audio_pcm_sw_read (sw, buf, len);
+ D("%s: audio_pcm_sw_read(%d) returned %d\n", __FUNCTION__, len, result);
+ return result;
+}
- switch (cmd) {
- case VOICE_ENABLE:
- /* start playback */
- if (!isPlaying(core->outputDeviceID)) {
- status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
- if (status != kAudioHardwareNoError) {
- coreaudio_logerr (status, "Could not resume playback\n");
- }
- }
- break;
+static int coreaudio_init_in (HWVoiceIn *hw, struct audsettings *as)
+{
+ coreaudioVoice* core = CORE_IN(hw);
+ int err;
- case VOICE_DISABLE:
- /* stop playback */
- if (!conf.isAtexit) {
- if (isPlaying(core->outputDeviceID)) {
- status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
- if (status != kAudioHardwareNoError) {
- coreaudio_logerr (status, "Could not pause playback\n");
- }
- }
- }
- break;
+ audio_pcm_init_info (&hw->info, as);
+
+ err = coreaudio_voice_init (core, as, conf.in_buffer_frames, audioInDeviceIOProc, hw, 1);
+ if (err < 0) {
+ return err;
}
+
+ hw->samples = core->bufferFrameSize * conf.in_nbuffers;
return 0;
}
+static void coreaudio_fini_in (HWVoiceIn *hw)
+{
+
+ coreaudioVoice* core = CORE_IN(hw);
+
+ coreaudio_voice_fini(core);
+}
+
+static int coreaudio_ctl_in (HWVoiceIn *hw, int cmd, ...)
+{
+ coreaudioVoice* core = CORE_IN(hw);
+
+ return coreaudio_voice_ctl(core, cmd);
+}
+
static void *coreaudio_audio_init (void)
{
atexit(coreaudio_atexit);
@@ -512,16 +739,28 @@ static void coreaudio_audio_fini (void *opaque)
static struct audio_option coreaudio_options[] = {
{
- .name = "BUFFER_SIZE",
+ .name = "OUT_BUFFER_SIZE",
+ .tag = AUD_OPT_INT,
+ .valp = &conf.out_buffer_frames,
+ .descr = "Size of the output buffer in frames"
+ },
+ {
+ .name = "OUT_BUFFER_COUNT",
.tag = AUD_OPT_INT,
- .valp = &conf.buffer_frames,
- .descr = "Size of the buffer in frames"
+ .valp = &conf.out_nbuffers,
+ .descr = "Number of output buffers"
},
{
- .name = "BUFFER_COUNT",
+ .name = "IN_BUFFER_SIZE",
.tag = AUD_OPT_INT,
- .valp = &conf.nbuffers,
- .descr = "Number of buffers"
+ .valp = &conf.in_buffer_frames,
+ .descr = "Size of the input buffer in frames"
+ },
+ {
+ .name = "IN_BUFFER_COUNT",
+ .tag = AUD_OPT_INT,
+ .valp = &conf.in_nbuffers,
+ .descr = "Number of input buffers"
},
{ /* End of list */ }
};
@@ -531,7 +770,13 @@ static struct audio_pcm_ops coreaudio_pcm_ops = {
.fini_out = coreaudio_fini_out,
.run_out = coreaudio_run_out,
.write = coreaudio_write,
- .ctl_out = coreaudio_ctl_out
+ .ctl_out = coreaudio_ctl_out,
+
+ .init_in = coreaudio_init_in,
+ .fini_in = coreaudio_fini_in,
+ .run_in = coreaudio_run_in,
+ .read = coreaudio_read,
+ .ctl_in = coreaudio_ctl_in
};
struct audio_driver coreaudio_audio_driver = {
@@ -543,7 +788,7 @@ struct audio_driver coreaudio_audio_driver = {
.pcm_ops = &coreaudio_pcm_ops,
.can_be_default = 1,
.max_voices_out = 1,
- .max_voices_in = 0,
+ .max_voices_in = 1,
.voice_size_out = sizeof (coreaudioVoiceOut),
- .voice_size_in = 0
+ .voice_size_in = sizeof (coreaudioVoiceIn),
};