【发布时间】:2020-10-26 07:47:53
【问题描述】:
我有一些现有代码使用AVAudioEngine 从麦克风获取输入,对其进行下采样并将其写入AVAudioFile
internal func setupNodeChain() {
guard let audioEngine = audioEngine else { return } // Fatal error ?
let engineInputNode = audioEngine.inputNode
let bus = 0
let engineInputNodeFormat = engineInputNode.outputFormat(forBus: bus)
// This attempts to down sample the audio from the microphone
let downSampleMixerNode = AVAudioMixerNode()
let mixerOutputFormat = AVAudioFormat(standardFormatWithSampleRate: 8000, channels: 1)
// Input -> (volume) -> down sample -> (volume) -> Output
let inputVolumeMixerNode = AVAudioMixerNode()
inputVolumeMixerNode.volume = Float(10 * microphoneVolume)
audioEngine.attach(inputVolumeMixerNode)
audioEngine.attach(downSampleMixerNode)
self.downSampleMixerNode = downSampleMixerNode
self.inputVolumeMixerNode = inputVolumeMixerNode
let silenceNode = AVAudioMixerNode()
silenceNode.outputVolume = 0
self.silenceNode = silenceNode
audioEngine.connect(engineInputNode, to: inputVolumeMixerNode, format: engineInputNodeFormat)
audioEngine.connect(inputVolumeMixerNode, to: downSampleMixerNode, format: engineInputNodeFormat)
// Try and stop the microphone audio from going through to the speaker
audioEngine.attach(silenceNode)
audioEngine.connect(downSampleMixerNode, to: silenceNode, format: mixerOutputFormat)
audioEngine.connect(silenceNode, to: audioEngine.outputNode, format: mixerOutputFormat)
downSampleMixerNode.installTap(onBus: bus, bufferSize: 1024 * 16, format: mixerOutputFormat) { (buffer: AVAudioPCMBuffer, time: AVAudioTime) in
guard let tap = self.audioTap else { return }
// Write buffer to AVAudioFile
tap.drip(buffer: buffer, time: time)
}
}
这主要是可行的,但我正在研究用AudioKit 替换它,但我遇到了问题,我不知道如何创建一种机制来对从麦克风到录音机的音频进行下采样。
AKSettings.enableEchoCancellation = true
AKSettings.allowAirPlay = true
AKSettings.useBluetooth = true
do {
try AKSettings.setSession(category: .playAndRecord,
with: [
.allowBluetoothA2DP,
])
AKSettings.defaultToSpeaker = true
let audioFile = try self.makeAudioFile(named: "Recording")
let mixerOutputFormat = AVAudioFormat(standardFormatWithSampleRate: 8000, channels: 1)!
let microphone = AKMicrophone()
let microphoneBooster = AKBooster(microphone)
microphoneBooster.gain = 0
let recorder = try AKNodeRecorder(node: microphoneBooster)
//recorder.recordFormat = mixerOutputFormat
let silence = AKMixer(microphoneBooster)
silence.volume = 0
self.microphone = microphone
self.microphoneBooster = microphoneBooster
self.recorder = recorder
self.silence = silence
AKManager.output = silence
log(debug: "Start")
try AKManager.start()
log(debug: "Record")
try recorder.record()
DispatchQueue.main.async {
self.state = .recording
self.plot?.node = microphone
self.callButton.setImage(#imageLiteral(resourceName: "EndCall"), for: [])
}
} catch let error {
log(error: "Failed to establish play and record session: \(error)")
}
所以,问题是 - 我将如何创建“下采样”节点/工作流程,它将麦克风链接到具有“默认”格式的“节点”,然后将“节点”链接到下一个需要AVAudioFormat的链中的节点?
麦克风 -> 向下采样(默认格式)
下采样->下一个节点(目标格式)->记录器
【问题讨论】:
-
你有什么运气吗?我想做类似的事情。
-
@BrodyRobertson 我最终会编写自己的“节点分接器”来完成这项工作
-
@BrodyRobertson 我添加了一个“自我回答”,主要强调了我最终必须做些什么才能让它为我工作
-
感谢您发布您的解决方案。这很有帮助,尤其是 AVAudioConverter 实现。
-
我决定使用 AudioKit 5 并创建了一个扩展 BaseTap 的 ResampleDataTap,我在其中添加了 AVAudioConverter impl。完成后我会发布我的解决方案。
标签: swift audiokit avaudioengine