iPhone AVAudioPlayer 应用程序在第一次播放时冻结
Posted
技术标签:
【中文标题】iPhone AVAudioPlayer 应用程序在第一次播放时冻结【英文标题】:iPhone AVAudioPlayer app freeze on first play 【发布时间】: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 秒的卡顿?
【问题讨论】:
【参考方案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】:这有时也会发生在我的模拟器中。一切似乎都在设备上正常工作。您是否在实际硬件上进行过测试?
【讨论】:
你是对的。可能我应该在真实设备上进行测试。感谢您的建议...以上是关于iPhone AVAudioPlayer 应用程序在第一次播放时冻结的主要内容,如果未能解决你的问题,请参考以下文章
iPhone SDK:如何使用 AVAudioPlayer 标准化音频播放?
通过 Apple iPhone Earpods 控制 AVAudioPlayer
即使 iPhone 处于静音状态,AVAudioPlayer 仍在播放环境声音
iPhone AVAudioPlayer 应用程序在第一次播放时冻结