我在商店里有一个音频应用程序。它适用于iOS 4.0之前的iPhone OS版本。我正在开发一个新版本,首先要使应用程序符合新的iOS多任务处理功能。 (我的iPhone上有iOS 4.0,并已升级到最新的xCode和SDK。)
结果是一个显示阻止。
o当我在iPhone上安装应用程序并在调试器中运行,或者在iPhone关闭后启动应用程序时,应用程序就可以正常工作 - 按下按钮时播放音频,或者从“状态”重启音频上次应用程序运行时保存了。
o如果我尝试按下主页按钮,然后从后台重新启动应用程序,那么音频 - 和1-n音频流的混合 - 会发出只有我能识别的口吃声。
o如果 - 虽然音频很干净 - 我打电话给iPhone,我可以接听或拒绝接听电话。在这两种情况下,应用程序都会干净利落地进行播放。
请注意,在后台模式下,我不想尝试播放任何内容。我只想关闭一些东西并在被问到时将它们带回来。
技术:所有音频逻辑都使用RemoteIO。 (我有一天计划做一些相当复杂的信号处理。)
请原谅伪代码叙述 - 一些真正的代码非常广泛。
MainViewController:
o viewDidLoad - 没什么特别的
o didBecomeActive 将self设置为音频会话代理; 将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上的文档说它会阻塞,直到所有活动都完成。
答案 0 :(得分:0)
很难说没有关于音频代码的更多细节。但我建议您可能需要检查您的Player对象拆解代码,以确保在释放内容之前完全停止音频单元和音频会话(缓冲区回调线程耗尽)。
答案 1 :(得分:0)
您是否在代码中初始化和取消初始化AudioUnits?我最近发现一个问题,即创建和销毁AudioUnit然后离开并返回到您的应用程序将导致口吃。
我能够通过永不取消初始化AudioUnits来解决这个问题。
More info关于我的问题和我的AudioUnit代码。
答案 2 :(得分:0)
我在我的一个项目中遇到了同样的问题。我发现如果在挂起应用程序之前从按钮单击调用AudioOutputUnitStop(),然后在应用程序恢复时调用AudioOutputUnitStart(),我没有遇到任何问题。但是如果我从viewDidUnload处理程序中自动调用AudioOutputUnitStop()或者作为对UIApplicationWillResignActiveNotification的响应,我就会听到上面描述的口吃,类似反馈的声音。
我还注意到,如果我手动停止音频设备,然后暂停应用程序,则会调用中断监听器。但是,如果我在音频设备仍在运行时暂停应用程序,则不会调用中断侦听器。中断监听器应该停止音频单元,所以这对我没有好处。
经过几个小时的追踪,我找到了一种方法来完成没有音频单元的任务,并将它们从我的应用程序中取出。所以我担心我没有完整的答案。但希望这些线索可以帮助某些人。我可能需要在将来再次这样做,所以我会在这里查看是否有其他人已经弄清楚了。