2016-06-16 13 views
1

kAudioUnitSubType_LowPassFilter을 추가하려고하는데 성공하지 못했습니다. kAudioUnitSubType_LowPassFilter를 AUGraph에 추가하는 방법은 무엇입니까?

는 다음 코드 구현 :

// create a new AUGraph 
[Utilities checkError:NewAUGraph(&self.info->mGraph) 
      operation: "Couldn't create a new AUGraph"]; 

AUNode rioNode; 
AUNode lpfNode; 

// Create filter audio unit 
AudioComponentDescription lpfAU_description; 
lpfAU_description.componentType = kAudioUnitType_Effect; 
lpfAU_description.componentSubType = kAudioUnitSubType_LowPassFilter; 
lpfAU_description.componentFlags = 0; 
lpfAU_description.componentFlagsMask = 0; 
lpfAU_description.componentManufacturer = kAudioUnitManufacturer_Apple; 


// Create RemoteIO audio unit 
AudioComponentDescription rioAU_description; 
rioAU_description.componentType = kAudioUnitType_Output; 
rioAU_description.componentSubType = kAudioUnitSubType_RemoteIO; 
rioAU_description.componentManufacturer = kAudioUnitManufacturer_Apple; 
rioAU_description.componentFlags = 0; 
rioAU_description.componentFlagsMask = 0; 

[Utilities checkError:AUGraphAddNode(self.info->mGraph, &rioAU_description, &rioNode) 
      operation: "Couldn't add Graph Node"]; 
[Utilities checkError:AUGraphAddNode(self.info->mGraph, &lpfAU_description, &lpfNode) 
      operation: "Couldn't add Graph Node"]; 

// Open graph 
[Utilities checkError:AUGraphOpen(self.info->mGraph) 
      operation: "Couldn't open graph"]; 

// Get audio units 
[Utilities checkError:AUGraphNodeInfo(self.info->mGraph, lpfNode, NULL, &self.info->lpfUnit) 
      operation: "Couldn't link node to audio unit"]; 

[Utilities checkError:AUGraphNodeInfo(self.info->mGraph, rioNode, NULL, &self.info->rioUnit) 
      operation: "Couldn't link node to audio unit"]; 

// Make connections 
[Utilities checkError:AUGraphConnectNodeInput(self.info->mGraph, rioNode, 1, lpfNode, 1) 
      operation: "Couldn't connect remoteIO output scope bus 1 to filter input scope bus 1"];// input -> filter 

[Utilities checkError: AUGraphConnectNodeInput(self.info->mGraph, lpfNode, 0, rioNode, 0) 
      operation: "Couldn't connect filter output scope bus 0 to remoteIO input scope bus 0"]; // filter -> output 

// Enable IO for input and output (recording and playing) 
AudioUnitElement kRemoteIOInputScopeMic = 1; 
AudioUnitElement kRemoteIOOutputScopeSpeaker = 0; 

UInt32 enableInput = 1; 
[Utilities checkError:AudioUnitSetProperty (self.info->rioUnit, 
              kAudioOutputUnitProperty_EnableIO, 
              kAudioUnitScope_Input, 
              kRemoteIOInputScopeMic, 
              &enableInput, 
              sizeof(enableInput)) 
      operation: "Couldn't enable RIO input"]; 

// set up the rio unit for playback 
UInt32 enableOutput = 1; 
[Utilities checkError:AudioUnitSetProperty (self.info->rioUnit, 
              kAudioOutputUnitProperty_EnableIO, 
              kAudioUnitScope_Output, 
              kRemoteIOOutputScopeSpeaker, 
              &enableOutput, 
              sizeof(enableOutput)) 
      operation: "Couldn't enable RIO output"]; 

// Set property to low-pass filter 
AudioUnitSetParameter(self.info->lpfUnit, 
         kLowPassParam_CutoffFrequency, 
         kAudioUnitScope_Global, 
         0, 
         1000, 
         0); 



