Код AudioQueue из SpeakHere не работает на iPad - PullRequest
1 голос
/ 10 июля 2010

Я использую аудио классы 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, которые объясняют разницу в поведении iPad. - Примечание: iPad действительно отображал некоторые другие дефектные поведения, которые были исправлены, такие как несовпадающие вызовы Begin Interrupt, которые никогда не заканчивались (поэтому я никогда не деактивирую сеанс).

Я никогда не получаю никаких журналов, указывающих на неудачные вызовы инициализации или активации из кода 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 голосов
/ 13 июля 2010

Оказывается, это странная проблема.

1) Используйте только звукозапись и воспроизведение, и код отлично работает на iPad.

2) Добавьте воспроизведение фильма и НЕ звонителюбые изменения маршрутизации и все работает нормально на iPad.

Каким-то образом наличие воспроизведения в Movie Player достаточно для изменения AudioSession, что вызывает принудительное изменение маршрута (например, использование динамика устройства вместо наушников).AudioSession станет неактивным.

...