5

AVAudioRecorder次の設定で を使用して、iPhone でオーディオを録音しています。

NSMutableDictionary *recordSettings = [[NSDictionary alloc] initWithObjectsAndKeys:
       [NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
       [NSNumber numberWithFloat:44100.0], AVSampleRateKey,
       [NSNumber numberWithInt:1], AVNumberOfChannelsKey,
       [NSNumber numberWithInt:12800], AVEncoderBitRateKey,
       [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
       [NSNumber numberWithInt: AVAudioQualityHigh],  AVEncoderAudioQualityKey,
       nil];

(これらの設定のほとんどは柔軟に対応できますが、MPEG4 AAC を使用する必要があります。)

オーディオをファイルに保存します。

ユーザーは後日戻ってきて、同じファイルへの記録を続行できる必要があります。これを で直接行うオプションはないようですAVAudioRecorder。代わりに、新しいファイルに記録してそれらを連結しています。

現時点では、 anAVMutableCompositionと anAVMutableCompositionTrackを使用してファイルを追加していますが、長時間の録音では非常に遅いため、これは実際には実現可能ではありません。

2 番目のファイルからヘッダーを削除し、オーディオ データを最初のファイルに追加し、結合されたファイルのヘッダーを変更して新しいデュレーションを反映できれば、はるかに速くなると思います。両方のファイルがまったく同じ設定で作成されていることがわかっているので、ヘッダーの他の詳細は同じであるはずです。

残念ながら、ヘッダーの形式や、この方法でファイルを結合できるかどうかについての情報は見つかりません。

だから私の質問は:

  • iPhone で作成された MPEG-4 AAC ファイル ヘッダーの形式は何ですか?
  • このようにヘッダーをいじって、2 つのオーディオ ファイルを結合することはできますか?
  • 2 つの MPEG-4 AAC オーディオ ファイルをほぼ瞬時に追加するより良い方法はありますか?
4

2 に答える 2

3

MPEG4-AAC形式で録音するように依頼しAVAudioRecorderますが、常に.caf(Core Audio Format)ファイルを生成します。ただし、これは単なるラッパー形式であり、含まれる実際のオーディオデータはAAC形式です。

結局、ファイルの追加は、.cafファイルをバイトごとに操作することになりました。CoreAudioFormatファイルの仕様はこちらです。このドキュメントを消化し、それに応じてファイルを処理することは、最初は少し不快でしたが、仕様が非常に明確で完全であることが判明したので、それほど面倒ではありませんでした。

仕様で説明されているように、.cafファイルは、先頭に4バイトの名前が付いたチャンクで構成されています。AACファイルの場合、常にdescチャンクとkukiチャンクがあります。2つの元のファイルが同じ形式であることがわかっているので、これらのチャンクを変更せずに出力ファイルにコピーできます。

paktチャンクとチャンクもありdataます。これらが入力ファイル内でどの順序になるかを保証することはできません。チャンクがある場合とない場合がありますfreeが、これには0x00のパディングが含まれているだけなので、これを出力ファイルにコピーする必要はありません。

チャンクを結合するにはpakt、チャンクヘッダーを調べて、フィールドが入力ファイル内のそれらの合計である新しいpaktチャンクを生成する必要があります。およびは常にゼロです。これらはストリーミングメディアにのみ関連します。チャンクの大部分(つまり、実際のパケットテーブルデータ)は連結することができます。mNumberPacketsmNumberValidFramesmPrimingFramesmRemainderFramespakt

dataチャンクについても同様です。mChunkSizeフィールドを合計してから、データの大部分を連結する必要があります。

これらのファイル内のすべての2進数フィールドからデータを読み取るときは注意してください。ファイルはビッグエンディアンですが、iPhoneはリトルエンディアンです。

追加のクレジットとして、ファイル内からオーディオのセグメントを削除したり、あるオーディオファイルを別のファイルの途中に挿入したりすることも検討してください。paktチャンクの内容を解析する必要があるため、これは少し注意が必要です。ここでも、仕様に従っている場合です。パケットサイズが可変長整数でどのように格納されるかについての適切な説明があるため、これらを解析して、各パケットがdataチャンクで占めるバイト数を見つけ、それらを計算する必要があります。それに応じて配置します。

全体として、これは私が望んでいたよりもかなり面倒です。たぶん、あなたのためにこれをすべて行うオープンソースライブラリがあるかもしれませんが、私はそれを見つけることができませんでした。

ただし、このようなrawファイルの処理は、元の質問のように使用する場合に比べて目がくらむほど速くAVMutableCompositionなりAVMutableCompositionTrackます。1時間の録音を同じ長さの別の録音に挿入するには、約2秒かかります。

幸運を!

于 2011-03-21T09:58:09.340 に答える
1

実装がはるかに高速な方法を見つけました:

  1. AVAudioRecorder を使用し、一時ファイルに拡張子「m4a」を使用します。ただし、必要に応じて「caf」を使用することもできますが、不要です。

  2. ここのコードを変更して、 AVAssetExportPresetPassthrough と exportSession.outputFileType = AVFileTypeQuickTimeMovie およびファイル名「audioJoined.mov」を使用します。新しく記録した一時 m4a と既存の m4a ファイルを使用します。これにより、瞬時に結合され (再圧縮なし)、「mov」が生成されます。

ノート。残念ながら、AVAudioPlayer は「mov」を再生できないため、次のステップは再生可能なものに変換することです。ただし、どこかでファイルを共有するだけの場合は、次のステップをスキップする可能性があります。これは、mov が Mac の Quicktime で完全に再生できるためです。また、iTunes で再生したり、iPhone に同期したり、iPod アプリで再生したりすることもできます。

  1. [[AVAssetExportSession alloc] initWithAsset:movFileAsset presetName:AVAssetExportPresetAppleM4A]、ファイル名に @"audioJoined.m4a"、および exportSession.outputFileType = AVFileTypeAppleM4A を使用して、mov を m4a に変換して戻します。繰り返しますが、これはインスタントです。この状況では、AVMutableComposition アセットではなく mov アセットで開始する場合、エクスポーターがよりスマートになると思います。

私は、録音が停止されてファイルが再生された後、またはアプリが再起動された場合でも、録音を再開できるアプリでこの手法を使用しています。

于 2011-06-09T01:32:21.293 に答える