我在我正在创建的应用程序中使用SpeakHere音频类,必须播放和播放同时录制。
我在通用应用构建中使用最新的SDK和3.2设备目标(针对iPad和iPhone)。
该应用使用MPMoviePlayerController播放流媒体电影并同时录制音频。
这在iPhone上完全可以正常使用。
然而,它在我的客户iPad上100%失败。日志显示!操作错误,AudioSession只是拒绝激活!我从他那里收到的每个日志文件都包含许多中断文件。路由更改(即类别)返回到回调函数。 **在iPhone上我根本看不到这样的东西。日志仅显示创建的记录,并记录到指定的文件中。没有中断,没有路线变化,没有废话。
以下是相关日志:
Jul 10 07:15:21 iPad mediaserverd[15502] <Error>: [07:15:21.464 <0x1207000>] AudioSessionSetClientPlayState: Error adding running client - session not active
Sat Jul 10 07:15:21 iPad mediaserverd[15502] <Error>: [07:15:21.464 <AudioQueueServer>] AudioQueue: Error '!act' from AudioSessionSetClientPlayState(15642)
我已经将我的回调函数简化为仅记录中断和路由更改的发生(有原因)。所以我不打算发布代码,因为它确实没什么。我在一次尝试开始在iPad上录制时,多次看到这些日志。
我几乎阅读了Apple Dev论坛和StackOverflow中的每一篇文章,但似乎找不到具有相同问题的人或Apple Docs中任何解释iPad行为差异的相关说明。 - 注意:iPad确实显示了一些其他有缺陷的行为,例如从未结束的不匹配的Begin Interruption调用(因此我从未停用会话)。
我从未收到任何指示来自AudioQueue或AudioSession代码的初始化或激活调用失败的日志。当我尝试开始录制时,它就会失败。 - 我甚至试图强制AudioSessionSetActive(true);在每次尝试使用音响系统之前调用,我仍然会收到这些错误。
以下是初始化调用的相关代码:
//Initialize the Sound System
OSStatus error = AudioSessionInitialize(NULL, NULL, interruptionListener, self);
if (error){ printf("ERROR INITIALIZING AUDIO SESSION! %d\n", (int)error); }
else {
//must set the session active first according to devs talking about some defect....
error = AudioSessionSetActive(true);
if (error) NSLog(@"AudioSessionSetActive (true) failed");
UInt32 category = kAudioSessionCategory_PlayAndRecord;
error = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category);
if (error) printf("couldn't set audio category!\n");
error = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, self);
if (error) printf("ERROR ADDING AUDIO SESSION PROP LISTENER! %d\n", (int)error);
//Force mixing!
UInt32 allowMixing = true;
error = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof (allowMixing), &allowMixing );
if (error) printf("ERROR ENABLING MIXING PROPS! %d\n", (int)error);
UInt32 inputAvailable = 0;
UInt32 size = sizeof(inputAvailable);
// we do not want to allow recording if input is not available
error = AudioSessionGetProperty(kAudioSessionProperty_AudioInputAvailable, &size, &inputAvailable);
if (error) printf("ERROR GETTING INPUT AVAILABILITY! %d\n", (int)error);
isInputAvailable = (inputAvailable) ? YES : NO;
//iPad doesn't require the routing changes, branched to help isolate iPad behavioral issues
if(! [Utils GetMainVC].usingiPad){
//redirect to speaker? //this only resets on a category change!
UInt32 doChangeDefaultRoute = 1;
error = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof (doChangeDefaultRoute), &doChangeDefaultRoute);
if (error) printf("ERROR CHANGING DEFAULT ROUTE PROPS! %d\n", (int)error);
//this resets with interruption and/or route changes
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
error = AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
if (error) printf("ERROR SPEAKER ROUTE PROPS! %d\n", (int)error);
}
// we also need to listen to see if input availability changes
error = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioInputAvailable, propListener, self);
if (error) printf("ERROR ADDING AUDIO SESSION PROP LISTENER! %d\n", (int)error);
error = AudioSessionSetActive(true);
if (error) NSLog(@"AudioSessionSetActive (true) failed");
}
// Allocate our singleton instance for the recorder & player object
myRecorder = new AQRecorder();
myPlayer = new AQPlayer();
稍后在视频的loadstate回调中,我只是尝试将记录开始到预定的文件路径:
myRecorder->StartRecord((CFStringRef)myPathStr);
录音完全失败。
感谢您的时间和帮助。
答案 0 :(得分:0)
原来这是一个奇怪的问题。
1)仅使用录音和回放,代码在iPad上完美运行。
2)添加电影播放,不要调用任何路由更改,iPad上的工作正常。
以某种方式,电影播放器播放的存在足以以某种方式更改AudioSession,强制任何路由更改(比如使用设备扬声器而不是耳机)会导致AudioSession变为非活动状态。