From: Seokyeon Hwang Date: Wed, 17 Aug 2016 08:56:23 +0000 (+0900) Subject: coreaudio: implement audio-in X-Git-Tag: Tizen_Studio_1.3_Release_p2.3.2~29^2~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=04e0802659d4722f6c9639f9c8bdd779d8c9dddb;p=sdk%2Femulator%2Fqemu.git coreaudio: implement audio-in Change-Id: I7b7c91d24444b7e772846b0a0c64fcf677cad74d Signed-off-by: Seokyeon Hwang --- diff --git a/audio/coreaudio.c b/audio/coreaudio.c index d4ad224590..d9c43fb685 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -22,6 +22,16 @@ * THE SOFTWARE. */ +/* + * Implemented audio-in + * + * Contributors: + * - S-Core Co., Ltd + * + * Contact: + * SeokYeon Hwang + */ + #include "qemu/osdep.h" #include #include /* pthread_X */ @@ -43,26 +53,35 @@ typedef struct { int nbuffers; } CoreaudioConf; -typedef struct coreaudioVoiceOut { - HWVoiceOut hw; +typedef struct coreaudioVoice { pthread_mutex_t mutex; - AudioDeviceID outputDeviceID; + AudioDeviceID deviceID; UInt32 audioDevicePropertyBufferFrameSize; - AudioStreamBasicDescription outputStreamBasicDescription; + AudioStreamBasicDescription description; AudioDeviceIOProcID ioprocid; int live; int decr; - int rpos; + int pos; +} coreaudioVoice; + +typedef struct coreaudioVoiceOut { + HWVoiceOut hw; + coreaudioVoice core[1]; } coreaudioVoiceOut; +typedef struct coreaudioVoiceIn { + HWVoiceIn hw; + coreaudioVoice core[1]; +} coreaudioVoiceIn; + #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 /* The APIs used here only become available from 10.6 */ -static OSStatus coreaudio_get_voice(AudioDeviceID *id) +static OSStatus coreaudio_get_voice(AudioDeviceID *id, bool isInput) { UInt32 size = sizeof(*id); AudioObjectPropertyAddress addr = { - kAudioHardwarePropertyDefaultOutputDevice, + isInput ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; @@ -76,12 +95,12 @@ static OSStatus coreaudio_get_voice(AudioDeviceID *id) } static OSStatus coreaudio_get_framesizerange(AudioDeviceID id, - AudioValueRange *framerange) + AudioValueRange *framerange, bool isInput) { UInt32 size = sizeof(*framerange); AudioObjectPropertyAddress addr = { kAudioDevicePropertyBufferFrameSizeRange, - kAudioDevicePropertyScopeOutput, + isInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster }; @@ -93,12 +112,12 @@ static OSStatus coreaudio_get_framesizerange(AudioDeviceID id, framerange); } -static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize) +static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize, bool isInput) { UInt32 size = sizeof(*framesize); AudioObjectPropertyAddress addr = { kAudioDevicePropertyBufferFrameSize, - kAudioDevicePropertyScopeOutput, + isInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster }; @@ -110,12 +129,12 @@ static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize) framesize); } -static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize) +static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize, bool isInput) { UInt32 size = sizeof(*framesize); AudioObjectPropertyAddress addr = { kAudioDevicePropertyBufferFrameSize, - kAudioDevicePropertyScopeOutput, + isInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster }; @@ -128,12 +147,12 @@ static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize) } static OSStatus coreaudio_get_streamformat(AudioDeviceID id, - AudioStreamBasicDescription *d) + AudioStreamBasicDescription *d, bool isInput) { UInt32 size = sizeof(*d); AudioObjectPropertyAddress addr = { kAudioDevicePropertyStreamFormat, - kAudioDevicePropertyScopeOutput, + isInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster }; @@ -146,12 +165,12 @@ static OSStatus coreaudio_get_streamformat(AudioDeviceID id, } static OSStatus coreaudio_set_streamformat(AudioDeviceID id, - AudioStreamBasicDescription *d) + AudioStreamBasicDescription *d, bool isInput) { UInt32 size = sizeof(*d); AudioObjectPropertyAddress addr = { kAudioDevicePropertyStreamFormat, - kAudioDevicePropertyScopeOutput, + isInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster }; @@ -182,44 +201,44 @@ static OSStatus coreaudio_get_isrunning(AudioDeviceID id, UInt32 *result) #else /* Legacy versions of functions using deprecated APIs */ -static OSStatus coreaudio_get_voice(AudioDeviceID *id) +static OSStatus coreaudio_get_voice(AudioDeviceID *id, bool isInput) { UInt32 size = sizeof(*id); return AudioHardwareGetProperty( - kAudioHardwarePropertyDefaultOutputDevice, + isInput ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice, &size, id); } static OSStatus coreaudio_get_framesizerange(AudioDeviceID id, - AudioValueRange *framerange) + AudioValueRange *framerange, bool isInput) { UInt32 size = sizeof(*framerange); return AudioDeviceGetProperty( id, 0, - 0, + isInput, kAudioDevicePropertyBufferFrameSizeRange, &size, framerange); } -static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize) +static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize, bool isInput) { UInt32 size = sizeof(*framesize); return AudioDeviceGetProperty( id, 0, - false, + isInput, kAudioDevicePropertyBufferFrameSize, &size, framesize); } -static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize) +static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize, bool isInput) { UInt32 size = sizeof(*framesize); @@ -227,28 +246,28 @@ static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize) id, NULL, 0, - false, + isInput, kAudioDevicePropertyBufferFrameSize, size, framesize); } static OSStatus coreaudio_get_streamformat(AudioDeviceID id, - AudioStreamBasicDescription *d) + AudioStreamBasicDescription *d, bool isInput) { UInt32 size = sizeof(*d); return AudioDeviceGetProperty( id, 0, - false, + isInput, kAudioDevicePropertyStreamFormat, &size, d); } static OSStatus coreaudio_set_streamformat(AudioDeviceID id, - AudioStreamBasicDescription *d) + AudioStreamBasicDescription *d, bool isInput) { UInt32 size = sizeof(*d); @@ -256,7 +275,7 @@ static OSStatus coreaudio_set_streamformat(AudioDeviceID id, id, 0, 0, - 0, + isInput, kAudioDevicePropertyStreamFormat, size, d); @@ -366,11 +385,11 @@ static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 ( coreaudio_logstatus (status); } -static inline UInt32 isPlaying (AudioDeviceID outputDeviceID) +static inline UInt32 isPlaying (AudioDeviceID deviceID) { OSStatus status; UInt32 result = 0; - status = coreaudio_get_isrunning(outputDeviceID, &result); + status = coreaudio_get_isrunning(deviceID, &result); if (status != kAudioHardwareNoError) { coreaudio_logerr(status, "Could not determine whether Device is playing\n"); @@ -383,7 +402,7 @@ static void coreaudio_atexit (void) isAtexit = 1; } -static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name) +static int coreaudio_lock (coreaudioVoice *core, const char *fn_name) { int err; @@ -396,7 +415,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_unlock (coreaudioVoice *core, const char *fn_name) { int err; @@ -409,112 +428,13 @@ static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name) return 0; } -static int coreaudio_run_out (HWVoiceOut *hw, int live) -{ - int decr; - coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; - - if (coreaudio_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->rpos; - - coreaudio_unlock (core, "coreaudio_run_out"); - return decr; -} - -/* 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) -{ - 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; - } - - frameCount = core->audioDevicePropertyBufferFrameSize; - 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->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 - } - - 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, - void *drv_opaque) +static int coreaudio_init_voice (coreaudioVoice *core, void *hw, struct audsettings *as, + CoreaudioConf *conf, AudioDeviceIOProc inProc, bool isInput) { OSStatus status; - coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; int err; - const char *typ = "playback"; + const char *typ = isInput ? "capture" : "playback"; AudioValueRange frameRange; - CoreaudioConf *conf = drv_opaque; /* create mutex */ err = pthread_mutex_init(&core->mutex, NULL); @@ -523,22 +443,20 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, return -1; } - audio_pcm_init_info (&hw->info, as); - - status = coreaudio_get_voice(&core->outputDeviceID); + status = coreaudio_get_voice(&core->deviceID, isInput); if (status != kAudioHardwareNoError) { coreaudio_logerr2 (status, typ, - "Could not get default output Device\n"); + "Could not get default device\n"); 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 */ - status = coreaudio_get_framesizerange(core->outputDeviceID, - &frameRange); + status = coreaudio_get_framesizerange(core->deviceID, + &frameRange, isInput); if (status != kAudioHardwareNoError) { coreaudio_logerr2 (status, typ, "Could not get device buffer frame range\n"); @@ -558,8 +476,8 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, } /* set Buffer Frame Size */ - status = coreaudio_set_framesize(core->outputDeviceID, - &core->audioDevicePropertyBufferFrameSize); + status = coreaudio_set_framesize(core->deviceID, + &core->audioDevicePropertyBufferFrameSize, isInput); if (status != kAudioHardwareNoError) { coreaudio_logerr2 (status, typ, "Could not set device buffer frame size %" PRIu32 "\n", @@ -568,55 +486,54 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, } /* get Buffer Frame Size */ - status = coreaudio_get_framesize(core->outputDeviceID, - &core->audioDevicePropertyBufferFrameSize); + status = coreaudio_get_framesize(core->deviceID, + &core->audioDevicePropertyBufferFrameSize, isInput); if (status != kAudioHardwareNoError) { coreaudio_logerr2 (status, typ, "Could not get device buffer frame size\n"); return -1; } - hw->samples = conf->nbuffers * core->audioDevicePropertyBufferFrameSize; /* get StreamFormat */ - status = coreaudio_get_streamformat(core->outputDeviceID, - &core->outputStreamBasicDescription); + status = coreaudio_get_streamformat(core->deviceID, + &core->description, isInput); 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; - status = coreaudio_set_streamformat(core->outputDeviceID, - &core->outputStreamBasicDescription); + core->description.mSampleRate = (Float64) as->freq; + status = coreaudio_set_streamformat(core->deviceID, + &core->description, isInput); 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 */ core->ioprocid = NULL; - status = AudioDeviceCreateIOProcID(core->outputDeviceID, - audioDeviceIOProc, + status = AudioDeviceCreateIOProcID(core->deviceID, + inProc, hw, &core->ioprocid); if (status != kAudioHardwareNoError || core->ioprocid == NULL) { 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, core->ioprocid); + /* start Playback/Capture */ + if (!isPlaying(core->deviceID)) { + status = AudioDeviceStart(core->deviceID, core->ioprocid); if (status != kAudioHardwareNoError) { - coreaudio_logerr2 (status, typ, "Could not start playback\n"); - AudioDeviceDestroyIOProcID(core->outputDeviceID, core->ioprocid); - core->outputDeviceID = kAudioDeviceUnknown; + coreaudio_logerr2 (status, typ, "Could not start %s\n", typ); + AudioDeviceDestroyIOProcID(core->deviceID, core->ioprocid); + core->deviceID = kAudioDeviceUnknown; return -1; } } @@ -624,29 +541,29 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, return 0; } -static void coreaudio_fini_out (HWVoiceOut *hw) +static void coreaudio_fini_voice (coreaudioVoice *core, bool isInput) { OSStatus status; + const char *typ = isInput ? "capture" : "playback"; int err; - coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; if (!isAtexit) { - /* stop playback */ - if (isPlaying(core->outputDeviceID)) { - status = AudioDeviceStop(core->outputDeviceID, core->ioprocid); + /* stop playback/capture */ + if (isPlaying(core->deviceID)) { + status = AudioDeviceStop(core->deviceID, core->ioprocid); if (status != kAudioHardwareNoError) { - coreaudio_logerr (status, "Could not stop playback\n"); + coreaudio_logerr (status, "Could not stop %s\n", typ); } } - /* remove callback */ - status = AudioDeviceDestroyIOProcID(core->outputDeviceID, + /* remove callback/capture */ + status = AudioDeviceDestroyIOProcID(core->deviceID, core->ioprocid); if (status != kAudioHardwareNoError) { coreaudio_logerr (status, "Could not remove IOProc\n"); } } - core->outputDeviceID = kAudioDeviceUnknown; + core->deviceID = kAudioDeviceUnknown; /* destroy mutex */ err = pthread_mutex_destroy(&core->mutex); @@ -655,30 +572,30 @@ static void coreaudio_fini_out (HWVoiceOut *hw) } } -static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) +static int coreaudio_ctl_voice (coreaudioVoice *core, int cmd, bool isInput) { OSStatus status; - coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; + const char *typ = isInput ? "capture" : "playback"; switch (cmd) { case VOICE_ENABLE: - /* start playback */ - if (!isPlaying(core->outputDeviceID)) { - status = AudioDeviceStart(core->outputDeviceID, core->ioprocid); + /* start playback/capture */ + if (!isPlaying(core->deviceID)) { + status = AudioDeviceStart(core->deviceID, core->ioprocid); if (status != kAudioHardwareNoError) { - coreaudio_logerr (status, "Could not resume playback\n"); + coreaudio_logerr (status, "Could not resume %s\n", typ); } } break; case VOICE_DISABLE: - /* stop playback */ + /* stop playback/capture */ if (!isAtexit) { - if (isPlaying(core->outputDeviceID)) { - status = AudioDeviceStop(core->outputDeviceID, + if (isPlaying(core->deviceID)) { + status = AudioDeviceStop(core->deviceID, core->ioprocid); if (status != kAudioHardwareNoError) { - coreaudio_logerr (status, "Could not pause playback\n"); + coreaudio_logerr (status, "Could not pause %s\n", typ); } } } @@ -687,6 +604,252 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) return 0; } +static int coreaudio_run_out (HWVoiceOut *hw, int live) +{ + int decr; + coreaudioVoice *core = ((coreaudioVoiceOut *) hw)->core; + + if (coreaudio_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_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 = ((coreaudioVoiceOut *) hw)->core; + 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; + } + + frameCount = core->audioDevicePropertyBufferFrameSize; + 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 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, + void *drv_opaque) +{ + coreaudioVoice *core = ((coreaudioVoiceOut *) hw)->core; + CoreaudioConf *conf = drv_opaque; + + if (coreaudio_init_voice(core, hw, as, conf, audioOutDeviceIOProc, false) < 0) { + return -1; + } + + audio_pcm_init_info (&hw->info, as); + hw->samples = conf->nbuffers * core->audioDevicePropertyBufferFrameSize; + + return 0; +} + +static void coreaudio_fini_out (HWVoiceOut *hw) +{ + coreaudioVoice *core = ((coreaudioVoiceOut *) hw)->core; + + coreaudio_fini_voice(core, false); +} + +static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) +{ + coreaudioVoice *core = ((coreaudioVoiceOut *) hw)->core; + + return coreaudio_ctl_voice (core, cmd, false); +} + +static int coreaudio_run_in (HWVoiceIn *hw) +{ + int decr; + coreaudioVoice *core = ((coreaudioVoiceIn *) hw)->core; + + if (coreaudio_lock (core, "coreaudio_run_in")) { + return 0; + } + + decr = core->decr; + core->decr -= decr; + hw->wpos = core->pos; + + coreaudio_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 = ((coreaudioVoiceIn *) hw)->core; + 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->audioDevicePropertyBufferFrameSize; + avail = hw->samples - hw->total_samples_captured - core->decr; + + /* if there are not enough samples, set signal and return */ + if (avail < frameCount) { + inInputTime = 0; + coreaudio_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; + + + coreaudio_unlock (core, "audioDeviceIOProc"); + return 0; +} + +static int coreaudio_read (SWVoiceIn *sw, void *buf, int len) +{ + return audio_pcm_sw_read (sw, buf, len); +} + +static int coreaudio_init_in(HWVoiceIn *hw, struct audsettings *as, + void *drv_opaque) +{ + coreaudioVoice *core = ((coreaudioVoiceIn *) hw)->core; + CoreaudioConf *conf = drv_opaque; + + if (coreaudio_init_voice(core, hw, as, conf, audioInDeviceIOProc, true) < 0) { + return -1; + } + + audio_pcm_init_info (&hw->info, as); + hw->samples = conf->nbuffers * core->audioDevicePropertyBufferFrameSize; + + return 0; +} + +static void coreaudio_fini_in (HWVoiceIn *hw) +{ + coreaudioVoice *core = ((coreaudioVoiceIn *) hw)->core; + + coreaudio_fini_voice(core, true); +} + +static int coreaudio_ctl_in (HWVoiceIn *hw, int cmd, ...) +{ + coreaudioVoice *core = ((coreaudioVoiceIn *) hw)->core; + + return coreaudio_ctl_voice (core, cmd, true); +} + static CoreaudioConf glob_conf = { .buffer_frames = 512, .nbuffers = 4, @@ -727,7 +890,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 = { @@ -739,7 +908,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), };