4

iPod ライブラリからのオーディオを処理する必要があります。iPod ライブラリのアセットを読み取る唯一の方法は、AVAssetReader です。Audio Unit でオーディオを処理するには、ステレオ形式である必要があるため、左右のチャンネルの値を取得します。しかし、AVAssetReader を使用して iPod ライブラリからアセットを読み取ると、ステレオ フォーマットで取得できません。左右のオーディオ チャンネルに分割する方法がわからないインターリーブ形式で出力されます。

必要な場所に到達するには、次のいずれかを実行する必要があります。

  1. AVAssetReader を取得して、ステレオ形式の AudioBufferList を取得します
  2. インターリーブされたデータを非インターリーブに変換して、必要なステレオ出力を取得します
  3. Audio Queue Services を介して送信し、自動バッファリングで必要なものを取得します

既存のパブリック API でできることと、iPod ライブラリ アセットを読み取るときに AVAssetReader がサポートすることによって制限されているようです。あなたならどうしますか?Audio Unit で処理する必要があるものを取得するにはどうすればよいですか?

私が持っているもう 1 つの制限は、メモリがいっぱいになり、アプリがクラッシュするため、一度に曲全体を読み取ることができないことです。これが、Audio Queue Services を使用したい理由です。iPod ライブラリのアセットをステレオ形式のストリームとして扱うことができれば、すべての要件が満たされます。

これもできますか?これがどのように行われるかを説明するドキュメント、ブログ、または記事はどこかにありますか?

4

1 に答える 1

3

そこにはいくつかの質問が積み上げられているようですね。

AVAssetReader をセットアップするときに、設定のディクショナリを渡すことができます。AVAssetReaders を作成する方法は次のとおりです...

    AVAssetReader* CreateAssetReaderFromSong(AVURLAsset* songURL) {

    if([songURL.tracks count] <= 0)
        return NULL;


    AVAssetTrack* songTrack = [songURL.tracks objectAtIndex:0];

    NSDictionary* outputSettingsDict = [[NSDictionary alloc] initWithObjectsAndKeys:

                                        [NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey,
                                        //     [NSNumber numberWithInt:AUDIO_SAMPLE_RATE],AVSampleRateKey,  /*Not Supported*/
                                        //     [NSNumber numberWithInt: 2],AVNumberOfChannelsKey,   /*Not Supported*/

                                        [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
                                        [NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey,
                                        [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
                                        [NSNumber numberWithBool:NO],AVLinearPCMIsNonInterleaved,

                                        nil];

    NSError* error = nil;
    AVAssetReader* reader = [[AVAssetReader alloc] initWithAsset:songURL error:&error];

    {
        AVAssetReaderTrackOutput* output = [[AVAssetReaderTrackOutput alloc] initWithTrack:songTrack outputSettings:outputSettingsDict];
        [reader addOutput:output];
        [output release];
    }

    return reader;
}

左チャンネルと右チャンネルを分割する限り、「AVLinearPCMBitDepthKey」に基づいてデータをループできます。

16ビットの場合、このようなもの...

for (j=0; j<tBufCopy; j++, pAD+=2) {            // Fill the buffers...
    mProcessingBuffer.Left[(tBlockUsed+j)] = ((sint32)pAD[0]);
    mProcessingBuffer.Right[(tBlockUsed+j)] = ((sint32)pAD[1]);
}

これで、処理にこれが必要になると思います。しかし、インターリーブ形式でデータを保持することは、非常に優れています。通常、ストレート インターリーブ形式を使用して、AudioQueue またはリモート I/O コールバックに直接渡すと、正しく再生されます。

AudioQueue フレームワークを使用してオーディオを再生するには、データが次のフローに従う必要があります。

AVAssetReader -> NSData Buffer -> AudioQueueBuffer

次に、追加のデータを要求する AudioQueue コールバックで、単純に AudioQueueBuffer を渡します。何かのようなもの...

- (void) audioQueueCallback:(AudioQueueRef)aq  buffer:(AudioQueueBufferRef)buffer {

    memcpy(buffer->mAudioData, srcData, mBufferByteSize);
    //Setup buffer->mAudioDataSize

    //...

    AudioQueueEnqueueBuffer(mQueue, buffer, 0 /*CBR*/, 0 /*non compressed*/);
}
于 2011-08-23T17:28:20.343 に答える