Esempio n. 1
0
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;
}
Esempio n. 2
0
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,
								  &param,
								  sizeof(UInt32));
	ms_message("AudioUnitSetProperty %i %x", result, result);
	
	param = 0;
	result = AudioUnitSetProperty(d->caInAudioUnit,
								  kAudioOutputUnitProperty_EnableIO,
								  kAudioUnitScope_Output,
								  0,
								  &param,
								  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,
								  &param);
	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;
}
Esempio n. 3
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;
}