AVAudioConverter.convertToBuffer выбрасывает код ошибки -50

Мне нужно преобразовать файл.wav, записанный с 2 ​​аудиоканалами, в формат.wav, который имеет только 1 канал, а также уменьшить глубину в битах с 32 до 16. Я пытался использовать AVAudioConverter.convertToBuffer Однако преобразование выдает ошибку: Error Domain=NSOSStatusErrorDomain Code=-50 "(null)"

По сути, единственное, что действительно нужно изменить, - это обрезать звук до одного канала и глубины в битах. Я получаю эти файлы из другого инструмента, поэтому я не могу просто изменить способ записи файлов.

Я не так хорош в работе со звуком, и я немного озадачен. Код, над которым я работаю, приведен ниже - я что-то упускаю?

let inAudioFileURL:NSURL = <url_to_wav_file>

var inAudioFile:AVAudioFile?
do
{
    inAudioFile = try AVAudioFile(forReading: inAudioFileURL)
}
catch let error
{
    print ("error: \(error)")
}

let inAudioFormat:AVAudioFormat = inAudioFile!.processingFormat
let inFrameCount:UInt32 = UInt32(inAudioFile!.length)

let inAudioBuffer:AVAudioPCMBuffer = AVAudioPCMBuffer(PCMFormat: inAudioFormat, frameCapacity: inFrameCount)

do
{
    try inAudioFile!.readIntoBuffer(inAudioBuffer)
}
catch let error
{
    print ("readError: \(error)")
}

let startFormat:AVAudioFormat = AVAudioFormat.init(settings: inAudioFile!.processingFormat.settings)
print ("startFormat: \(startFormat.settings)")

var endFormatSettings = startFormat.settings
endFormatSettings[AVLinearPCMBitDepthKey] = 16
endFormatSettings[AVNumberOfChannelsKey] = 1
endFormatSettings[AVEncoderAudioQualityKey] = AVAudioQuality.Medium.rawValue
print ("endFormatSettings: \(endFormatSettings)")


let endFormat:AVAudioFormat = AVAudioFormat.init(settings: endFormatSettings)
let outBuffer = AVAudioPCMBuffer(PCMFormat: endFormat, frameCapacity: inFrameCount)

let avConverter:AVAudioConverter = AVAudioConverter.init(fromFormat: startFormat, toFormat: endFormat)

do
{
    try avConverter.convertToBuffer(outBuffer, fromBuffer: inAudioBuffer)
}
catch let error
{
    print ("avconverterError: \(error)")
}

Что касается вывода:

startFormat: 
  ["AVSampleRateKey": 16000,
  "AVLinearPCMBitDepthKey": 32,
  "AVLinearPCMIsFloatKey": 1,
  "AVNumberOfChannelsKey": 2,
  "AVFormatIDKey": 1819304813,
  "AVLinearPCMIsNonInterleaved": 0,
  "AVLinearPCMIsBigEndianKey": 0]

endFormatSettings:
["AVSampleRateKey": 16000,
"AVLinearPCMBitDepthKey": 16,
"AVLinearPCMIsFloatKey": 1,
"AVNumberOfChannelsKey": 1,
"AVFormatIDKey": 1819304813,
"AVLinearPCMIsNonInterleaved": 0,
"AVLinearPCMIsBigEndianKey": 0,
"AVEncoderQualityKey": 64]

avconverterError: Error Domain=NSOSStatusErrorDomain Code=-50 "(null)"

1 ответ

Решение

Я не уверен на 100%, почему это так, но я нашел решение, которое помогло мне в этом, так что вот как я понимаю проблему. Я нашел это решение, пытаясь использовать альтернативный convert(to:error:withInputFrom:) метод. Использование этого дало мне другую ошибку:

`ERROR:    AVAudioConverter.mm:526: FillComplexProc: required condition is false: [impl->_inputBufferReceived.format isEqual: impl->_inputFormat]`

Проблема была вызвана в строке, где я настраиваю AVAudioConverter:

let avConverter:AVAudioConverter = AVAudioConverter.init(fromFormat: startFormat, toFormat: endFormat)

Похоже, что аудио конвертер хочет использовать тот же AVAudioFormat что используется входной буфер, вместо использования копии на основе настроек оригинала. Однажды я поменялся startFormat из за inAudioFormat, convert(to:error:withInputFrom:) ошибка была отклонена, и все работало как ожидалось. Затем я смог вернуться к использованию более простого convert(to:fromBuffer:) метод, и первоначальная ошибка, с которой я имел дело, также исчезла.

Напомним, что строка настройки конвертера теперь выглядит так:

let avConverter:AVAudioConverter = AVAudioConverter.init(fromFormat: inAudioFormat, toFormat: endFormat)

Что касается отсутствия документов о том, как использовать AVAudioConverterЯ понятия не имею, почему ссылка API не имеет ничего общего. Вместо этого в Xcode, CMD-клик на AVAudioConverter в вашем коде, чтобы перейти к его заголовочный файл. Там много комментариев и информации. Не полный пример кода или что-то, но это по крайней мере что-то.

Другие вопросы по тегам