📄 coreaudio.c
字号:
/* * QEMU OS X CoreAudio audio driver * * Copyright (c) 2005 Mike Kronenberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */#include <CoreAudio/CoreAudio.h>#include <string.h> /* strerror */#include <pthread.h> /* pthread_X */#include "vl.h"#define AUDIO_CAP "coreaudio"#include "audio_int.h"struct { int buffer_frames; int nbuffers; int isAtexit;} conf = { .buffer_frames = 512, .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;static void coreaudio_logstatus (OSStatus status){ char *str = "BUG"; switch(status) { case kAudioHardwareNoError: str = "kAudioHardwareNoError"; break; case kAudioHardwareNotRunningError: str = "kAudioHardwareNotRunningError"; break; case kAudioHardwareUnspecifiedError: str = "kAudioHardwareUnspecifiedError"; break; case kAudioHardwareUnknownPropertyError: str = "kAudioHardwareUnknownPropertyError"; break; case kAudioHardwareBadPropertySizeError: str = "kAudioHardwareBadPropertySizeError"; break; case kAudioHardwareIllegalOperationError: str = "kAudioHardwareIllegalOperationError"; break; case kAudioHardwareBadDeviceError: str = "kAudioHardwareBadDeviceError"; break; case kAudioHardwareBadStreamError: str = "kAudioHardwareBadStreamError"; break; case kAudioHardwareUnsupportedOperationError: str = "kAudioHardwareUnsupportedOperationError"; break; case kAudioDeviceUnsupportedFormatError: str = "kAudioDeviceUnsupportedFormatError"; break; case kAudioDevicePermissionsError: str = "kAudioDevicePermissionsError"; break; default: AUD_log (AUDIO_CAP, "Reason: status code %ld\n", status); return; } AUD_log (AUDIO_CAP, "Reason: %s\n", str);}static void GCC_FMT_ATTR (2, 3) coreaudio_logerr ( OSStatus status, const char *fmt, ... ){ va_list ap; va_start (ap, fmt); AUD_log (AUDIO_CAP, fmt, ap); va_end (ap); coreaudio_logstatus (status);}static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 ( OSStatus status, const char *typ, const char *fmt, ... ){ va_list ap; AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ); va_start (ap, fmt); AUD_vlog (AUDIO_CAP, fmt, ap); va_end (ap); coreaudio_logstatus (status);}static inline UInt32 isPlaying (AudioDeviceID outputDeviceID){ OSStatus status; UInt32 result = 0; UInt32 propertySize = sizeof(outputDeviceID); status = AudioDeviceGetProperty( outputDeviceID, 0, 0, kAudioDevicePropertyDeviceIsRunning, &propertySize, &result); if (status != kAudioHardwareNoError) { coreaudio_logerr(status, "Could not determine whether Device is playing\n"); } return result;}static void coreaudio_atexit (void){ conf.isAtexit = 1;}static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name){ int err; err = pthread_mutex_lock (&core->mutex); if (err) { dolog ("Could not lock voice for %s\nReason: %s\n", fn_name, strerror (err)); return -1; } return 0;}static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name){ int err; err = pthread_mutex_unlock (&core->mutex); if (err) { dolog ("Could not unlock voice for %s\nReason: %s\n", fn_name, strerror (err)); return -1; } return 0;}static int coreaudio_run_out (HWVoiceOut *hw){ int live, decr; coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; if (coreaudio_lock (core, "coreaudio_run_out")) { return 0; } live = audio_pcm_hw_get_live_out (hw); 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; st_sample_t *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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -