2016-09-14 116 views
0

我需要轉換記錄有2個聲道到僅具有1個通道,以及降低的位深度從32到16,我已經一個.wav .wav文件試圖使用AVAudioConverter.convertToBuffer但是,轉換出現了一個錯誤:Error Domain=NSOSStatusErrorDomain Code=-50 "(null)"AVAudioConverter.convertToBuffer投擲錯誤代碼-50

基本上,唯一真正需要更改的是將音頻拆分爲單個通道和位深度。我從一個不同的工具獲取這些文件,所以我不能只改變文件的記錄方式。

我不帶音頻的工作是真棒,我有點難倒。我正在處理的代碼如下 - 有什麼我失蹤?

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)" 

回答

2

我不是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:)錯誤,事情都按預期。然後,我能夠回到使用更簡單的方法,並且我正在處理的原始錯誤也消失了。

總括來說,該行現在設置轉換器的樣子:

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

至於缺乏關於如何使用AVAudioConverter文檔的,我不知道爲什麼API參考具有微乎其微。相反,在Xcode中,通過CMD在代碼中單擊AVAudioConverter以轉到它的頭文件。那裏有很多評論和信息。不是完整的示例代碼或任何東西,但它至少是某種東西。