来自SpeakHere的AudioQueue代码在iPad上失败

时间:2010-07-10 16:15:30

标签: iphone objective-c ipad audioqueue audiosession

我在我正在创建的应用程序中使用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);

录音完全失败。

感谢您的时间和帮助。

1 个答案:

答案 0 :(得分:0)

原来这是一个奇怪的问题。

1)仅使用录音和回放,代码在iPad上完美运行。

2)添加电影播放,不要调用任何路由更改,iPad上的工作正常。

以某种方式,电影播放器​​播放的存在足以以某种方式更改AudioSession,强制任何路由更改(比如使用设备扬声器而不是耳机)会导致AudioSession变为非活动状态。