1

内部にエンコードされた PCM オーディオを含む複数の CAF ファイルを結合できます。まず、CAF ファイルの 1 つからデータ形式を読み込みます。

UInt32 size = sizeof(srcFormatDescription);
        status = AudioFileGetProperty(srcAudioFile, kAudioFilePropertyDataFormat, &size, &srcFormatDescription);

PCMデータ形式の場合は次のようになります

[Line 7697] mSampleRate: 44100.000000
[Line 7698] mFormatID: 1819304813d
[Line 7699] mFormatFlags: 12d
[Line 7700] mBytesPerPacket: 2d
[Line 7701] mFramesPerPacket: 1d
[Line 7702] mBytesPerFrame: 2d
[Line 7703] mChannelsPerFrame: 1d
[Line 7704] mBitsPerChannel: 16d
[Line 7705] mReserved: 0d

次に、すべての CAF を含む宛先ファイルのデータ形式を設定します。

destFormatDescription = srcFormatDescription;
status = AudioFileCreateWithURL(dest, kAudioFileCAFType, &destFormatDescription, kAudioFileFlags_EraseFile, &destAudioFile);

次のステップでは、CAF からデータを読み取ります

status = AudioFileReadBytes(srcAudioFile,
                                    FALSE,
                                    currentStartForReading,
                                    &bytesNumberToRead,
                                    buffer);

destAudioFileに書き込みます

status = AudioFileWriteBytes(destAudioFile,
                                     FALSE,
                                     writePosition,
                                     &bytesNumberToWrite,
                                     buffer);

この手順はループで実行されます。それはうまくいきます。しかし、私は大きな問題を抱えています.ALAC形式のデータを含むCAFファイルに対して同じ手順を実行しようとしています. うまくいきません。AudioFileWriteBytes がエラーを返す操作はサポートされていません。

ALAC データ形式の場合は次のようになります

[Line 7697] mSampleRate: 44100.000000
[Line 7698] mFormatID: 1634492771d
[Line 7699] mFormatFlags: 1d
[Line 7700] mBytesPerPacket: 0d
[Line 7701] mFramesPerPacket: 4096d
[Line 7702] mBytesPerFrame: 0d
[Line 7703] mChannelsPerFrame: 1d
[Line 7704] mBitsPerChannel: 0d
[Line 7705] mReserved: 0d

内部に Apple Lossless データを含む複数の CAF ファイルを結合する方法を知っている人はいますか?

4

2 に答える 2

1

エンコードされたPCMオーディオを内部に持つ複数のCAFファイルを結合できます。まず、CAFファイルの1つからデータ形式を読み取ります。

ASBDが一致する場合、オーディオファイルは正しいでしょう。ただし、入力ファイルのサンプル形式が一致しない場合、データが破損する可能性があります。これは、各CAFファイルが正確に1つのサンプルデータチャンクと1つの音声ガイドチャンクを定義しているためです。

したがって、複数の形式のサンプルデータを1つのオーディオデータチャンクに追加しようとするとエラーになります。(それがあなたが試みているものであるかどうかは特定されていません)

さらに、圧縮形式には、設定する必要のある追加のフィールドがあります。これはマジッククッキーです。すべてのCookieは等しくなければなりません(これは不透明なデータ表現です、ところで)。

最後に、圧縮データを書き込む適切な方法は、パケットテーブルチャンクを使用することです。VBR / VFR形式では、パケットテーブルチャンクを1つだけ指定する必要があります。

Apple Losslessデータを含む複数のCAFファイルを結合する方法を知っている人はいますか?

これが意味すること:ALACの場合に選択したアプローチを使用すると、高い故障率が発生します。同様に、これらのファイルとそのチャンクを、関連するすべてのパケットの詳細と正しく同期させるために必要なことがたくさんあります。

それでは、別の角度からこれにアプローチしましょう。

  • ExtAudioFileCreateWithURL新しいALACファイルを作成するために使用します
  • ExtAudioFileOpenURL入力ファイルを開くために使用する
  • 入力ファイルから一般的なサンプル形式を決定します
  • ExtAudioFileSetProperty+を使用kExtAudioFileProperty_ClientDataFormatして一般的なPCM形式を指定します
  • 選択した一般的なPCM形式を想定するように、宛先/ALACファイルのコンバーターを構成します。
  • 入力ファイルのサンプルデータを読み取り、宛先に書き込みます
  • 残りのファイルについて繰り返します
  • すべてのファイルを閉じる

それはそれであるはずです(しかし、生のAudioFile APIを扱っている場合は、おそらく数百行のコードが必要になります)。

于 2012-08-27T07:31:53.157 に答える
0

なぜ、、、、を使用しようとしなかったAVAssetExportSessionAVMutableCompositionか疑問AVAssetに思っていますAVMutableCompositionTrack。以下の手順に従って、さまざまなオーディオ ファイルを結合/マージすることをお勧めします。

  1. URL を使用して各オーディオ ファイルを にロードしますAVAsset
  2. AVMutableComposition以下のコードを使用してオブジェクトを初期化します。

    AVMutableComposition* mixComposition = [[AVMutableComposition alloc] init];
    
  3. 以下のように、ミュータブル コンポジションにミュータブル オーディオ トラックを追加します。

    AVMutableCompositionTrack *AudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    
  4. 以下のようにアセットの時間範囲を追加AudioTrackします。

    [AudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, CMTimeAdd(firstAsset.duration, secondAsset.duration)) ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];
    
  5. AVAssetExportSessionコードの下にすべてのオーディオ ファイルを作成してマージします。

    // Prepare final exporter for merging
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition AVAssetExportPresetAppleM4A];
    exporter.outputURL = outputURL;
    exporter.outputFileType = AVFileTypeAppleM4A;
    exporter.videoComposition = mainCompositionInst;
    exporter.shouldOptimizeForNetworkUse = YES;
    
    // Notify caller that merging process is about tro start
    [self.delegate handler:self didStartMergingAtPath:[outputURL path]];
    
    [exporter exportAsynchronouslyWithCompletionHandler:^ {
         dispatch_async(dispatch_get_main_queue(), ^{
             [self exportDidFinishMerging:exporter];
         });
     }];
    
  6. また、エクスポート処理のステータスを確認するメソッドも実装します。

    - (void)exportDidFinishMerging:(AVAssetExportSession*)session {
    if(session.status == AVAssetExportSessionStatusCompleted){
    // notify the calling class that merging is finished
    [self.delegate handler:self didFinishMergingAtPath:[session.outputURL path]];
       }
    }
    

注: これはコードに直接使用できるサンプル コードではありませんが、これは理解を目的としたものであることに注意してください。これがお役に立てば幸いです。

于 2012-08-31T11:02:00.153 に答える