0

私のアプリには52個のmp3があり、ビューコントローラーをロードすると、52個のmp3すべてを次のように割り当てます。

NSString *pathFrase1 = [NSString stringWithFormat:@"%@/%@",[[NSBundle mainBundle] resourcePath],[NSString stringWithFormat:@"a%d_1a.mp3",set]];
NSURL *filePath1 = [NSURL fileURLWithPath:pathFrase1 isDirectory:NO];
f1 = [[AVAudioPlayer alloc] initWithContentsOfURL:filePath1 error:nil];
[f1 prepareToPlay];

しかし、viewcontrollerを開くと非常に遅くなります。それを使用するときにmp3を割り当てる方法はありますか? その AVAudioPlayer をリリースしますか??

4

3 に答える 3

6

処理は少し複雑ですが、AVAudioPlayerを使用する代わりに、AVPlayerを使用してください。AVPlayerは、ファイルをプリロードできるAVAssetsを再生するように設計されています。具体的には、AVURLAssetsと呼ばれるAVAssetのサブクラスを使用する必要があります。これにより、URLをロードできます:LoadingAVAssetその後、AVAssetを使用してAVPlayerItemを作成できます。AVPlayerItemは、AVPlayerがAVAssetの再生状態を追跡するために使用する軽量ラッパーです。AVPlayerを使用することの良いところは、AVMutableCompositionを再生できることです。、それ自体に複数のAVAssetsを含めることができます。AVPlayerは、AVAssetsのキューを再生し、新しいAVAssetの再生を開始するタイミングとその開始に関する情報を提供することもできます。MP3を一連のAVURlAssetsにロードすると、それらをロードして保持し、1つ(または複数)のMP3を再生する場合にのみAVPlayerItemとAVPlayerを作成できます。

AVAudioPlayerは単一のファイルを再生するように設計されていますが、舞台裏でAVAssets(およびおそらくAVPlayer)を使用します。単純な状況には適していますが、もっと複雑で、本当にAVPlayerを使いたいと思うでしょう。

また、AVPlayerItemとAVPlayerは軽量オブジェクトであることも指摘しておく必要があります。インスタンス化するのにそれほど時間はかかりません。常に時間がかかるAVAssetを読み込んでいます。そのため、必要に応じてAVPlayerItemおよびAVPlayerオブジェクトを自由に作成および破棄できます。

最後に、AVAssetとAVPlayerは、通知をブロックに依存する場合があります。したがって、たとえば、AVURLAssetをロードするときにc-blockを使用して、アセットが完全にロードされたときに通知を受け取る必要がある場合があります。これらのブロックはメインスレッドでは呼び出されないことに注意してください。したがって、UI要素を更新しようとしたり、そのブロックからアニメーションを実行したりしようとすると、正しく機能しません。これを行うには、メインスレッドに別のブロックをディスパッチする必要があります。次に例を示しますdispatch_async(dispatch_get_main_queue(),^{....update UI element code....});。ブロックのディスパッチの詳細については、Appleの同時実行プログラミングガイドおよびブロックプログラミングガイドを参照してください。

于 2012-05-06T13:37:09.807 に答える
1

確かに、しかし がAVAudioPlayer割り当てられ、プレイの準備が整っているため、遅延が発生します。何をいつプレイするか予測できますか? もしそうなら、特定の mp3 を再生する必要がある数秒前にロードできるかもしれません。

タイミング要件によっては機能しない可能性がある代替手段は次のとおりです。

- (void)prepareAudioPlayer {
    static int index = -1;
    index = index + 1;
    if (index < [[self FileNames] count]) {
        NSError *err = nil;
        NSString *audioFilePath = @""; // Figure out how to get each file name here
        NSURL *audioFileURL = [NSURL fileURLWithPath:audioFilePath];
        AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL error:&err];
        if (err) {
            NSLog(@"Audio Player Error: %@", [err description]);
        }
        [player prepareToPlay];
        // Add this player to the "AudioPlayers" array
        [[self AudioPlayers] addObject:player];
        // Recurse until all players are loaded
        [self prepareAudioPlayer];
    }
}

この解には と のプロパティが必要FileNamesですAudioPlayers

これが設定されると、次のようなことができます (おそらく でviewDidLoad)。

// Make the file name array 
[self setFileNames:[NSMutableArray array]];
// Initiate the audio player loading
[self performSelectorInBackground:@selector(prepareAudioPlayer) withObject:nil];

後で特定のファイルを再生する必要がある場合は、配列内のファイル名のインデックスと、配列内のそのインデックスFileNamesの呼び出しplayを見つけることができます。AVAudioPlayerAudioPlayers

これはおそらく最善の方法ではないように思えますが、この方法が必要な場合は機能する可能性があります。

于 2012-05-06T13:07:18.990 に答える
0

使用方法は次のとおりです。サウンドが再生されている場合、現在の時間は、サウンドの開始からの秒単位で測定された現在の再生位置のオフセットです。サウンドが再生されていない場合、現在の Time は、サウンドの開始から秒単位で測定された、play メソッドの呼び出し時に再生が開始されるオフセットです。

このプロパティを設定すると、サウンド ファイル内の特定のポイントをシークしたり、オーディオの早送りおよび巻き戻し機能を実装したりできます。このプロパティの値は、オーディオ プレーヤーの再生中または一時停止中に単調に増加します。

複数のオーディオ プレーヤーがオーディオ出力デバイスに接続されている場合、少なくとも 1 つのプレーヤーが再生中または一時停止している限り、デバイス時間は増加し続けます。

再生中または一時停止中のオーディオ プレーヤーがオーディオ出力デバイスに接続されていない場合、デバイス時間は 0 に戻ります。

このプロパティを使用して、play AtTime: インスタンス メソッドを呼び出すときに「現在」を示します。deviceCurrent Time から指定されたオフセットで再生するように複数のオーディオ プレーヤーを構成することにより、その方法の説明で説明されているように、正確な同期を実行できます

于 2012-05-06T13:32:26.510 に答える