// Set callbacks 
// Callback for input 
AURenderCallbackStruct callbackStruct; 
callbackStruct.inputProc = recordingCallback; 
callbackStruct.inputProcRefCon = (__bridge void*) self; 


[Utilities checkError: AudioUnitSetProperty(self.info->rioUnit, 
              kAudioOutputUnitProperty_SetInputCallback, 
              kAudioUnitScope_Global, 
              1, // Input bus 
              &callbackStruct, 
              sizeof(AURenderCallbackStruct)) 
      operation: "AudioUnitSetProperty set RenderCalback"]; 

// Callback to render data 
callbackStruct.inputProc = renderCallback; 
callbackStruct.inputProcRefCon = (__bridge void*) self; 


[Utilities checkError: AudioUnitSetProperty(self.info->rioUnit, 
              kAudioUnitProperty_SetRenderCallback, 
              kAudioUnitScope_Input, //kAudioUnitScope_Global, ???? 
              0, // Output bus 
              &callbackStruct, 
              sizeof(AURenderCallbackStruct)) 
      operation: "AudioUnitSetProperty set RenderCalback"]; 

[Utilities checkError: AUGraphInitialize(self.info->mGraph) 
      operation: "Couldn't initialize graph"]; 


// Input ASBD 
AudioStreamBasicDescription inputasbd; 
UInt32 propSize = sizeof(inputasbd); 
[Utilities checkError:AudioUnitGetProperty(self.info->rioUnit, 
              kAudioUnitProperty_StreamFormat, 
              kAudioUnitScope_Input, 
              1, 
              &inputasbd, 
              &propSize) 
      operation:"Failed to get stream format of microphone input scope"]; 

// Output ASBD 
AudioStreamBasicDescription outputasbd; 
UInt32 typeByteSize = sizeof(float); 
outputasbd.mBitsPerChannel = 8 * typeByteSize; 
outputasbd.mChannelsPerFrame = 1; 
outputasbd.mBytesPerFrame = typeByteSize * outputasbd.mChannelsPerFrame; 
outputasbd.mFormatFlags  = kAudioFormatFlagIsFloat | kAudioFormatFlagIsNonInterleaved; 
outputasbd.mFormatID   = kAudioFormatLinearPCM; 
outputasbd.mFramesPerPacket = 1; 
outputasbd.mBytesPerPacket = outputasbd.mFramesPerPacket * outputasbd.mBytesPerFrame; 
outputasbd.mSampleRate  = inputasbd.mSampleRate; 

// Set stream format to output scope of input bus 
[Utilities checkError:AudioUnitSetProperty (self.info->rioUnit, 
              kAudioUnitProperty_StreamFormat, 
              kAudioUnitScope_Output, 
              1, 
              &inputasbd, 
              sizeof (AudioStreamBasicDescription)) 
      operation: "Couldn't set ASBD for RIO on output scope/bus 1"]; 

// Set format on inputscope of output bus 
[Utilities checkError:AudioUnitSetProperty(self.info->rioUnit, 
              kAudioUnitProperty_StreamFormat, 
              kAudioUnitScope_Input, 
              0, 
              &outputasbd, 
              sizeof(AudioStreamBasicDescription)) 
      operation: "Couldn't set ASBD for RIO on input scope/bus 0"]; 


// Start AUGraph 
[Utilities checkError:AUGraphStart(self.info->mGraph) 
     operation: "Couldn't start AUGraph"]; 

을하지만 불행히도 AU 그래프는이 코드 (OSStatus -10863)로 시작할 수 없습니다. AUGraphConnectNodeInput 메서드를 주석 처리하여 필터를 제거하거나 remoteIO AU를 사용하면 오디오가 문제없이 마이크에서 스피커로 직접 재생됩니다.

아무에게도 구성을 잘못했는지 힌트를 줄 수 있습니까? kAudioUnitSubType_LowPassFilter?

+0

