/*
* 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
#include "audio_int.h"
#ifdef CONFIG_MARU
-// FIXME: W/A for avoid guest block waiting for audio in
-// TODO: Implements audio in using CoreAudio
-#include "qemu-timer.h"
+#include "../tizen/src/debug_ch.h"
#endif
struct {
- int buffer_frames;
- int nbuffers;
+ int o_buffer_frames;
+ int o_nbuffers;
+ int i_buffer_frames;
+ int i_nbuffers;
int isAtexit;
} conf = {
- .buffer_frames = 512,
- .nbuffers = 4,
+ .o_buffer_frames = 512,
+ .o_nbuffers = 4,
+ .i_buffer_frames = 512,
+ .i_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;
-
-#ifdef CONFIG_MARU
-typedef struct NoVoiceIn {
- HWVoiceIn hw;
- int64_t old_ticks;
-} NoVoiceIn;
-#endif
-
static void coreaudio_logstatus (OSStatus status)
{
const char *str = "BUG";
coreaudio_logstatus (status);
}
-static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
+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,
conf.isAtexit = 1;
}
-static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
+static int coreaudio_lock (coreaudioVoice *core, const char *fn_name)
{
int err;
return 0;
}
-static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name)
+static int coreaudio_unlock (coreaudioVoice *core, const char *fn_name)
{
int err;
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 */
+ printf("%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 */
+ printf("%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);
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;
}
/* get minimum and maximum buffer frame sizes */
propertySize = sizeof(frameRange);
status = AudioDeviceGetProperty(
- core->outputDeviceID,
- 0,
+ core->deviceID,
0,
+ core->isInput,
kAudioDevicePropertyBufferFrameSizeRange,
&propertySize,
&frameRange);
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);
+ "Could not set device buffer frame size %ld\n",
+ 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;
}
}
return 0;
}
-static void coreaudio_fini_out (HWVoiceOut *hw)
-{
- OSStatus status;
- int err;
- coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
+typedef struct coreaudioVoiceOut {
+ HWVoiceOut hw;
+ coreaudioVoice core[1];
+} coreaudioVoiceOut;
- 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");
- }
- }
+#define CORE_OUT(hw) ((coreaudioVoiceOut*)(hw))->core
- /* remove callback */
- status = AudioDeviceRemoveIOProc(core->outputDeviceID,
- audioDeviceIOProc);
- if (status != kAudioHardwareNoError) {
- coreaudio_logerr (status, "Could not remove IOProc\n");
- }
+
+static int coreaudio_run_out (HWVoiceOut *hw, int live)
+{
+ int decr;
+ coreaudioVoice *core = CORE_OUT(hw);
+
+ if (coreaudio_lock (core, "coreaudio_run_out")) {
+ return 0;
}
- core->outputDeviceID = kAudioDeviceUnknown;
- /* destroy mutex */
- err = pthread_mutex_destroy(&core->mutex);
- if (err) {
- dolog("Could not destroy mutex\nReason: %s\n", strerror (err));
+ 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_unlock (core, "coreaudio_run_out");
+ return decr;
}
-static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
+/* 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)
{
- OSStatus status;
- coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
+ 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
- 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;
+ if (coreaudio_lock (core, "audioDeviceIOProc")) {
+ inInputTime = 0;
+ return 0;
+ }
- 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;
+ frameCount = core->bufferFrameSize;
+ live = core->live;
+
+ /* if there are not enough samples, set signal and return */
+ if (live < frameCount) {
+ inInputTime = 0;
+ coreaudio_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_unlock (core, "audioDeviceIOProc");
return 0;
}
-static void *coreaudio_audio_init (void)
+static int coreaudio_write (SWVoiceOut *sw, void *buf, int len)
{
- atexit(coreaudio_atexit);
- return &coreaudio_audio_init;
+ return audio_pcm_sw_write (sw, buf, len);
}
-static void coreaudio_audio_fini (void *opaque)
+static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
{
- (void) opaque;
+ coreaudioVoice* core = CORE_OUT(hw);
+ int err;
+
+ audio_pcm_init_info (&hw->info, as);
+
+ err = coreaudio_voice_init (core, as, conf.o_buffer_frames, audioOutDeviceIOProc, hw, 0);
+ if (err < 0)
+ return err;
+
+ hw->samples = core->bufferFrameSize * conf.o_nbuffers;
+ return 0;
}
-static struct audio_option coreaudio_options[] = {
- {
- .name = "BUFFER_SIZE",
- .tag = AUD_OPT_INT,
- .valp = &conf.buffer_frames,
- .descr = "Size of the buffer in frames"
- },
- {
- .name = "BUFFER_COUNT",
- .tag = AUD_OPT_INT,
- .valp = &conf.nbuffers,
- .descr = "Number of buffers"
- },
- { /* End of list */ }
-};
+static void coreaudio_fini_out (HWVoiceOut *hw)
+{
+ coreaudioVoice *core = CORE_OUT(hw);
-#ifdef CONFIG_MARU
-static int no_init_in (HWVoiceIn *hw, struct audsettings *as)
+ coreaudio_voice_fini (core);
+}
+
+static int
+coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
{
- audio_pcm_init_info (&hw->info, as);
- hw->samples = 1024;
- return 0;
+ coreaudioVoice *core = CORE_OUT(hw);
+
+ return coreaudio_voice_ctl (core, cmd);
}
-static void no_fini_in (HWVoiceIn *hw)
+//
+// Enable coreaudio audio-in
+//
+
+typedef struct coreaudioVoiceIn {
+ HWVoiceIn hw;
+ coreaudioVoice core[1];
+} coreaudioVoiceIn;
+
+#define CORE_IN(hw) ((coreaudioVoiceIn *) (hw))->core
+
+
+static int coreaudio_run_in (HWVoiceIn *hw, int live)
{
- (void) hw;
+ int decr;
+
+ coreaudioVoice *core = CORE_IN(hw);
+
+ if (coreaudio_lock (core, "coreaudio_run_in")) {
+ return 0;
+ }
+ printf("%s: core.decr=%d core.pos=%d\n", __FUNCTION__, core->decr, core->pos);
+ decr = core->decr;
+ core->decr -= decr;
+ hw->wpos = core->pos;
+
+ coreaudio_unlock (core, "coreaudio_run_in");
+ return decr;
}
-static int no_run_in (HWVoiceIn *hw)
+
+/* 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)
{
- NoVoiceIn *no = (NoVoiceIn *) hw;
- int live = audio_pcm_hw_get_live_in (hw);
- int dead = hw->samples - live;
- int samples = 0;
-
- if (dead) {
- int64_t now = qemu_get_clock_ns (vm_clock);
- int64_t ticks = now - no->old_ticks;
- int64_t bytes =
- muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
-
- no->old_ticks = now;
- bytes = audio_MIN (bytes, INT_MAX);
- samples = bytes >> hw->info.shift;
- samples = audio_MIN (samples, dead);
+ 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_lock (core, "audioDeviceIOProc")) {
+ inInputTime = 0;
+ return 0;
+ }
+
+ frameCount = core->bufferFrameSize;
+ avail = hw->samples - hw->total_samples_captured - core->decr;
+
+ printf("%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 < frameCount) {
+ inInputTime = 0;
+ coreaudio_unlock (core, "audioDeviceIOProc(empty)");
+ return 0;
}
- return samples;
+
+ 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;
+
+ printf("exit: core.decr=%d core.pos=%d\n", core->decr, core->pos);
+ coreaudio_unlock (core, "audioDeviceIOProc");
+ return 0;
}
-static int no_read (SWVoiceIn *sw, void *buf, int size)
+static int
+coreaudio_read (SWVoiceIn *sw, void *buf, int len)
{
- /* use custom code here instead of audio_pcm_sw_read() to avoid
- * useless resampling/mixing */
- int samples = size >> sw->info.shift;
- int total = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
- int to_clear = audio_MIN (samples, total);
- sw->total_hw_samples_acquired += total;
- audio_pcm_info_clear_buf (&sw->info, buf, to_clear);
- return to_clear << sw->info.shift;
+ int result = audio_pcm_sw_read (sw, buf, len);
+ printf("%s: audio_pcm_sw_read(%d) returned %d\n", __FUNCTION__, len, result);
+ return result;
}
-static int no_ctl_in (HWVoiceIn *hw, int cmd, ...)
+static int
+coreaudio_init_in (HWVoiceIn *hw, struct audsettings *as)
{
- (void) hw;
- (void) cmd;
+ coreaudioVoice* core = CORE_IN(hw);
+ int err;
+
+ audio_pcm_init_info (&hw->info, as);
+
+ err = coreaudio_voice_init (core, as, conf.i_buffer_frames, audioInDeviceIOProc, hw, 1);
+ if (err < 0) {
+ return err;
+ }
+
+ hw->samples = core->bufferFrameSize * conf.i_nbuffers;
return 0;
}
-#endif
+
+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);
+ return &coreaudio_audio_init;
+}
+
+static void coreaudio_audio_fini (void *opaque)
+{
+ (void) opaque;
+}
+
+static struct audio_option coreaudio_options[] = {
+ {
+ .name = "O_BUFFER_SIZE",
+ .tag = AUD_OPT_INT,
+ .valp = &conf.o_buffer_frames,
+ .descr = "Size of the output buffer in frames"
+ },
+ {
+ .name = "O_BUFFER_COUNT",
+ .tag = AUD_OPT_INT,
+ .valp = &conf.o_nbuffers,
+ .descr = "Number of output buffers"
+ },
+ {
+ .name = "I_BUFFER_SIZE",
+ .tag = AUD_OPT_INT,
+ .valp = &conf.i_buffer_frames,
+ .descr = "Size of the input buffer in frames"
+ },
+ {
+ .name = "I_BUFFER_COUNT",
+ .tag = AUD_OPT_INT,
+ .valp = &conf.i_nbuffers,
+ .descr = "Number of input buffers"
+ },
+ { /* End of list */ }
+};
static struct audio_pcm_ops coreaudio_pcm_ops = {
-#ifndef CONFIG_MARU
- .init_out = coreaudio_init_out,
- .fini_out = coreaudio_fini_out,
- .run_out = coreaudio_run_out,
- .write = coreaudio_write,
- .ctl_out = coreaudio_ctl_out
-#else
.init_out = coreaudio_init_out,
.fini_out = coreaudio_fini_out,
.run_out = coreaudio_run_out,
.write = coreaudio_write,
.ctl_out = coreaudio_ctl_out,
- .init_in = no_init_in,
- .fini_in = no_fini_in,
- .run_in = no_run_in,
- .read = no_read,
- .ctl_in = no_ctl_in
-#endif
+ .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 = {
.pcm_ops = &coreaudio_pcm_ops,
.can_be_default = 1,
.max_voices_out = 1,
-#ifdef CONFIG_MARU
- .max_voices_in = 1,
-#else
- .max_voices_in = 0,
-#endif
+ .max_voices_in = 1, // enable auido-in
.voice_size_out = sizeof (coreaudioVoiceOut),
-#ifdef CONFIG_MARU
- .voice_size_in = sizeof (NoVoiceIn)
-#else
- .voice_size_in = 0
-#endif
+ .voice_size_in = sizeof (coreaudioVoiceIn),
};