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:Loading AVAsset。然后,您可以使用 AVAsset 创建AVPlayerItem。AVPlayerItem 是一个轻量级包装器,AVPlayer 使用它来跟踪 AVAsset 的播放状态。使用 AVPlayer 的好处是它可以播放AVMutableComposition,它本身可以包含多个 AVAsset。AVPlayer 还可以播放 AVAsset 队列,并为您提供有关何时开始播放新 AVAsset 以及哪个 AVAsset 的信息。如果您将 MP3 加载到一堆 AVURlAssets 中,您可以加载它们并保留它们,仅当您想播放一个(或多个)MP3 时才创建 AVPlayerItem 和 AVPlayer。

AVAudioPlayer 旨在播放单个文件,但它在幕后使用 AVAssets(可能还有 AVPlayer)。它适用于简单的情况,但对于更复杂的情况,你真的想使用 AVPlayer。

我还应该指出 AVPlayerItem 和 AVPlayer 是轻量级对象。他们不需要很长时间来实例化。它正在加载需要所有时间的 AVAsset。因此,您可以根据需要随意创建和销毁 AVPlayerItem 和 AVPlayer 对象。

最后,AVAsset 和 AVPlayer 有时依赖块来通知。因此,例如,您可能需要在加载 AVURLAsset 时使用 c-blocks 以获取有关资产何时完全加载的通知。请注意,这些块不会在主线程上调用。因此,如果您尝试更新任何 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调用。playAVAudioPlayerAudioPlayers

这似乎不是最好的做事方式,但如果您需要这种方式,它可能会起作用。

于 2012-05-06T13:07:18.990 回答
0

这里是使用方法,如果声音正在播放,current Time 是当前播放位置的偏移量,以声音开始的秒数为单位。如果声音没有播放,当前时间是调用 play 方法时开始播放的偏移量,以声音开始的秒数为单位。

通过设置此属性,您可以寻找到声音文件中的特定点或实现音频快进和快退功能。当音频播放器正在播放或暂停时,此属性的值会单调增加。

如果不止一个音频播放器连接到音频输出设备,只要至少有一个播放器正在播放或暂停,设备时间就会继续增加。

如果音频输出设备没有连接的正在播放或暂停的音频播放器,则设备时间恢复为 0。

调用 play AtTime: 实例方法时,使用此属性指示“现在”。通过将多个音频播放器配置为从 deviceCurrent Time 的指定偏移量播放,您可以执行精确同步 — 如该方法的讨论中所述。要了解更多信息,请访问..在此处输入链接描述

于 2012-05-06T13:32:26.510 回答