2017-01-05 55 views
3

我想实时录制iOS上的音频,分析原始音频数据并保存部分记录的数据。我正在用此代码记录数据:https://gist.github.com/hotpaw2/ba815fc23b5d642705f2b1dedfaf0107iOS Swift malloc错误

现在,我的数据保存在Float阵列中,并且我想将它保存到音频文件。我试着用这个代码做:

let fileMgr = FileManager.default 
    let dirPaths = fileMgr.urls(for: .documentDirectory, in: .userDomainMask) 
    let recordSettings = [AVEncoderAudioQualityKey: AVAudioQuality.min.rawValue, 
         AVEncoderBitRateKey: 16, 
         AVNumberOfChannelsKey: 2, 
         AVSampleRateKey: 44100] as [String: Any] 
    let soundFileUrl = dirPaths[0].appendingPathComponent("recording-" + getDate() + ".pcm") 


    do { 
     let audioFile = try AVAudioFile(forWriting: soundFileUrl, settings: recordSettings) 
     let format = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: 44100, channels: 2, interleaved: true) 

     let audioFileBuffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: 3000) 

     for i in 0..<circBuffer.count { 
      audioFileBuffer.int16ChannelData?.pointee[i] = Int16(circBuffer[i]) 
     } 

     try audioFile.write(from: audioFileBuffer) 

    } 

就上线,我得到它说的错误:

ERROR:> avae> AVAudioFile.mm:306: - [AVAudioFile writeFromBuffer:错误:] :error -50 amplitudeDemo(79264,0x70000f7cb000)malloc:*对象0x7fc5b9057e00错误:对于释放的对象错误的校验和 - 对象可能在释放后被修改。 *在malloc_error_break中设置一个断点来调试

我已经在很多其他问题中搜索过,但是我找不到任何帮助我的东西。

回答

1

在您的代码在这一行:

let audioFileBuffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: 3000) 

声明一个AVAudioPCMBuffer与容量3000层的帧* 2个信道,其用于您的audioFileBuffer可以包含6000个样品分配的缓冲区。如果通道数据的索引超过此限制,则代码将销毁堆中的邻近区域,这会导致对象可能被修改为错误。

因此,您的circBuffer.count可能会超出此限制。您需要分配足够的缓冲区大小,为AVAudioPCMBuffer

do { 
     //### You need to specify common format 
     let audioFile = try AVAudioFile(forWriting: soundFileUrl, settings: recordSettings, commonFormat: .pcmFormatInt16, interleaved: true) 

     let channels = 2 
     let format = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: 44100, channels: AVAudioChannelCount(channels), interleaved: true) 
     let audioFileBuffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: AVAudioFrameCount(circBuffer.count/channels)) //<-allocate enough frames 
     //### `stride` removed as it seems useless... 
     let int16ChannelData = audioFileBuffer.int16ChannelData! //<-cannot be nil for the `format` above 

     //When interleaved, channel data of AVAudioPCMBuffer is not as described in its doc: 
     // https://developer.apple.com/reference/avfoundation/avaudiopcmbuffer/1386212-floatchanneldata . 
     // The following code is modified to work with actual AVAudioPCMBuffer. 
     //Assuming `circBuffer` as 
     // Interleaved, 2 channel, Float32 
     // Each sample is normalized to [-1.0, 1.0] (as usual floating point audio format) 
     for i in 0..<circBuffer.count { 
      int16ChannelData[0][i] = Int16(circBuffer[i] * Float(Int16.max)) 
     } 
     //You need to update `frameLength` of the `AVAudioPCMBuffer`. 
     audioFileBuffer.frameLength = AVAudioFrameCount(circBuffer.count/channels) 

     try audioFile.write(from: audioFileBuffer) 

    } catch { 
     print("Error", error) 
    } 

一些笔记添加为注释,请在尝试此代码之前检查它们。


UPDATE 对不起,显示未测试的代码,有两点固定:

  • 您需要实例AVAudioFile时指定commonFormat:
  • int16ChannelData(以及其他通道数据)不会按照其文档中所述在交错时返回预期的指针,数据填充循环修改为适合实际行为。

请尝试。

+0

谢谢,这帮助了很多。但仍然,生成的音频文件是空的,我得到的错误:“错误:> avae> AVAudioFile.mm:306: - [AVAudioFile writeFromBuffer:error:]:error -50”任何想法,为什么会发生这种情况? – user7310287

+0

@ user7310287,对不起,我应该检查我的代码多一点,我只是检查写入缓冲区不会导致崩溃。但没有检查实际写入文件是否成功。现在检查实际的iOS行为,请取消选中接受标记直到找到修复程序。 – OOPer

1

您似乎已经选择frameCapacity任意3000

它设置为实际的样本数:

let audioFileBuffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: AVAudioFrameCount(circBuffer.count))