2012-11-07 3 views
3

AudioUnitAddRenderNotify를 사용하여 RemoteIO에서 녹음을하려고합니다. 기본적으로 버스 1에서 샘플을 가져올 수 없습니다. 이는 입력 버스입니다. recordingCallback이지나 가지 않습니다 :iOS RemoteIO - AudioUnitAddRenderNotify Callback

if (*ioActionFlags & kAudioUnitRenderAction_PostRender || inBusNumber != 1) { 
    return noErr; 
} 

하지만이 recordingCallback가 각 버스마다 라운드를 호출해야한다는 말을 들었다. 즉. inBusNumber == 0, 그 다음에 inBusNumber == 1로 불리며 각각 출력 (remoteIO out)과 입력 (recording bus)입니다.

녹음 할 수 있도록 recordingCallback을 입력 버스에서 불러 오려면 어떻게해야합니까? 감사합니다. .

부두.

다음은 콜백입니다.

static OSStatus recordingCallback(void *inRefCon, 
           AudioUnitRenderActionFlags *ioActionFlags, 
           const AudioTimeStamp *inTimeStamp, 
           UInt32 inBusNumber, 
           UInt32 inNumberFrames, 
           AudioBufferList *ioData) { 
NSLog(@"Entered recording callback"); 

// Only do pre render on bus 1 
if (*ioActionFlags & kAudioUnitRenderAction_PostRender || inBusNumber != 1) { 
    return noErr; 
} 

RIO *rio = (RIO*)inRefCon; 
AudioUnit rioUnit = rio->theAudioUnit; 
//ExtAudioFileRef eaf = rio->outEAF; 
AudioBufferList abl = rio->audioBufferList; 

SInt32 samples[NUMBER_OF_SAMPLES]; // A large enough size to not have to worry about buffer overrun 
abl.mNumberBuffers = 1; 
abl.mBuffers[0].mData = &samples; 
abl.mBuffers[0].mNumberChannels = 1; 
abl.mBuffers[0].mDataByteSize = inNumberFrames * sizeof(SInt16); 

OSStatus result; 
result = AudioUnitRender(rioUnit, 
         ioActionFlags, 
         inTimeStamp, 
         inBusNumber, 
         inNumberFrames, 
         &abl); 

if (noErr != result) { NSLog(@"Obtain recorded samples error! Error : %ld", result); } 

NSLog(@"Bus %ld", inBusNumber); 

// React to a recording flag, if recording, save the abl into own buffer, else ignore 
if (rio->recording) 
{ 
    TPCircularBufferProduceBytes(&rio->buffer, abl.mBuffers[0].mData, inNumberFrames * sizeof(SInt16)); 
    //rio->timeIncurred += (('p'float)inNumberFrames)/44100.0; 
    //NSLog(@"Self-calculated time incurred: %f", rio->timeIncurred); 
} 

return noErr; 

}

다음은 콜백을 호출하는 코드입니다.

- (void)setupAudioUnitRemoteIO { 

UInt32 framesPerSlice = 0; 
UInt32 framesPerSlicePropertySize = sizeof (framesPerSlice); 
UInt32 sampleRatePropertySize = sizeof (_graphSampleRate); 

// Describe audio component 
AudioComponentDescription desc; 
desc.componentType = kAudioUnitType_Output; 
desc.componentSubType = kAudioUnitSubType_RemoteIO; 
desc.componentFlags = 0; 
desc.componentFlagsMask = 0; 
desc.componentManufacturer = kAudioUnitManufacturer_Apple; 

// Get component 
AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc); 

// Get audio units 
status = AudioComponentInstanceNew(inputComponent, &_remoteIOUnit); 

if (noErr != status) { NSLog(@"Get audio units error"); return; } 

// Enable IO for recording 
UInt32 flag = 1; 
status = AudioUnitSetProperty(_remoteIOUnit, 
           kAudioOutputUnitProperty_EnableIO, 
           kAudioUnitScope_Input, 
           kInputBus, 
           &flag, 
           sizeof(flag)); 
if (noErr != status) { NSLog(@"Enable IO for recording error"); return; } 

// Enable IO for playback 
status = AudioUnitSetProperty(_remoteIOUnit, 
           kAudioOutputUnitProperty_EnableIO, 
           kAudioUnitScope_Output, 
           kOutputBus, 
           &flag, 
           sizeof(flag)); 

if (noErr != status) { NSLog(@"Enable IO for playback error"); return; } 

// Obtain the value of the maximum-frames-per-slice from the I/O unit. 
status = AudioUnitGetProperty (
            _remoteIOUnit, 
            kAudioUnitProperty_MaximumFramesPerSlice, 
            kAudioUnitScope_Global, 
            0, 
            &framesPerSlice, 
            &framesPerSlicePropertySize 
           ); 

// Describe format 

audioFormat.mSampleRate   = 44100.00; 
audioFormat.mFormatID   = kAudioFormatLinearPCM; 
audioFormat.mFormatFlags  = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; 
audioFormat.mFramesPerPacket = 1; 
audioFormat.mChannelsPerFrame = 1; 
audioFormat.mBitsPerChannel  = 16; 
audioFormat.mBytesPerPacket  = 2; 
audioFormat.mBytesPerFrame  = 2; 

// Apply format 
status = AudioUnitSetProperty(_remoteIOUnit, 
           kAudioUnitProperty_StreamFormat, 
           kAudioUnitScope_Output, 
           kInputBus, 
           &audioFormat, 
           sizeof(audioFormat)); 

if (noErr != status) { NSLog(@"Apply format to input bus error"); return; } 

status = AudioUnitSetProperty(_remoteIOUnit, 
           kAudioUnitProperty_StreamFormat, 
           kAudioUnitScope_Input, 
           kOutputBus, 
           &audioFormat, 
           sizeof(audioFormat)); 
if (noErr != status) { NSLog(@"Apply format to output bus error"); return; } 




rio.theAudioUnit = _remoteIOUnit; // Need this, as used in callbacks to refer to remoteIO 

AURenderCallbackStruct callbackStruct; 
callbackStruct.inputProc = recordingCallback; 
callbackStruct.inputProcRefCon = &rio; 
status = AudioUnitAddRenderNotify(_remoteIOUnit, callbackStruct.inputProc, callbackStruct.inputProcRefCon); 

NSAssert (status == noErr, @"Problem adding recordingCallback to RemoteIO. Error code: %d '%.4s'", (int) status, (const char *)&status); 

답변

2

나는 AudioUnitAddRenderNotify를 사용하지 않고 다음 코드를 사용하여이 문제를 해결할 수있었습니다. 입력 버스

AURenderCallbackStruct callbackStruct; 
callbackStruct.inputProc = recordingCallback; 
callbackStruct.inputProcRefCon = &rio; 
status = AudioUnitSetProperty(_remoteIOUnit, 
           kAudioOutputUnitProperty_SetInputCallback, 
           kAudioUnitScope_Global, 
           kInputBus, 
           &callbackStruct, 
           sizeof(callbackStruct)); 
if (noErr != status) { NSLog(@"Set input callback error"); return; } 

대신

관련 문제