AVAudioConverter портит данные
Я пытаюсь преобразовать
AVAudioPCMBuffer
от Float32 44,1 кГц до Int16 8 кГц. я использую
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 8 кГц с микрофона. Если кто-нибудь знает, как это сделать по-другому, я очень признателен за вашу помощь.
1 ответ
Аудиоконвертеры имеют внутреннее состояние. Создание одного преобразователя вместо одного при каждом вызове
convertBuffer
должен исправить проблему.