AVAudioEngine 下采样问题

nul*_*ife 5 audio core-audio swift avaudioengine swift3

我在对从麦克风中提取的音频进行下采样时遇到问题。我正在使用 AVAudioEngine 通过以下代码从麦克风中获取样本:

assert(self.engine.inputNode != nil)
let input = self.engine.inputNode!

let audioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 8000, channels: 1, interleaved: false)    
let mixer = AVAudioMixerNode()
engine.attach(mixer)
engine.connect(input, to: mixer, format: input.inputFormat(forBus: 0))

do {
    try engine.start()

    mixer.installTap(onBus: 0, bufferSize: 1024, format: audioFormat, block: {
            (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
        //some code here
    })

} catch let error {
    print(error.localizedDescription)
}
Run Code Online (Sandbox Code Playgroud)

此代码在 iPhone 5s 上运行良好,因为麦克风输入为 8000Hz,并且缓冲区填充了来自麦克风的数据。

问题是我希望能够从 iPhone 6s(及更高版本)录制麦克风以 16000Hz 录制的内容。奇怪的是,如果我将 mixernode 与引擎 mainmixernode 连接起来(使用以下代码):

engine.connect(mixer, to: mainMixer, format: audioFormat)
Run Code Online (Sandbox Code Playgroud)

这实际上是有效的,我得到的缓冲区的格式为 8000Hz,声音完全降采样,唯一的问题是声音也从我不想要的扬声器发出(如果我不连接它缓冲区为空)。

有谁知道如何解决这个问题?

非常感谢任何帮助、输入或想法。

den*_*T30 8

另一种方法是使用AVAudioConverterSwift 5

let engine = AVAudioEngine()


func setup() {

    let input = engine.inputNode
    let bus = 0
    let inputFormat = input.outputFormat(forBus: bus )
    guard let outputFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 8000, channels: 1, interleaved: true), let converter = AVAudioConverter(from: inputFormat, to: outputFormat) else{
        return
    }

    input.installTap(onBus: bus, bufferSize: 1024, format: inputFormat) { (buffer, time) -> Void in
        var newBufferAvailable = true

        let inputCallback: AVAudioConverterInputBlock = { inNumPackets, outStatus in
            if newBufferAvailable {
                outStatus.pointee = .haveData
                newBufferAvailable = false
                return buffer
            } else {
                outStatus.pointee = .noDataNow
                return nil
            }
        }

        if let convertedBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: AVAudioFrameCount(outputFormat.sampleRate) * buffer.frameLength / AVAudioFrameCount(buffer.format.sampleRate)){
            var error: NSError?
            let status = converter.convert(to: convertedBuffer, error: &error, withInputFrom: inputCallback)
            assert(status != .error)

            // 8kHz buffers
            print(convertedBuffer.format)
        }
    }
    do {
        try engine.start()
    } catch { print(error) }
}
Run Code Online (Sandbox Code Playgroud)