2012-05-15 2 views
4

아래 코드를 사용하여 오디오 구성 요소를 초기화하고 있습니다.AudioUnitInitialize가 AudioComponentInstance를 초기화하는 동안 오류를 발생시킵니다.

-(void) startListeningWithCoreAudio 
{ 
    NSError *error = nil; 

    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayAndRecord error:&error]; 
    if (error) 
      NSLog(@"error setting up audio session: %@", [error localizedDescription]); 

    [[AVAudioSession sharedInstance] setDelegate:self]; 

    OSStatus status = AudioSessionSetActive(YES); 
    checkStatus(status); 

      // Find the apple mic 
    AudioComponentDescription desc; 
    desc.componentType = kAudioUnitType_Output; 
    desc.componentSubType = kAudioUnitSubType_VoiceProcessingIO; 
    desc.componentFlags = 0; 
    desc.componentFlagsMask = 0; 
    desc.componentManufacturer = kAudioUnitManufacturer_Apple; 

    AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc); 
    status = AudioComponentInstanceNew(inputComponent, &kAudioUnit); 
    checkStatus(status); 

      // enable mic output as our input 
    UInt32 flag = 1; 
    status = AudioUnitSetProperty(kAudioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag)); 
    checkStatus(status); 


      // Define mic output audio format 
    AudioStreamBasicDescription audioFormat; 
    audioFormat.mSampleRate   = 16000.0; 
    audioFormat.mFormatID   = kAudioFormatLinearPCM; 
    audioFormat.mFormatFlags  = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; 
    audioFormat.mFramesPerPacket = 1; 
    audioFormat.mChannelsPerFrame = 1; 
    audioFormat.mBitsPerChannel  = 16; 
    audioFormat.mBytesPerPacket  = 2; 
    audioFormat.mBytesPerFrame  = 2; 

    status = AudioUnitSetProperty(kAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &audioFormat, sizeof(audioFormat)); 
    checkStatus(status); 

      // Define our callback methods 
    AURenderCallbackStruct callbackStruct; 
    callbackStruct.inputProc = recordingCallback; 
    callbackStruct.inputProcRefCon = self; 
    status = AudioUnitSetProperty(kAudioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, kInputBus, &callbackStruct, sizeof(callbackStruct)); 
    checkStatus(status); 

      // By pass voice processing 
    UInt32 audiobypassProcessing = [[NSUserDefaults standardUserDefaults] boolForKey:VOICE_BY_PASS_PROCESSING]; 
    status = AudioUnitSetProperty(kAudioUnit, kAUVoiceIOProperty_BypassVoiceProcessing, 
            kAudioUnitScope_Global, kInputBus, &audiobypassProcessing, sizeof(audiobypassProcessing)); 
    checkStatus(status); 

      // Automatic Gain Control 
    UInt32 audioAGC = [[NSUserDefaults standardUserDefaults]boolForKey:VOICE_AGC]; 
    status = AudioUnitSetProperty(kAudioUnit, kAUVoiceIOProperty_VoiceProcessingEnableAGC, 
            kAudioUnitScope_Global, kInputBus, &audioAGC, sizeof(audioAGC)); 
    checkStatus(status); 

      //Non Audio Voice Ducking 
    UInt32 audioDucking = [[NSUserDefaults standardUserDefaults]boolForKey:VOICE_DUCKING]; 
    status = AudioUnitSetProperty(kAudioUnit, kAUVoiceIOProperty_DuckNonVoiceAudio, 
            kAudioUnitScope_Global, kInputBus, &audioDucking, sizeof(audioDucking)); 
    checkStatus(status); 

      //Audio Quality 
    UInt32 quality = [[NSUserDefaults standardUserDefaults]integerForKey:VOICE_QUALITY]; 
    status = AudioUnitSetProperty(kAudioUnit, kAUVoiceIOProperty_VoiceProcessingQuality, 
            kAudioUnitScope_Global, kInputBus, &quality, sizeof(quality)); 
    checkStatus(status); 

    status = AudioUnitInitialize(kAudioUnit); 
    checkStatus(status); 

    status = AudioOutputUnitStart(kAudioUnit); 
    checkStatus(status); 

    UInt32 audioRoute = (UInt32)kAudioSessionOverrideAudioRoute_Speaker; 
    status = AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof (audioRoute), &audioRoute); 
    checkStatus(status);  
} 


-(void) stopListeningWithCoreAudio 
{ 
    OSStatus  status = AudioUnitUninitialize(kAudioUnit); 
    checkStatus(status); 

    status = AudioOutputUnitStop(kAudioUnit); 
    checkStatus(status); 

//  if(kAudioUnit) 
//  { 
//   status = AudioComponentInstanceDispose(kAudioUnit); 
//   checkStatus(status); 
//   kAudioUnit = nil; 
//  } 

    status = AudioSessionSetActive(NO); 
    checkStatus(status); 

    NSError *error = nil; 
    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategorySoloAmbient error:&error]; 
    if (error) 
      NSLog(@"error setting up audio session: %@", [error localizedDescription]); 
} 

처음에는 문제가 없습니다. button pressed 이벤트에 의해 startListeningWithCoreAudio이 호출됨을 의미합니다. 오디오를 잘 녹음/처리 할 수 ​​있습니다. 다른 경우에는 stopListeningWithCoreAudio에게 녹음/처리 오디오를 중지하도록 요청합니다.

startListeningWithCoreAudio 함수를 다시 호출하려고 할 때 문제가 발생합니다. 두 함수에 오류가 발생합니다. startListeningWithCoreAudio에서 호출되는 AudioUnitInitializeAudioOutputUnitStart입니다.

아무도 도와 주실 수 있습니까?

고맙습니다.

답변

2

해결책을 찾았습니다. 아래 함수를 연속적으로 호출하면 문제가 발생합니다.

extern OSStatus AudioUnitUninitialize(AudioUnit inUnit)      
extern OSStatus AudioComponentInstanceDispose(AudioComponentInstance inInstance) 

그래서 아래의 방법으로 메인 스레드에서 메소드를 호출했습니다.

[self performSelectorOnMainThread:@selector(disposeCoreAudio) withObject:nil waitUntilDone:NO]; 

-(void) disposeCoreAudio 
{ 
    OSStatus status = AudioComponentInstanceDispose(kAudioUnit); 
    kAudioUnit = nil; 
} 

문제가 해결되었습니다. 따라서 올바른 순서는 레코딩 중지, 레코더 초기화 취소 및 메인 스레드의 레코더 폐기입니다.

1

가능한 한 가지 문제는 코드가 실행중인 오디오 장치를 중지하기 전에 초기화되지 않는 것입니다.

+0

답변 해 주셔서 감사합니다. +1. 실제 이유는 청각이었다. 앱이 활성화되는 동안 세션을 설정하고 앱이 백그라운드로 진행되는 동안 세션을 제거합니다. 나중에 오디오 장치가 초기화되지 않습니다. – Apurv

관련 문제