2015-12-06 80 views
5

我正在創建一個用於將聲音寫入聲音文件的AVAudioFile。如果文件已經存在,我想將framePosition移動到文件末尾,繼續在末尾寫入,而不是替換現有的文件。即使文件存在,AVAudioFile.length也爲0

我做了一些測試,試圖從文件讀取緩衝區到一個新的文件,使用不同的URL,以便它不會覆蓋原始文件。我收到的時候我試圖讀取緩衝區到新文件崩潰:

let audioFile = try AVAudioFile(forReading: [URL to existing .caf file]) 
let audioFrameCount = AVAudioFrameCount(UInt32(audioFile.length)) 
let audioBuffer = AVAudioPCMBuffer(PCMFormat: audioFile.processingFormat, frameCapacity: audioFrameCount) 

let newAudioFile = try AVAudioFile(forWriting: [another URL], settings: self.engine.mainMixerNode.outputFormatForBus(0).settings) 
try newAudioFile.readIntoBuffer(audioBuffer, frameCount: audioFrameCount!) <-- CRASHES ON THIS LINE 

崩潰日誌:終止應用程序由於未捕獲的異常「com.apple.coreaudio.avfaudio」,原因:'錯誤-50'

男人,我真的很討厭CoreAudio崩潰日誌。他們絕對沒有告訴我!

是不是可以將數據讀入已創建的用於寫入的文件?

UPDATE

OK,所以一些建議後,我做了一些改變。基本上,這些是我正在採取的步驟:

  1. 檢查文件是否已經存在。
  2. 如果存在,打開它進行讀取並獲取音頻緩衝區。
  3. 創建寫入新文件(使用相同的文件URL)
  4. 使用writeFromBuffer從舊文件中的緩衝區寫入新文件
  5. 將新的文件到最後的framePosition,讓我可以繼續寫入/記錄。

但是,在寫入它之後,新文件的長度爲0。

這裏是我的代碼:

//Check if a file already exists. If so continue to record at the end of it 
var audioBuffer : AVAudioPCMBuffer! 
var audioFrameCount : AVAudioFrameCount! 
if (NSFileManager.defaultManager().fileExistsAtPath(self.audioRecordURL.path!)) { 
    do { 
     let existingAudioFile = try AVAudioFile(forReading: self.audioRecordURL) 
     audioFrameCount = AVAudioFrameCount(existingAudioFile.length) 
     if (audioFrameCount > 0) { 
      audioBuffer = AVAudioPCMBuffer(PCMFormat: existingAudioFile.processingFormat, frameCapacity: audioFrameCount) 
     } 
    } catch let error as NSError { 
     NSLog("Error reading buffer from file %@", error.localizedDescription) 
    } 
} 

//Create a new file. This will replace the old file 
do { 
    self.audioFile = try AVAudioFile(forWriting: self.audioRecordURL, settings: self.engine.mainMixerNode.outputFormatForBus(0).settings) 
} catch let error as NSError { 
    NSLog("Error creating AVAudioFile %@", error.localizedDescription) 
} 

//Read the audio buffer from the old file into the new file 
if (audioBuffer != nil) { 
    do { 
     try self.audioFile.writeFromBuffer(audioBuffer) 
     self.audioFile.framePosition = self.audioFile.length 
    } catch let error as NSError { 
     NSLog("Error reading buffer into file %@", error.localizedDescription) 
    } 
} 

順便說一句,在readIntoBuffer的命名極爲混亂給我。聽起來好像您應該使用該方法將文件讀入緩衝區,但根據文檔,您應該使用它來將緩衝區讀入文件中?那麼,爲什麼我不能使用該方法將緩衝區添加到我的文件中?爲什麼我必須使用writeFromBuffer?

更新2

所以,我設法解決這個問題。顯然我必須調用readIntoBuffer才能使用它,然後用數據填充緩衝區。所以我說這行

try existingAudioFile.readIntoBuffer(audioBuffer) 

audioBuffer = AVAudioPCMBuffer(PCMFormat: existingAudioFile.processingFormat, frameCapacity: audioFrameCount) 
+0

'-50'通常是一個參數錯誤。 'audioFrameCount'背後的'!'真的有必要嗎? 'audioFrameCount'有一個有效的值嗎? – hendrik

+0

我刪除了! (不知道我爲什麼那裏)。是的,audioFrameCount具有有效值。 – andlin

+0

而你仍然是-50?要麼從打開的文件中讀取文件是不可能的,要麼您的設置與音頻緩衝區格式不匹配。爲什麼不先打開文件進行閱讀,閱讀,關閉文件,然後打開文件以解決此問題? – hendrik

回答

1

不知道這僅僅是您所提供的代碼輸入錯誤後,我在這方面的專家,但據推測你的意思是有崩潰是行:

try audioFile.readIntoBuffer(audioBuffer, frameCount: audioFrameCount!) 

,因爲按理說,從文件打開寫(newAudioFile),你可以不讀。

然後填充該緩衝區後,你會想寫信給使用writeFromBuffer https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioFile_Class/#//apple_ref/occ/instm/AVAudioFile/writeFromBuffer:error新文件:

+0

我想從我的舊音頻文件添加緩衝區到我新創建的緩衝區(然後繼續錄製到最後)。我應該使用writeFromBuffer嗎?這樣做我不會崩潰,寫入後我的音頻文件長度爲0。我會用更多信息更新我的問題 – andlin

+0

感謝您幫助我解決這個問題。我沒有意識到,在使用緩衝區之前,我必須調用readIntoBuffer實際上使用舊文件中的數據填充緩衝區。 readIntoBuffer的文檔聲明「從中讀取文件的緩衝區」。對我而言,這聽起來和它實際上的完全相反。 – andlin

相關問題