2017-01-05 10 views
3

リアルタイムでiOSにオーディオを録音し、生のオーディオデータを分析し、記録されたデータの一部を保存します。 https://gist.github.com/hotpaw2/ba815fc23b5d642705f2b1dedfaf0107iOS Swift mallocエラー

私のデータはフロートアレイに保存され、オーディオファイルに保存したいと思います。 [AVAudioFile writeFromBuffer:エラー:] - :私はこのコードでそれをやってみました:

ERROR:> avae> AVAudioFile.mm:306最後の行に

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) 

    } 

、私が言うエラーが出ます:-50 amplitudeDemo(79264,0x70000f7cb000)malloc:*オブジェクトのエラー0x7fc5b9057e00:解放されたオブジェクトのチェックサムが正しくありません。オブジェクトは解放された後に変更されている可能性があります。 *は、デバッグするためにmalloc_error_breakにブレークポイントを設定しました

私は既に他の多くの質問を検索しましたが、何か助けになるものは見つかりませんでした。この行では、あなたのコードで

答えて

1

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

あなたのaudioFileBuffer 6000個のサンプルを含めることができるために割り当てられたバッファを意味* 2つのチャンネル容量3000のフレーム、とAVAudioPCMBufferを宣言します。チャネルデータのインデックスがこの制限を超えると、ヒープ内の近くの領域がコードによって破棄され、オブジェクトがおそらく変更されたというエラーが発生します。

だから、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) 
    } 

このコードを試す前に、コメントとしてコメントを追加してください。


、固定された2つのことをテストされていないコードを示すため、 申し訳ありませんUPDATE:

  • あなたはAVAudioFileをインスタンス化するときcommonFormat:を指定する必要があります。
  • int16ChannelData(およびその他のチャネルデータ)は、インターリーブされたときにそのドキュメントに記載されているように予想されるポインタを返さないため、実際の動作に合わせてデータ充填ループが変更されます。

お試しください。

+0

が、これは多くのことを助け、ありがとうございます。しかし、まだ生成されたオーディオファイルは空であり、エラーが発生します: "エラー:> avae> AVAudioFile.mm:306: - [AVAudioFile writeFromBuffer:error:]:エラー-50" – user7310287

+0

@ user7310287、申し訳ありませんが、私はもう少し私のコードをチェックすべきです、私はちょうどバッファにクラッシュを引き起こさない書き込みをチェックしています。しかし、ファイルへの実際の書き込みでチェックされず、成功するかどうか。実際のiOSの動作を確認したら、「修正が見つかるまで署名を受け入れる」のチェックを外してください。 – OOPer

1

frameCapacityを任意に3000に設定したようです。

実際のサンプル数に設定し、それを:

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