2015-12-06 51 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

相关问题