我在商店里有一个音频应用程序 . 它适用于iOS 4.0之前的iPhone OS版本 . 我正在开发一个新版本,首先要使应用程序符合新的iOS多任务处理功能 . (我的iPhone上有iOS 4.0,并已升级到最新的xCode和SDK . )
结果是一个显示阻止 .
o当我在iPhone上安装应用程序并在调试器中运行,或者在iPhone关闭后启动应用程序时,应用程序就可以正常工作 - 按下按钮时播放音频,或者从保存的“状态”重新启动音频上一次应用程序运行 .
o如果我尝试按下Home按钮,然后从后台重新启动应用程序,那么音频 - 和1-n音频流的混合 - 会发出一种只有我才能识别的口吃声 .
o如果 - 虽然音频很干净 - 我打电话给iPhone,我可以接听或拒绝接听电话 . 在这两种情况下,应用程序都会干净利落地进行播放 .
请注意,我不是在后台模式下尝试播放任何内容 . 我只是想关闭一些东西并在被问到时将它们带回来 .
技术:所有音频逻辑都使用RemoteIO . (我有一天计划做一些相当复杂的信号处理 . )
请原谅伪代码叙述 - 一些真正的代码非常广泛 .
MainViewController:
o viewDidLoad - 没什么特别的
o didBecomeActive将自己设置为音频会话代表;将AudioSessionCategory设置为MediaPlayback;设置AudioSessionActive;创建一个播放器(见下文);重启之前播放的任何声音;
o willResignActive保存播放的状态;调用stopAllSounds;阻止玩家;设置音频会话无效;
o didEnterBackground - 没有(方法已注册,但没有内容 . )
o willEnterForeground - 没有(方法已注册,但没有内容 . )
播放器概述 - 我的课程:播放器是单身人士 . 我确保在didBecomeActive中销毁单例实例,并创建一个新实例 . 实例化单例实际上启动了AudioUnit .
构造函数setupRemoteIO;启动AudioOutputUnitStart;停止AudioOutputUnitStop;玩家回调通常的东西;
以下是我的MainViewController中的一些方法:
(void)willResignActive:(NSNotification *)note {
[ self saveState ];
[ [ NaturePlayer getInstance ] stopAllSounds ];
[ [ NaturePlayer getInstance ] stop ];
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive: NO error: &activationError];
[NaturePlayer destroy];
}
- (void)didBecomeActive:(NSNotification *)note {
[ self setupAudioSession ];
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive: YES error: &activationError];
[ self restartSounds ];
[ self setViewState ];
}
- (void)didEnterBackground:(NSNotification *)note {
int xxx = 1;
}
- (void)willEnterForeground:(NSNotification *)note {
int xxx = 1;
}
- (void) applicationWillTerminate: (NSNotification*) notification {
int xxx = 1;
}
这是NaturePlayer的一个方法:
/**
* Stop the playback process.
*/
void NaturePlayerDelegate::stop() {
if (isPlaying_) {
AudioOutputUnitStop(outputUnit_);
isPlaying_ = FALSE ;
}
}
我检查了:正在调用stop(),然后调用AudioOutputUnitStop();同时检查:AudioOutputUnitStop上的文档说它会阻塞,直到所有活动都完成 .
3 回答
没有关于音频代码的更多细节很难说 . 但我建议您可能需要检查您的Player对象拆解代码,以确保音频单元和音频会话在释放内容之前完全停止(缓冲回调线程耗尽) .
您是否在代码中初始化和取消初始化AudioUnit?我最近发现了一个问题,即创建和销毁AudioUnit然后离开并返回到您的应用程序将导致口吃 .
通过永远不会初始化AudioUnits,我能够在我的应用程序中解决这个问题 .
More info关于我的问题和我的AudioUnit代码 .
我在一个项目中遇到了同样的问题 . 我发现如果在挂起应用程序之前从按钮单击调用AudioOutputUnitStop(),然后在应用程序恢复时调用AudioOutputUnitStart(),我没有遇到任何问题 . 但是如果我从viewDidUnload处理程序自动调用AudioOutputUnitStop()或者作为对UIApplicationWillResignActiveNotification的响应,我就会听到上面描述的口吃,类似反馈的声音 .
我还注意到,如果我手动停止音频单元,然后暂停应用程序,则会调用中断监听器 . 但是,如果我在音频设备仍在运行时暂停应用程序,则不会调用中断侦听器 . 中断监听器应该停止音频单元,所以这对我没有好处 .
经过几个小时的跟踪,我找到了一种方法来完成没有音频单元的任务,并将它们从我的应用程序中取出 . 所以我担心我没有完整的答案 . 但希望这些线索可以帮助某些人 . 我可能需要在将来再次这样做,所以我会在这里查看是否有其他人已经弄清楚了 .