2012-02-08 4 views
3

У меня возникла странная проблема с классом AVAudioPlayer с обратным вызовом audioPlayerDidFinishPlaying:successfully:, который не называется иногда. Урезанная версия кода, который начинается воспроизведение выглядит,AVAudioPlayer audioPlayerDidFinishPlaying: успешно: не называется

self.player = [[[AVAudioPlayer alloc] initWithContentsOfURL:localFileAudioURL error:&error] autorelease]; 
self.player.delegate = self; 
[player prepareToPlay]; 
[NSTimer scheduledTimerWithTimeInterval:0.016f target:self selector:@selector(updatePlaybackProgress) userInfo:nil repeats:YES]; 
[player play]; 

Существует таймер, который проходит каждые 16 мс, чтобы показать прогресс воспроизведения. Всякий раз, когда воспроизведение звука заканчивается и вызывается обратный вызов audioPlayerDidFinishPlaying:successfully:, таймер будет недействительным. Код обратного вызова:

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { 
    [self.progressTimer invalidate]; 
    self.progressTimer = nil; 
} 

Однако, иногда (один раз в 20-30 воспроизведении) этот обратный вызов не вызывается. Я добавил точки останова и записи для проверки того, что этот метод обратного вызова не был вызван.

НомерOfLoops для воспроизведения установлен в 0, поэтому он не повторяется.

Дополнительная информация, если это поможет. Повторяющийся таймер, который создается, обновляет пользовательский интерфейс с текущим ходом воспроизведения. Его код выглядит,

- (void)updatePlaybackProgress { 
    SoundCell *soundCell = [self soundCellForCurrentlyPlayingSound]; 

    NSTimeInterval progress = player.currentTime/player.duration; 
    if (progress >= 0) { 
     soundCell.progress = progress; 
    } 
} 

завершение обратного вызова не вызывается иногда, так что таймер не отменен, и называется через каждые 16 мс. Я зарегистрировал значения player.currentTime и progress внутри метода updatePlaybackProgress, и кажется, что воспроизведение повторяется снова и снова. Значение currentTime продолжает увеличиваться с 0.0 до 1.0, затем обратно на 0.0 и начинается с начала. Звук, однако, воспроизводится только в первый раз, а не постоянно, как предлагает значение currentTime.

Эта проблема произошла для звуков продолжительностью от 1 секунды до 30 секунд.

У меня нет идей на этом этапе, и Google и форумы разработчиков Apple не имеют ничего общего.

+0

Вы нашли решение для этого?Я также сталкиваюсь с той же проблемой. – arundevma

+0

Я следил за советом от @drunknbass и использовал «CADisplayLink» вместо 16 мс таймера для обновления дисплея. Я также установил частоту, достаточную для того, чтобы исправить эту проблему. Частота дисплея составляет 60 Гц (около 16 мс), и я устанавливаю его для обновления каждые 5 циклов обновления (примерно каждые 80 мс). Проблема была не так часто, но я все еще мог воспроизвести ее, к сожалению. – Anurag

+0

Но моя проблема другая. Я хочу сделать некоторые операции после окончания воспроизведения проигрывателя. Вся моя логика зависит от функции обратной связи. Но иногда его не увольняют. Я не могу воспроизвести эту проблему. – arundevma

ответ

1
  1. Ваш таймер не гарантирует срабатывание в указанное вами время. Если вы пытаетесь создать индикатор прогресса игрока, я предлагаю использовать CADisplayLink, чтобы дать вам nstimer как функциональность без накладных расходов (его увольнение основано на обновлении экрана).

  2. я бы реализовать все методы AVAudioPlayerDelegate протокола, связанных с воспроизведением ..

В ответ на воспроизводимый звук Завершение - audioPlayerDidFinishPlaying: успешно: Реагирование на ошибки декодирования аудио - audioPlayerDecodeErrorDidOccur: ошибка: Обработка прерываний звука - audioPlayerBeginInterruption: - audioPlayerEndInterruption: - audioPlayerEndInterruption: withFlags:

Скорее всего, один из них вызывается, когда воспроизведение останавливается. Вы также можете зарегистрироваться для NSNotifications для воспроизведения звука, а в методе, который вы реализуете, вам просто нужно сравнить аудиоплеера с вашим местным игроком, чтобы узнать, что это вас заинтересовало.

+0

Спасибо за 'CADisplayLink'. Я не знал об этом. Я выполнил все 4 метода делегата 'AVAudioPlayerDelegate', и ни один из них не был вызван на основе вызовов регистрации. Я еще не пробовал проверять уведомления. Может ли высокая частота таймера каким-то образом блокировать обратный вызов? NSNotifications находятся в очереди, насколько я знаю, и не отбрасываются. Попробуйте это сейчас. – Anurag

+0

Я попытался около 15 минут воспроизвести проблему, но этого еще не произошло. Поведение очень непоследовательно. Является ли 16 мс или 62,5 Гц высокой частотой для обновлений NSTimer? – Anurag

+0

Я использую 'CADisplayLink', и проблема встречается гораздо реже, чем раньше. На самом деле, я видел это только дважды с прошлого месяца. Но тот факт, что это все еще случалось вообще, беспокоит – Anurag

Смежные вопросы