📄 aqsnd.c
字号:
/*mediastreamer2 library - modular sound and video processing and streamingCopyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* this file is specifically distributed under a BSD license *//*** Copyright (C) 2008 Hiroki Mori (himori@users.sourceforge.net)* All rights reserved.* * Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions are met:* * Redistributions of source code must retain the above copyright* notice, this list of conditions and the following disclaimer.* * Redistributions in binary form must reproduce the above copyright* notice, this list of conditions and the following disclaimer in the* documentation and/or other materials provided with the distribution.* * Neither the name of the <organization> nor the* names of its contributors may be used to endorse or promote products* derived from this software without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY <copyright holder> ``AS IS'' AND ANY* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE* DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.**//* This is MacOS X Audio Queue Service support code for mediastreamer2. Audio Queue Support MacOS X 10.5 or later. http://developer.apple.com/documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/ */#include <AudioToolbox/AudioToolbox.h>#if !defined(__AudioHardware_h__)#include "AudioHardware.h"#endif#include "mediastreamer2/mssndcard.h"#include "mediastreamer2/msfilter.h"MSFilter *ms_aq_read_new(MSSndCard *card);MSFilter *ms_aq_write_new(MSSndCard *card);#define kSecondsPerBuffer 0.04#define kNumberAudioDataBuffers 5typedef struct AQData{ int rate; int bits; bool_t stereo; ms_mutex_t mutex; queue_t rq; bool_t read_started; bool_t write_started; AudioQueueRef readQueue; AudioStreamBasicDescription readAudioFormat; UInt32 readBufferByteSize; AudioQueueRef writeQueue; AudioStreamBasicDescription writeAudioFormat; UInt32 writeBufferByteSize; AudioQueueBufferRef writeBuffers[kNumberAudioDataBuffers]; int curWriteBuffer; MSBufferizer *bufferizer;} AQData;/* Audio Queue recode callback */static void readCallback ( void *aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumPackets, const AudioStreamPacketDescription *inPacketDesc) { ms_debug("readCallback"); AQData *d=(AQData*)aqData; OSStatus err;// ms_debug("readCallback inNumPackets %d %d", inNumPackets, inBuffer->mAudioDataByteSize); mblk_t *rm=NULL; rm=allocb(inNumPackets*2,0); memcpy(rm->b_wptr, inBuffer->mAudioData, inNumPackets*2); rm->b_wptr += inNumPackets*2; ms_mutex_lock(&d->mutex); putq(&d->rq,rm); ms_mutex_unlock(&d->mutex); rm=NULL; err = AudioQueueEnqueueBuffer ( d->readQueue, inBuffer, 0, NULL ); if(err != noErr) { ms_error("readCallback:AudioQueueEnqueueBuffer %d", err); }}/* Audio Queue play callback */static void writeCallback ( void *aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) { ms_debug("writeCallback"); AQData *d=(AQData*)aqData; OSStatus err; if(d->bufferizer->size >= d->writeBufferByteSize) { ms_mutex_lock(&d->mutex); ms_bufferizer_read(d->bufferizer, inBuffer->mAudioData, d->writeBufferByteSize); ms_mutex_unlock(&d->mutex); } else { memset(inBuffer->mAudioData, 0, d->writeBufferByteSize); } inBuffer->mAudioDataByteSize = d->writeBufferByteSize; err = AudioQueueEnqueueBuffer ( d->writeQueue, inBuffer, 0, NULL ); if(err != noErr) { ms_error("AudioQueueEnqueueBuffer %d", err); }}void putWriteAQ(void *aqData, int queuenum){ ms_debug("putWriteAQ"); AQData *d=(AQData*)aqData; OSStatus err; err = AudioQueueEnqueueBuffer ( d->writeQueue, d->writeBuffers[queuenum], 0, NULL ); if(err != noErr) { ms_error("AudioQueueEnqueueBuffer %d", err); }}/* play buffer setup function */void setupWrite(MSSndCard *card) { ms_debug("setupWrite"); AQData *d=(AQData*)card->data; OSStatus err; int bufferIndex; for (bufferIndex = 0; bufferIndex < kNumberAudioDataBuffers; ++bufferIndex) { err = AudioQueueAllocateBuffer ( d->writeQueue, d->writeBufferByteSize, &d->writeBuffers[bufferIndex] ); if(err != noErr) { ms_error("setupWrite:AudioQueueAllocateBuffer %d", err); } }}/* recode buffer setup function */void setupRead(MSSndCard *card) { ms_debug("setupRead"); AQData *d=(AQData*)card->data; OSStatus err; // allocate and enqueue buffers int bufferIndex; for (bufferIndex = 0; bufferIndex < kNumberAudioDataBuffers; ++bufferIndex) { AudioQueueBufferRef buffer; err = AudioQueueAllocateBuffer ( d->readQueue, d->readBufferByteSize, &buffer ); if(err != noErr) { ms_error("setupRead:AudioQueueAllocateBuffer %d", err); } err = AudioQueueEnqueueBuffer ( d->readQueue, buffer, 0, NULL ); if(err != noErr) { ms_error("AudioQueueEnqueueBuffer %d", err); } }}/* mediastreamer2 function */static void aq_set_level(MSSndCard *card, MSSndCardMixerElem e, int percent){ AQData *d=(AQData*)card->data;}static int aq_get_level(MSSndCard *card, MSSndCardMixerElem e){ AQData *d=(AQData*)card->data; return 0;}static void aq_set_source(MSSndCard *card, MSSndCardCapture source){ AQData *d=(AQData*)card->data;}static void aq_init(MSSndCard *card){ ms_debug("aq_init"); AQData *d=ms_new(AQData,1); d->bits=16; d->rate=8000; d->stereo=FALSE; d->read_started=FALSE; d->write_started=FALSE; qinit(&d->rq); d->bufferizer=ms_bufferizer_new(); ms_mutex_init(&d->mutex,NULL); card->data=d;}static void aq_uninit(MSSndCard *card){ AQData *d=(AQData*)card->data; flushq(&d->rq,0); ms_bufferizer_destroy(d->bufferizer); ms_mutex_destroy(&d->mutex); ms_free(d);}static void aq_detect(MSSndCardManager *m);static MSSndCard *aq_duplicate(MSSndCard *obj);MSSndCardDesc aq_card_desc={ .driver_type="AQ", .detect=aq_detect, .init=aq_init, .set_level=aq_set_level, .get_level=aq_get_level, .set_capture=aq_set_source, .create_reader=ms_aq_read_new, .create_writer=ms_aq_write_new, .uninit=aq_uninit, .duplicate=aq_duplicate};static MSSndCard *aq_duplicate(MSSndCard *obj){ MSSndCard *card=ms_snd_card_new(&aq_card_desc); AQData *dcard=(AQData*)card->data; AQData *dobj=(AQData*)obj->data; card->name=ms_strdup(obj->name); return card;}static MSSndCard *aq_card_new(){ MSSndCard *card=ms_snd_card_new(&aq_card_desc); card->name=ms_strdup("Audio Queue"); return card;}static void aq_detect(MSSndCardManager *m){ ms_debug("aq_detect");#if defined(__AudioHardware_h__) OSStatus err; UInt32 count; AudioDeviceID inDevice, outDevice; char name[255]; count = sizeof(inDevice); err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &count,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -