1.AVAudioEngine负责:
• 管理所有的音频节点(audio nodes)
• 连接所有的音频节点使其运作形成链条(active chains)
• 动态的获取(attach)和配置所有音频的节点。
• 开启和停止API
2.有多种node,负责实现不同的功能,而AVAudioEngine在运行中可以自由组合、拆卸node,node经由它们各自的输入被连接到下一级的输出,从而可以灵活实现想要的效果,但是AVAudioEngine在运行中不能拆卸(detach)inputNode和OutputNode,且disconectNodes(两个node)时,必须同时disconect掉前一个node的output和后一个node的input。由于没有发现这些细节,导致采用比较复杂的方式解决插扒耳机的问题以至于触发了新的问题。
3.AVAudioEngine实例化后默认有三个node,分别为inputNode、outputNode,这两个node不可以被detach,还有一个可选的mainMixerNode。
4.在使用AVAudioEngine时,inputNode、outputNode分别对应硬件的麦克风和扬声器,需要检查其采样率和声道数,若采样率为0,则不可用。
5.使用实例,实现录音+耳返+音乐,且耳返和录音结果中有混响效果:
inputNode(麦克风)
mixerNode(混音)–> reverbNode(混响)–> outputNode(输出)
playerNode(播放背景音乐)
// attach EngineNodes
self.input = self.engine.inputNode;// 输入
self.output = self.engine.outputNode;// 输出
[self.engine attachNode:self.reverb];// 混响
[self.engine attachNode:self.mixer];
[self.engine attachNode:self.player];
// make Engine Connections
[self.engine connect:self.player to:self.mixer fromBus:0 toBus:0 format:[file processingFormat]];
[self.engine connect:self.input to:self.mixer fromBus:0 toBus:1 format:[self.input inputFormatForBus:0]];
[self.engine connect:self.mixer to:self.reverb format:self.audioFormat];
[self.reverb installTapOnBus:0 bufferSize:8192 format:self.audioFormat block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
if (self->_isRecording) {// write buffer to file
[weakSelf.audioFile writeFromBuffer:buffer error:&writeBufferError];
weakSelf.currentRecTime += buffer.frameLength/when.sampleRate;
}
}];
[self.engine connect:self.reverb to:self.output format:self.audioFormat];
// start && play
[self.engine prepare];
[self.engine startAndReturnError:&startError];