"kAudioUnitSubType_LowPassFilter"를 구성하는 데 "뭔가 잘못 했어요"에 대한 개념은 무엇입니까? 그것에 대해 당신은 무엇을 확신합니까? 다른 하위 유형의 단위를 연결하려 했습니까? – user3078414

+0

사실 나는 문제가 어디에 있는지 정확히 알지 못했다. 나는 또한 그래프에'kAudioUnitSubType_MultiChannelMixer'를 넣으려고했지만 (마이크로부터 하나의 입력만으로), 동일한 에러 코드를 받는다. – Taco

+0

'OSStatus -10863 = kAudioToolboxErr_CannotDoInCurrentContext'. 렌더링 콜백에 문제가있어'remoteIO' AU를 play-through 설정에 넣는 것처럼 보입니다. 'AUGraphConnectNodeInput()'연결을 만들 때 주석 처리를 해보고 어떤 일이 일어나는지 살펴 보시겠습니까? – user3078414

답변

0

EDIT 2 :

ASBD를 스테레오로 변경하십시오. 필터가 필요합니다.

AUGraphConnectNodeInput(self.info->mGraph, rioNode, 1, lpfNode, 1)AUGraphConnectNodeInput(self.info->mGraph, rioNode, 1, lpfNode, 0)으로 생각됩니다. inDestInputNumber 인수는 본질적으로 입력 버스이며 필터는 단지 하나의 버스를가집니다. 따라서 인수는 버스 0이어야합니다. 그래도 문제가 해결되지 않으면 setStreamFormatWithInputASBD 방법 (관련이있는 경우)에서 진행중인 작업을 게시하십시오. 어느 쪽이든, 나는 일반적으로 모든 출력 ASBD를 연결된 장치의 입력과 일치하도록 명시 적으로 설정합니다.

주어 이런 그래프 inUnit-> unitA-> unitB-> outUnit이 패턴을 사용하여 설정 ASBDs (ASBD위한 audioUnitGetProperty 대한 의사 코드 및 setProperty는)

unitB.outputASBD = outUnit.inputASBD; 
unitA.outputASBD = unitB.inputASBD; 
inUnit.outputASBD = unitA.inputASBD; 

때때로이 ISN ' 필요하지만 때로는 그렇습니다! 대부분의 필터는 필수 스테레오 플로트 ASBD를 입력으로 사용합니다.

+0

불행히도 iOS에서는 작동하지 않지만 OSX CoreAudio API에 익숙합니다. RemoteIO는 iOS 전용이며 API는 Mac의 HAL AU, @Dave와 유사합니다. 렌더링 콜백은 입력 및 출력 버스 간의 연결을 정의하는 play-through 구성을 담당하지만 입력 콜백은 아마도 관계없는 것일 수 있습니다. 그러나 RemoteIO AU의 입력 버스 사이에 또 ​​다른 AU를 연결하면 이러한 방식으로 등록 된 렌더 콜백은 아무런 도움이되지 않을 수 있습니다. AUGraph에는 API를 깨지 않는 콜백을 등록하는 다른 메커니즘이 있습니다. – user3078414

+0

계속해서 inSourceInputNumber와 inDestInputNumber는 입력 채널이고, 필터는 하나의 채널을 가지고 있습니다. @, @Dave. 이것들은 노드 번호가 인 _ 버스 번호이며 스트림 형식의 프레임 당 _audio_ 채널 수와 혼동되어서는 안됩니다. (- : – user3078414

+0

나는 버스 번호를 변경하려고 시도했지만 오류 코드는 변경되지 않았다. user3078414의 의견과 관련하여 나는 이것이 정확하다고 가정했다. 또한 ASBD를 사용하여 질문을 편집했다. callback 필자는 FIR 필터링을 포함한 여러 가지 분석을 수행하고 순환 버퍼에 오디오를 넣은 다음 녹음을 수행 할 수 있습니다. 버퍼에서 오디오를 렌더링하고 오디오를 재생 및 플롯하기 위해 렌더링 콜백을 사용합니다. – Taco