2016-06-16 16 views
1

Я пытаюсь добавить kAudioUnitSubType_LowPassFilter в AUGraph, но этого не добиться.Как добавить 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 Graph не может начинаться с этим кодом (OSStatus -10863). Когда я удаляю фильтр, комментируя методы AUGraphConnectNodeInput или используя remoteIO AU, непосредственно звук воспроизводится с микрофона на динамик без проблем.

Может кто-нибудь дать мне намек, что я делаю неправильно с настройкой kAudioUnitSubType_LowPassFilter?

+0

Что ваша концепция о «сделав что-то неправильно с настройкой» 'kAudioUnitSubType_LowPassFilter'? Что вы в этом уверены? Вы пытались подключить единицу другого подтипа? – user3078414

+0

На самом деле я имел в виду, что я действительно не знаю, где проблема. Я также попытался поместить на график 'kAudioUnitSubType_MultiChannelMixer' (только с одним входом от микрофона), но я получаю тот же код ошибки. – Taco

+0

'OSStatus -10863 = kAudioToolboxErr_CannotDoInCurrentContext'. Проблема может быть в обратном вызове рендеринга, который, по-видимому, помещает 'remoteIO' AU в конфигурацию воспроизведения. Попробуйте прокомментировать это, когда вы подключаете '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, используя этот шаблон:

(псевдо код для audioUnitGetProperty и SetProperty для ASBD)

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

Иногда это ISN» необходимо, но иногда это так! Большинство фильтров принимают обязательный стереопоток ASBD в качестве входных данных.

+0

К сожалению, я не работаю в iOS, но я знаком с API OSX CoreAudio. RemoteIO AU является специфичным для iOS, и его API похож на HAL AU на mac, @Dave. Обратный вызов render отвечает за конфигурацию воспроизведения, определяя соединение между шинами ввода и вывода, в то время как обратный вызов может быть посторонним. Однако, если вы подключаете другой AU между входными шинами RemoteIO AU, вполне вероятно, что обратный вызов визуализации, зарегистрированный таким образом, не имеет никакой цели. Существуют и другие механизмы регистрации обратных вызовов в AUGraph, которые не нарушают API. – user3078414

+0

Далее вы не указали _not exact_ about 'inSoruceInputNumber' и' inDestInputNumber', который является «по существу входным каналом, а фильтры имеют только один канал», @Dave. Это - номера шин узлов_ и не следует путать с количеством _audio_ каналов на кадр в формате потока. (-: – user3078414

+0

Хотя я также пытался изменить номера шин, он не изменил код ошибки. Что касается комментария пользователя3078414, я предполагаю, что это было правильно. Кроме того, я отредактировал свой вопрос с помощью ASBD, который я использовал для ясности. callback Я выполняю несколько анализов (включая фильтрацию FIR), помещаю аудио в круговой буфер, и запись может быть выполнена. Я использую обратный вызов рендеринга для рендеринга звука из буфера, а также для воспроизведения и построения звука. – Taco