iPhone AVAudioPlayer应用冻结第一次播放

时间:2010-09-22 09:40:49

标签: ios audio avaudioplayer

我正在使用iOS SDK中的AVAudioPlayer在tableView行中的每次点击时播放短音。 我已在每行按钮上手动设置了@selector,以触发方法playSound:(id)receiver {}。从接收器我得到声音网址所以我可以播放它。

这个方法看起来像这样:

- (void)playSound:(id)sender {
    [audioPlayer prepareToPlay];
    UIButton *audioButton = (UIButton *)sender;
    [audioButton setImage:[UIImage imageNamed:@"sound_preview.png"] forState:UIControlStateNormal];
    NSString *soundUrl = [[listOfItems objectForKey:[NSString stringWithFormat:@"%i",currentPlayingIndex]] objectForKey:@"sound_url"];

    //here I get mp3 file from http url via NSRequest in NSData
    NSData *soundData = [sharedAppSettingsController getSoundUrl:defaultDictionaryID uri:soundUrl];
    NSError *error;
    audioPlayer = [[AVAudioPlayer alloc] initWithData:soundData error:&error];
    audioPlayer.numberOfLoops = 0;
    if (error) {
        NSLog(@"Error: %@",[error description]);
    }
    else {
        audioPlayer.delegate = self;
        [audioPlayer play];
    }
}

除了第一次播放某些声音外,一切正常。应用程序冻结约2秒钟,然后播放声音。在点击声音按钮后,第二次和其他所有声音播放都会正常工作。

我想知道为什么在应用程序启动时第一次播放会冻结大约2秒钟?

4 个答案:

答案 0 :(得分:2)

检查您是否在函数中异步获取数据..

NSData *soundData = [sharedAppSettingsController getSoundUrl:defaultDictionaryID uri:soundUrl];

如果您异步获取,则执行将被阻止,直到获取数据为止。

答案 1 :(得分:2)

在您的代码段中,audioPlayer必须是ivar,对吧?

在方法的顶部,您在现有-prepareToPlay实例上调用audioPlayer(至少在第一次传递时可能为零)。

稍后在该方法中,您将此现有音频播放器替换为全新的AVAudioPlayer实例。之前的-prepareToPlay被浪费了。而且你每个新的AVAudioPlayer都在泄漏内存。

我会尝试创建AVAudioPlayer对象的缓存,而不是缓存声音数据或URL,每个声音对应一个。在-playSound:方法中,获取对表格行的相应音频播放器的引用,并-play

您可以使用-tableView:cellForRowAtIndexPath:作为获取该行的AVAudioPlayer实例的适当点,也可以懒惰地创建实例并将其缓存在那里。

您可以尝试-tableView:willDisplayCell:forRowAtIndexPath:作为在行的AVAudioPlayer实例上调用-prepareToPlay的点。

或者您可以在-tableView:cellForRowAtIndexPath:进行准备。试验并看看哪种方法效果最佳。

答案 2 :(得分:1)

如果你的音频长度不到30秒,并且是线性PCM或IMA4格式,并打包为.caf,.wav或.aiff,你可以使用系统声音:

导入AudioToolbox框架

在.h文件中创建此变量:

SystemSoundID mySound;

在.m文件中,在init方法中实现它:

-(id)init{
if (self) {
//Get path of VICTORY.WAV <-- the sound file in your bundle
 NSString* soundPath = [[NSBundle mainBundle] pathForResource:@"VICTORY" ofType:@"WAV"];
//If the file is in the bundle
if (soundPath) {
    //Create a file URL with this path
    NSURL* soundURL = [NSURL fileURLWithPath:soundPath];

    //Register sound file located at that URL as a system sound
    OSStatus err = AudioServicesCreateSystemSoundID((CFURLRef)soundURL, &mySound);

        if (err != kAudioServicesNoError) {
            NSLog(@"Could not load %@, error code: %ld", soundURL, err);
        }
    }
}
return self;
}

在您的IBAction方法中,您可以使用以下方法调用声音:

AudioServicesPlaySystemSound(mySound);

这适合我,播放按下按钮时非常接近的声音。希望这会对你有所帮助。

答案 3 :(得分:0)

这有时也会在我的模拟器中发生。一切似乎在设备上正常工作。您是否在实际硬件上进行了测试?