OSStatus CAPlayThrough::InputProc(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList * ioData) { OSStatus err = noErr; CAPlayThrough *This = (CAPlayThrough *)inRefCon; This->mutex.lock(); if (This->mFirstInputTime < 0.) This->mFirstInputTime = inTimeStamp->mSampleTime; //Get the new audio data err = AudioUnitRender(This->mInputUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, //# of frames requested This->mInputBuffer);// Audio Buffer List to hold data checkErr(err); if(!err) { AEFloatConverterToFloat(This->converter, This->mInputBuffer, This->floatBuffers, inNumberFrames); This->postNotification(This->floatBuffers, inNumberFrames); err = This->mBuffer->Store(This->mInputBuffer, Float64(inNumberFrames), SInt64(inTimeStamp->mSampleTime)); } This->mutex.unlock(); return err; }
OSStatus CAPlayThrough::OutputProc(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *TimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList * ioData) { OSStatus err = noErr; CAPlayThrough *This = (CAPlayThrough *)inRefCon; Float64 rate = 0.0; AudioTimeStamp inTS, outTS; if (This->mFirstInputTime < 0.) { // input hasn't run yet -> silence MakeBufferSilent (ioData); return noErr; } //use the varispeed playback rate to offset small discrepancies in sample rate //first find the rate scalars of the input and output devices err = AudioDeviceGetCurrentTime(This->mInputDevice.mID, &inTS); // this callback may still be called a few times after the device has been stopped if (err) { MakeBufferSilent (ioData); return noErr; } err = AudioDeviceGetCurrentTime(This->mOutputDevice.mID, &outTS); checkErr(err); rate = inTS.mRateScalar / outTS.mRateScalar; err = AudioUnitSetParameter(This->mVarispeedUnit,kVarispeedParam_PlaybackRate,kAudioUnitScope_Global,0, rate,0); checkErr(err); //get Delta between the devices and add it to the offset if (This->mFirstOutputTime < 0.) { This->mFirstOutputTime = TimeStamp->mSampleTime; Float64 delta = (This->mFirstInputTime - This->mFirstOutputTime); This->ComputeThruOffset(); //changed: 3865519 11/10/04 if (delta < 0.0) This->mInToOutSampleOffset -= delta; else This->mInToOutSampleOffset = -delta + This->mInToOutSampleOffset; MakeBufferSilent (ioData); return noErr; } //copy the data from the buffers err = This->mBuffer->Fetch(ioData, inNumberFrames, SInt64(TimeStamp->mSampleTime - This->mInToOutSampleOffset)); //old line of code different once ring buffer is replaced //err = This->mBuffer->Fetch(ioData, inNumberFrames, SInt64(TimeStamp->mSampleTime - This->mInToOutSampleOffset), false); if(err != kCARingBufferError_OK) { MakeBufferSilent (ioData); SInt64 bufferStartTime, bufferEndTime; This->mBuffer->GetTimeBounds(bufferStartTime, bufferEndTime); This->mInToOutSampleOffset = TimeStamp->mSampleTime - bufferStartTime; } return noErr; }
OSStatus CAPlayThrough::OutputProc(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *TimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList * ioData) { OSStatus err = noErr; CAPlayThrough *This = (CAPlayThrough *)inRefCon; Float64 rate = 0.0; AudioTimeStamp inTS, outTS; if (This->mFirstInputTime < 0.) { // input hasn't run yet -> silence MakeBufferSilent (ioData); return noErr; } //use the varispeed playback rate to offset small discrepancies in sample rate //first find the rate scalars of the input and output devices err = AudioDeviceGetCurrentTime(This->mInputDevice.mID, &inTS); // this callback may still be called a few times after the device has been stopped if (err) { MakeBufferSilent (ioData); return noErr; } err = AudioDeviceGetCurrentTime(This->mOutputDevice.mID, &outTS); checkErr(err); rate = inTS.mRateScalar / outTS.mRateScalar; err = AudioUnitSetParameter(This->mVarispeedUnit,kVarispeedParam_PlaybackRate,kAudioUnitScope_Global,0, rate,0); checkErr(err); //get Delta between the devices and add it to the offset if (This->mFirstOutputTime < 0.) { This->mFirstOutputTime = TimeStamp->mSampleTime; Float64 delta = (This->mFirstInputTime - This->mFirstOutputTime); This->ComputeThruOffset(); //changed: 3865519 11/10/04 if (delta < 0.0) This->mInToOutSampleOffset -= delta; else This->mInToOutSampleOffset = -delta + This->mInToOutSampleOffset; CAPT_DEBUG( "Set initial IOOffset to %f.\n", This->mInToOutSampleOffset ); MakeBufferSilent (ioData); return noErr; } //copy the data from the buffers err = This->mBuffer->Fetch(ioData, inNumberFrames, SInt64(TimeStamp->mSampleTime - This->mInToOutSampleOffset)); if( err != kCARingBufferError_OK ) { SInt64 bufferStartTime, bufferEndTime; This->mBuffer->GetTimeBounds( bufferStartTime, bufferEndTime ); CAPT_DEBUG( "Oops. Adjusting IOOffset from %f, ", This->mInToOutSampleOffset ); if ( err < kCARingBufferError_OK ) { CAPT_DEBUG( "ahead " ); if ( err == kCARingBufferError_WayBehind ) { MakeBufferSilent( ioData ); } This->mInToOutSampleOffset += std::max( ( TimeStamp->mSampleTime - This->mInToOutSampleOffset ) - bufferStartTime, kAdjustmentOffsetSamples ); } else if ( err > kCARingBufferError_OK ) { CAPT_DEBUG( "behind " ); if ( err == kCARingBufferError_WayAhead ) { MakeBufferSilent( ioData ); } // Adjust by the amount that we read past in the buffer This->mInToOutSampleOffset += std::max( ( ( TimeStamp->mSampleTime - This->mInToOutSampleOffset ) + inNumberFrames ) - bufferEndTime, kAdjustmentOffsetSamples ); } CAPT_DEBUG( "to %f.\n", This->mInToOutSampleOffset ); MakeBufferSilent ( ioData ); } return noErr; }