OSStatus readRenderProc(void *inRefCon, AudioUnitRenderActionFlags *inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumFrames, AudioBufferList *ioData) { CAData *d=(CAData*)inRefCon; OSStatus err = noErr; err = AudioUnitRender(d->caInAudioUnit, inActionFlags, inTimeStamp, inBusNumber, inNumFrames, d->fAudioBuffer); if(err != noErr) { ms_error("AudioUnitRender %d size = %d", err, d->fAudioBuffer->mBuffers[0].mDataByteSize); return err; } UInt32 AvailableOutputBytes = inNumFrames * sizeof (float) * d->caInASBD.mChannelsPerFrame; UInt32 propertySize = sizeof (AvailableOutputBytes); err = AudioConverterGetProperty (d->caInConverter, kAudioConverterPropertyCalculateOutputBufferSize, &propertySize, &AvailableOutputBytes); if(err != noErr) { ms_error("AudioConverterGetProperty kAudioConverterPropertyCalculateOutputBufferSize %d", err); return err; } if (AvailableOutputBytes>d->fMSBuffer->mBuffers[0].mDataByteSize) { DestroyAudioBufferList(d->fMSBuffer); d->fMSBuffer = AllocateAudioBufferList(d->stereo ? 2 : 1, AvailableOutputBytes); } UInt32 ActualOutputFrames = AvailableOutputBytes / ((d->bits / 8) * 1) / d->caInASBD.mChannelsPerFrame; err = AudioConverterFillComplexBuffer (d->caInConverter, (AudioConverterComplexInputDataProc)(readACInputProc), inRefCon, &ActualOutputFrames, d->fMSBuffer, NULL); if(err != noErr) { ms_error("readRenderProc:AudioConverterFillComplexBuffer %d", err); return err; } mblk_t *rm=NULL; rm=allocb(ActualOutputFrames*2,0); memcpy(rm->b_wptr, d->fMSBuffer->mBuffers[0].mData, ActualOutputFrames*2); rm->b_wptr+=ActualOutputFrames*2; if (gain_volume_in != 1.0f) { int16_t *ptr=(int16_t *)rm->b_rptr; for (;ptr<(int16_t *)rm->b_wptr;ptr++) { *ptr=(int16_t)(((float)(*ptr))*gain_volume_in); } } ms_mutex_lock(&d->mutex); putq(&d->rq,rm); ms_mutex_unlock(&d->mutex); rm=NULL; return err; }
static int ca_open_r(CAData *d){ OSStatus result; UInt32 param; AudioDeviceID fInputDeviceID; ComponentDescription desc; Component comp; // Get Default Input audio unit desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_HALOutput; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; comp = FindNextComponent(NULL, &desc); if (comp == NULL) { ms_message("Cannot find audio component"); return -1; } result = OpenAComponent(comp, &d->caInAudioUnit); if(result != noErr) { ms_message("Cannot open audio component %x", result); return -1; } param = 1; result = AudioUnitSetProperty(d->caInAudioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, ¶m, sizeof(UInt32)); ms_message("AudioUnitSetProperty %i %x", result, result); param = 0; result = AudioUnitSetProperty(d->caInAudioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, ¶m, sizeof(UInt32)); ms_message("AudioUnitSetProperty %i %x", result, result); // Set the current device to the default input unit. result = AudioUnitSetProperty(d->caInAudioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &d->dev, sizeof(AudioDeviceID)); ms_message("AudioUnitSetProperty %i %x", result, result); UInt32 asbdsize = sizeof(AudioStreamBasicDescription); memset((char *)&d->caInASBD, 0, asbdsize); result = AudioUnitGetProperty (d->caInAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &d->caInASBD, &asbdsize); ms_message("AudioUnitGetProperty %i %x", result, result); if (d->caInASBD.mChannelsPerFrame>1) { d->caInASBD.mBytesPerFrame = d->caInASBD.mBytesPerFrame / d->caInASBD.mChannelsPerFrame; d->caInASBD.mBytesPerPacket = d->caInASBD.mBytesPerPacket / d->caInASBD.mChannelsPerFrame; d->caInASBD.mChannelsPerFrame = 1; } result = AudioUnitSetProperty(d->caInAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &d->caInASBD, sizeof(AudioStreamBasicDescription)); ms_message("AudioUnitSetProperty %i %x", result, result); d->caSourceBuffer=NULL; // Get the number of frames in the IO buffer(s) param = sizeof(UInt32); UInt32 fAudioSamples; result = AudioUnitGetProperty(d->caInAudioUnit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Input, 1, &fAudioSamples, ¶m); if(result != noErr) { ms_error("failed to get audio sample size"); return -1; } result = AudioUnitInitialize(d->caInAudioUnit); if(result != noErr) { ms_error("failed to AudioUnitInitialize input %i", result); return -1; } // Allocate our low device audio buffers d->fAudioBuffer = AllocateAudioBufferList(d->caInASBD.mChannelsPerFrame, fAudioSamples * d->caInASBD.mBytesPerFrame * 2); if(d->fAudioBuffer == NULL) { ms_error("failed to allocate buffers fAudioBuffer"); return -1; } // Allocate our low device audio buffers d->fMSBuffer = AllocateAudioBufferList( d->stereo ? 2 : 1, fAudioSamples * ((d->bits / 8)*(d->stereo ? 2 : 1)) *2); if(d->fMSBuffer == NULL) { ms_error("failed to allocate buffers fMSBuffer"); return -1; } return 0; }
static void * audio_cap_ca_init(char *cfg) { if(cfg && strcmp(cfg, "help") == 0) { printf("Available Core Audio capture devices:\n"); audio_cap_ca_help(NULL); return &audio_init_state_ok; } struct state_ca_capture *s; OSErr ret = noErr; #if OS_VERSION_MAJOR <= 9 Component comp; ComponentDescription desc; #else AudioComponent comp; AudioComponentDescription desc; #endif UInt32 size; AudioDeviceID device; s = (struct state_ca_capture *) calloc(1, sizeof(struct state_ca_capture)); size=sizeof(device); if(cfg != NULL) { device = atoi(cfg); } else { ret = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &size, &device); if(ret) { fprintf(stderr, "Error finding default input device.\n"); goto error; } } pthread_mutex_init(&s->lock, NULL); pthread_cond_init(&s->cv, NULL); s->boss_waiting = FALSE; s->data_ready = FALSE; s->frame.bps = audio_capture_bps ? audio_capture_bps : 2; s->frame.ch_count = audio_capture_channels; double rate; size = sizeof(double); ret = AudioDeviceGetProperty(device, 0, 0, kAudioDevicePropertyNominalSampleRate, &size, &rate); s->nominal_sample_rate = rate; s->frame.sample_rate = audio_capture_sample_rate ? audio_capture_sample_rate : rate; #if !defined HAVE_SPEEX || defined DISABLE_SPPEX_RESAMPLER s->frame.sample_rate = rate; #if !defined HAVE_SPEEX fprintf(stderr, "[CoreAudio] Libspeex support not compiled in, resampling won't work (check manual or wiki how to enable it)!\n"); #endif #else s->resampler = NULL; if(s->frame.sample_rate != s->nominal_sample_rate) { int err; s->resampler = speex_resampler_init(s->frame.ch_count, s->nominal_sample_rate, s->frame.sample_rate, 10, &err); if(err) { s->frame.sample_rate = s->nominal_sample_rate; } } #endif s->frame.max_size = s->frame.bps * s->frame.ch_count * s->frame.sample_rate; int nonres_channel_size = s->frame.bps * s->nominal_sample_rate; s->theBufferList = AllocateAudioBufferList(s->frame.ch_count, nonres_channel_size); s->tmp = (char *) malloc(nonres_channel_size * s->frame.ch_count); s->buffer = ring_buffer_init(s->frame.max_size); s->frame.data = (char *) malloc(s->frame.max_size); #ifdef HAVE_SPEEX s->resampled = (char *) malloc(s->frame.max_size); #endif //There are several different types of Audio Units. //Some audio units serve as Outputs, Mixers, or DSP //units. See AUComponent.h for listing desc.componentType = kAudioUnitType_Output; //Every Component has a subType, which will give a clearer picture //of what this components function will be. //desc.componentSubType = kAudioUnitSubType_DefaultOutput; desc.componentSubType = kAudioUnitSubType_HALOutput; //all Audio Units in AUComponent.h must use //"kAudioUnitManufacturer_Apple" as the Manufacturer desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; #if OS_VERSION_MAJOR > 9 comp = AudioComponentFindNext(NULL, &desc); if(!comp) { fprintf(stderr, "Error finding AUHAL component.\n"); goto error; } ret = AudioComponentInstanceNew(comp, &s->auHALComponentInstance); if (ret != noErr) { fprintf(stderr, "Error opening AUHAL component.\n"); goto error; } #else comp = FindNextComponent(NULL, &desc); if(!comp) { fprintf(stderr, "Error finding AUHAL component.\n"); goto error; } ret = OpenAComponent(comp, &s->auHALComponentInstance); if (ret != noErr) { fprintf(stderr, "Error opening AUHAL component.\n"); goto error; } #endif UInt32 enableIO; //When using AudioUnitSetProperty the 4th parameter in the method //refer to an AudioUnitElement. When using an AudioOutputUnit //the input element will be '1' and the output element will be '0'. enableIO = 1; ret = AudioUnitSetProperty(s->auHALComponentInstance, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, // input element &enableIO, sizeof(enableIO)); if (ret != noErr) { fprintf(stderr, "Error enabling input on AUHAL.\n"); goto error; } enableIO = 0; ret = AudioUnitSetProperty(s->auHALComponentInstance, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, //output element &enableIO, sizeof(enableIO)); if (ret != noErr) { fprintf(stderr, "Error disabling output on AUHAL.\n"); goto error; } size=sizeof(device); ret = AudioUnitSetProperty(s->auHALComponentInstance, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &device, sizeof(device)); if(ret) { fprintf(stderr, "[CoreAudio] Error setting device to AUHAL instance.\n"); goto error; } { AudioStreamBasicDescription desc; size = sizeof(desc); ret = AudioUnitGetProperty(s->auHALComponentInstance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &desc, &size); if(ret) { fprintf(stderr, "[CoreAudio] Error getting default device properties.\n"); goto error; } desc.mChannelsPerFrame = s->frame.ch_count; desc.mSampleRate = (double) s->nominal_sample_rate; desc.mFormatID = kAudioFormatLinearPCM; desc.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved; if (desc.mFormatID == kAudioFormatLinearPCM && s->frame.ch_count == 1) desc.mFormatFlags &= ~kLinearPCMFormatFlagIsNonInterleaved; /*#if __BIG_ENDIAN__ desc.mFormatFlags |= kAudioFormatFlagIsBigEndian; #endif */ desc.mBitsPerChannel = s->frame.bps * 8; desc.mBytesPerFrame = desc.mBitsPerChannel / 8; desc.mFramesPerPacket = 1; desc.mBytesPerPacket = desc.mBytesPerFrame; s->audio_packet_size = desc.mBytesPerPacket; ret = AudioUnitSetProperty(s->auHALComponentInstance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &desc, sizeof(desc)); if(ret) { fprintf(stderr, "[CoreAudio] Error setting device properties.\n"); goto error; } AURenderCallbackStruct input; input.inputProc = InputProc; input.inputProcRefCon = s; ret = AudioUnitSetProperty(s->auHALComponentInstance, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(input)); if(ret) { fprintf(stderr, "[CoreAudio] Error setting input callback.\n"); goto error; } } ret = AudioUnitInitialize(s->auHALComponentInstance); if(ret) { fprintf(stderr, "[CoreAudio] Error initializing device.\n"); goto error; } ret = AudioOutputUnitStart(s->auHALComponentInstance); if(ret) { fprintf(stderr, "[CoreAudio] Error starting device.\n"); goto error; } return s; error: pthread_mutex_destroy(&s->lock); pthread_cond_destroy(&s->cv); DestroyAudioBufferList(s->theBufferList); free(s->frame.data); ring_buffer_destroy(s->buffer); free(s->tmp); free(s); return NULL; }