0

我正在尝试AVAudioPCMBuffer从 Float32 44.1kHz 转换为 Int16 8kHz。我用AVAudioConverter. 但转换后我得到损坏的数据。当我每 100 毫秒从麦克风读取数据时,我每 800 个样本被破坏(读取数据中的第一个样本)。破损样本如下所示: 破损样本

这只是 800 个样本中的一个,但听起来每 100 毫秒的点击真的很烦人。这是我的一段代码:

...
    let outputFormat = AVAudioFormat(commonFormat: .pcmFormatInt16,
                                     sampleRate: 8000,
                                     channels: 1,
                                     interleaved: false)!
    let input = self.engine.inputNode
    let bus = 0
    let inputFormat = input.outputFormat(forBus: bus)
        
    let bufferSize = inputFormat.sampleRate * 0.1 // Read every 100ms
        
    input.installTap(onBus: bus, bufferSize: UInt32(bufferSize), format: inputFormat) { (buffer, time) -> Void in
                
        let convertedBuffer = self.convertBuffer(buffer: buffer, from: inputFormat, to: outputFormat)
        if self.isRecording {
            self.inFile?.seekToEndOfFile()
            let data = Data(buffer: UnsafeBufferPointer(start: convertedBuffer.int16ChannelData![0], count: Int(convertedBuffer.frameLength)))
            self.inFile?.write(data)
        }
...

func convertBuffer(buffer: AVAudioPCMBuffer,
                   from inputFormat: AVAudioFormat,
                   to outputFormat: AVAudioFormat) -> AVAudioPCMBuffer {
        
    let converter = AVAudioConverter(from: inputFormat, to: outputFormat)!
        
    let inputCallback: AVAudioConverterInputBlock = { inNumPackets, outStatus in
        outStatus.pointee = .haveData
        return buffer
    }
        
    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)
        
    return convertedBuffer
}

当我在没有任何转换的情况下写入缓冲区时,我会得到清晰的声音而不会损坏。如果我每 200 毫秒读取一次数据,则每 1600 个样本都会被破坏。所以只有我得到的每个缓冲区的第一个样本被破坏了。

我真的不知道我的代码有什么问题以及为什么会这样。有什么错误吗?

PS 我并不真正关心转换,我只需要从麦克风获取 16 位 PCM 8kHz 原始音频数据。如果有人知道如何以另一种方式做到这一点,我将非常感谢您的帮助。

4

1 回答 1

1

音频转换器具有内部状态。在每次调用中创建一个转换器而不是一个转换器convertBuffer应该可以解决该问题。

于 2020-10-28T11:50:24.860 回答