📄 macsnd.c
字号:
d->caInASBD.mChannelsPerFrame = fAudioChannels; d->caInASBD.mSampleRate = tmpASBD.mSampleRate; d->caInASBD.mFormatID = kAudioFormatLinearPCM; d->caInASBD.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved; if (d->caInASBD.mFormatID == kAudioFormatLinearPCM && fAudioChannels == 1) d->caInASBD.mFormatFlags &= ~kLinearPCMFormatFlagIsNonInterleaved; d->caInASBD.mFormatFlags = kAudioFormatFlagIsFloat; if (htonl(0x1234) == 0x1234) d->caInASBD.mFormatFlags |= kAudioFormatFlagIsBigEndian; d->caInASBD.mBitsPerChannel = sizeof(Float32) * 8; d->caInASBD.mBytesPerFrame = d->caInASBD.mBitsPerChannel / 8; d->caInASBD.mFramesPerPacket = 1; d->caInASBD.mBytesPerPacket = d->caInASBD.mBytesPerFrame; err = AudioUnitSetProperty(d->caInAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &d->caInASBD, sizeof(AudioStreamBasicDescription)); d->caSourceBuffer=NULL; // Get the number of frames in the IO buffer(s) param = sizeof(UInt32); UInt32 fAudioSamples; result = AudioUnitGetProperty(d->caInAudioUnit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global, 0, &fAudioSamples, ¶m); if(err != noErr) { fprintf(stderr, "failed to get audio sample size\n"); return; } // Allocate our low device audio buffers d->fAudioBuffer = AllocateAudioBufferList(d->caInASBD.mChannelsPerFrame, fAudioSamples * d->caInASBD.mBytesPerFrame); if(d->fAudioBuffer == NULL) { fprintf(stderr, "failed to allocate buffers\n"); return; } // Allocate our low device audio buffers d->fMSBuffer = AllocateAudioBufferList(d->caInASBD.mChannelsPerFrame, fAudioSamples * d->caInASBD.mBytesPerFrame); if(d->fMSBuffer == NULL) { fprintf(stderr, "failed to allocate buffers\n"); return; } d->pcmdev=NULL; d->mixdev=NULL; d->pcmfd=-1; d->read_started=FALSE; d->write_started=FALSE; d->bits=16; d->rate=8000; d->stereo=FALSE; qinit(&d->rq); d->bufferizer=ms_bufferizer_new(); ms_mutex_init(&d->mutex,NULL); card->data=d;}static void ca_uninit(MSSndCard *card){ CAData *d=(CAData*)card->data; if (d->pcmdev!=NULL) ms_free(d->pcmdev); if (d->mixdev!=NULL) ms_free(d->mixdev); ms_bufferizer_destroy(d->bufferizer); flushq(&d->rq,0); ms_mutex_destroy(&d->mutex); ms_free(d);}static void ca_detect(MSSndCardManager *m);static MSSndCard *ca_duplicate(MSSndCard *obj);MSSndCardDesc ca_card_desc={ .driver_type="CA", .detect=ca_detect, .init=ca_init, .set_level=ca_set_level, .get_level=ca_get_level, .set_capture=ca_set_source, .create_reader=ms_ca_read_new, .create_writer=ms_ca_write_new, .uninit=ca_uninit, .duplicate=ca_duplicate};static MSSndCard *ca_duplicate(MSSndCard *obj){ MSSndCard *card=ms_snd_card_new(&ca_card_desc); CAData *dcard=(CAData*)card->data; CAData *dobj=(CAData*)obj->data; dcard->pcmdev=ms_strdup(dobj->pcmdev); dcard->mixdev=ms_strdup(dobj->mixdev); card->name=ms_strdup(obj->name); return card;}static MSSndCard *ca_card_new(){ MSSndCard *card=ms_snd_card_new(&ca_card_desc); card->name=ms_strdup("Core Audio"); return card;}static void ca_detect(MSSndCardManager *m){ ms_debug("ca_detect"); MSSndCard *card=ca_card_new(); ms_snd_card_manager_add_card(m,card);}static void ca_start_r(MSSndCard *card){ OSStatus err= noErr; CAData *d=(CAData*)card->data; ms_debug("ca_start_r"); if (d->read_started==FALSE){ AudioStreamBasicDescription outASBD; outASBD = d->caInASBD; outASBD.mSampleRate = d->rate; outASBD.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; if (htonl(0x1234) == 0x1234) outASBD.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; outASBD.mBytesPerPacket = (d->bits / 8) * outASBD.mChannelsPerFrame; outASBD.mBytesPerFrame = (d->bits / 8) * outASBD.mChannelsPerFrame; outASBD.mFramesPerPacket = 1; outASBD.mBitsPerChannel = d->bits; err = AudioConverterNew( &d->caInASBD, &outASBD, &d->caInConverter); if(err != noErr) ms_error("AudioConverterNew %x %d", err, outASBD.mBytesPerFrame); else CAShow(d->caInConverter); d->caInRenderCallback.inputProc = readRenderProc; d->caInRenderCallback.inputProcRefCon = d; err = AudioUnitSetProperty(d->caInAudioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &d->caInRenderCallback, sizeof(AURenderCallbackStruct)); if(AudioOutputUnitStart(d->caInAudioUnit) == noErr) d->read_started = TRUE; }}static void ca_stop_r(MSSndCard *card){ CAData *d=(CAData*)card->data; OSErr err; if(d->read_started == TRUE) { if(AudioOutputUnitStop(d->caInAudioUnit) == noErr) d->read_started=FALSE; }}static void ca_start_w(MSSndCard *card){ OSStatus err= noErr; ms_debug("ca_start_w"); CAData *d=(CAData*)card->data; if (d->write_started==FALSE){ AudioStreamBasicDescription inASBD; inASBD = d->caOutASBD; inASBD.mSampleRate = d->rate; inASBD.mFormatID = kAudioFormatLinearPCM; // http://developer.apple.com/documentation/MusicAudio/Reference/CoreAudioDataTypesRef/Reference/reference.html inASBD.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; if (htonl(0x1234) == 0x1234) inASBD.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; inASBD.mChannelsPerFrame = d->stereo ? 2 : 1; inASBD.mBytesPerPacket = (d->bits / 8) * inASBD.mChannelsPerFrame; inASBD.mBytesPerFrame = (d->bits / 8) * inASBD.mChannelsPerFrame; inASBD.mFramesPerPacket = 1; inASBD.mBitsPerChannel = d->bits; err = AudioConverterNew( &inASBD, &d->caOutASBD, &d->caOutConverter); if(err != noErr) ms_error("AudioConverterNew %x %d", err, inASBD.mBytesPerFrame); else CAShow(d->caOutConverter); if (inASBD.mChannelsPerFrame == 1 && d->caOutASBD.mChannelsPerFrame == 2) { if (d->caOutConverter) { // This should be as large as the number of output channels, // each element specifies which input channel's data is routed to that output channel SInt32 channelMap[] = { 0, 0 }; err = AudioConverterSetProperty(d->caOutConverter, kAudioConverterChannelMap, 2*sizeof(SInt32), channelMap); } } memset((char*)&d->caOutRenderCallback, 0, sizeof(AURenderCallbackStruct)); d->caOutRenderCallback.inputProc = writeRenderProc; d->caOutRenderCallback.inputProcRefCon = d; err = AudioUnitSetProperty (d->caOutAudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &d->caOutRenderCallback, sizeof(AURenderCallbackStruct)); if(err != noErr) ms_error("AudioUnitSetProperty %x", err); if(err == noErr) { if(AudioOutputUnitStart(d->caOutAudioUnit) == noErr) d->write_started=TRUE; } }}static void ca_stop_w(MSSndCard *card){ CAData *d=(CAData*)card->data; OSErr err; if(d->write_started == TRUE) { if(AudioOutputUnitStop(d->caOutAudioUnit) == noErr) d->write_started=FALSE; }}static mblk_t *ca_get(MSSndCard *card){ CAData *d=(CAData*)card->data; mblk_t *m; ms_mutex_lock(&d->mutex); m=getq(&d->rq); ms_mutex_unlock(&d->mutex); return m;}static void ca_put(MSSndCard *card, mblk_t *m){ CAData *d=(CAData*)card->data; ms_mutex_lock(&d->mutex); ms_bufferizer_put(d->bufferizer,m); ms_mutex_unlock(&d->mutex);}static void ca_read_preprocess(MSFilter *f){ MSSndCard *card=(MSSndCard*)f->data; ca_start_r(card);}static void ca_read_postprocess(MSFilter *f){ MSSndCard *card=(MSSndCard*)f->data; ca_stop_r(card);}static void ca_read_process(MSFilter *f){ MSSndCard *card=(MSSndCard*)f->data; mblk_t *m; while((m=ca_get(card))!=NULL){ ms_queue_put(f->outputs[0],m); }}static void ca_write_preprocess(MSFilter *f){ ms_debug("ca_write_preprocess"); MSSndCard *card=(MSSndCard*)f->data; ca_start_w(card);}static void ca_write_postprocess(MSFilter *f){ ms_debug("ca_write_postprocess"); MSSndCard *card=(MSSndCard*)f->data; ca_stop_w(card);}static void ca_write_process(MSFilter *f){// ms_debug("ca_write_process"); MSSndCard *card=(MSSndCard*)f->data; mblk_t *m; while((m=ms_queue_get(f->inputs[0]))!=NULL){ ca_put(card,m); }}static int set_rate(MSFilter *f, void *arg){ ms_debug("set_rate %d", *((int*)arg)); MSSndCard *card=(MSSndCard*)f->data; CAData *d=(CAData*)card->data; d->rate=*((int*)arg); return 0;}static int set_nchannels(MSFilter *f, void *arg){ ms_debug("set_nchannels %d", *((int*)arg)); MSSndCard *card=(MSSndCard*)f->data; CAData *d=(CAData*)card->data; d->stereo=(*((int*)arg)==2); return 0;}static MSFilterMethod ca_methods[]={ { MS_FILTER_SET_SAMPLE_RATE , set_rate }, { MS_FILTER_SET_NCHANNELS , set_nchannels }, { 0 , NULL }};MSFilterDesc ca_read_desc={ .id=MS_CA_READ_ID, .name="MSCARead", .text="Sound capture filter for MacOS X Core Audio drivers", .category=MS_FILTER_OTHER, .ninputs=0, .noutputs=1, .preprocess=ca_read_preprocess, .process=ca_read_process, .postprocess=ca_read_postprocess, .methods=ca_methods};MSFilterDesc ca_write_desc={ .id=MS_CA_WRITE_ID, .name="MSCAWrite", .text="Sound playback filter for MacOS X Core Audio drivers", .category=MS_FILTER_OTHER, .ninputs=1, .noutputs=0, .preprocess=ca_write_preprocess, .process=ca_write_process, .postprocess=ca_write_postprocess, .methods=ca_methods};MSFilter *ms_ca_read_new(MSSndCard *card){ ms_debug("ms_ca_read_new"); MSFilter *f=ms_filter_new_from_desc(&ca_read_desc); f->data=card; return f;}MSFilter *ms_ca_write_new(MSSndCard *card){ ms_debug("ms_ca_write_new"); MSFilter *f=ms_filter_new_from_desc(&ca_write_desc); f->data=card; return f;}MS_FILTER_DESC_EXPORT(ca_read_desc)MS_FILTER_DESC_EXPORT(ca_write_desc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -