Я использую аудио классы 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);
А запись звука полностью не удалась.
Спасибо за ваше время и помощь в этом.