【问题标题】:iPhone AVAudioPlayer app freeze on first playiPhone AVAudioPlayer 应用程序在第一次播放时冻结
【发布时间】:2010-09-22 09:40:49
【问题描述】:

我正在使用 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 秒的卡顿?

【问题讨论】:

    标签: ios audio avaudioplayer


    【解决方案1】:

    根据您的代码 sn-p,audioPlayer 必须是 ivar,对吧?

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

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

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

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

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

    或者您可以在-tableView:cellForRowAtIndexPath: 中进行准备。试验一下,看看哪种效果最好。

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

        如果您的音频长度小于 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);
        

        这对我有用,在按下按钮时播放的声音非常接近。希望对您有所帮助。

        【讨论】:

          【解决方案4】:

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

          【讨论】:

          • 你是对的。可能我应该在真实设备上进行测试。感谢您的建议...
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-28
          相关资源
          最近更新 更多