Приложение iPhone AVAudioPlayer зависает при первой игре - PullRequest
2 голосов
/ 22 сентября 2010

Я использую AVAudioPlayer из iOS SDK для воспроизведения коротких звуков при каждом щелчке в строках tableView.Я вручную сделал @selector на кнопке в каждой строке, которая запускает метод playSound:(id)receiver {}.Из ресивера я получаю URL-адрес звука, чтобы я мог его воспроизвести.

Этот метод выглядит следующим образом:

- (void)playSound:(id)sender {
    [audioPlayer prepareToPlay];
    UIButton *audioButton = (UIButton *)sender;
    [audioButton setImage:[UIImage imageNamed:@"sound_preview.png"] forState:UIControlStateNormal];
    NSString *soundUrl = [[listOfItems objectForKey:[NSString stringWithFormat:@"%i",currentPlayingIndex]] objectForKey:@"sound_url"];

    //here I get mp3 file from http url via NSRequest in NSData
    NSData *soundData = [sharedAppSettingsController getSoundUrl:defaultDictionaryID uri:soundUrl];
    NSError *error;
    audioPlayer = [[AVAudioPlayer alloc] initWithData:soundData error:&error];
    audioPlayer.numberOfLoops = 0;
    if (error) {
        NSLog(@"Error: %@",[error description]);
    }
    else {
        audioPlayer.delegate = self;
        [audioPlayer play];
    }
}

Все работает отлично, за исключением первого воспроизведения некоторого звука.Приложение зависает примерно на 2 секунды, а затем воспроизводится звук.Второе и любое другое воспроизведение звука работает сразу после нажатия на кнопку звука.

Интересно, почему при первом воспроизведении приложения происходит остановка примерно на 2 секунды?

Ответы [ 4 ]

2 голосов
/ 22 сентября 2010

Проверьте, получаете ли вы данные асинхронно в функции.

NSData *soundData = [sharedAppSettingsController getSoundUrl:defaultDictionaryID uri:soundUrl];

Если вы получаете асинхронно, выполнение будет заблокировано, пока не будут получены данные.

2 голосов
/ 22 сентября 2010

Из вашего фрагмента кода, audioPlayer должен быть иваром, верно?

В верхней части метода вы вызываете -prepareToPlay для существующего экземпляра audioPlayer (который может быть равен нулю, по крайней мере, при первом проходе).

Позже в этом методе вы заменяете этот существующий аудиоплеер новым экземпляром AVAudioPlayer. Предыдущий -prepareToPlay потрачен впустую. И вы теряете память с каждым новым AVAudioPlayer.

Вместо кэширования звуковых данных или URL-адресов, я бы попытался создать кэш объектов AVAudioPlayer, по одному для каждого звука. В вашем методе -playSound: получите ссылку на соответствующий аудиоплеер для строки таблицы и -play.

Вы можете использовать -tableView:cellForRowAtIndexPath: в качестве подходящей точки для получения экземпляра AVAudioPlayer для этой строки, возможно, лениво создавая экземпляр и также кэшируя его там.

Вы можете попробовать -tableView:willDisplayCell:forRowAtIndexPath: как точку, в которой вы бы вызвали -prepareToPlay в экземпляре AVAudioPlayer строки.

Или вы можете просто подготовиться в -tableView:cellForRowAtIndexPath:. Поэкспериментируйте и посмотрите, что работает лучше всего.

1 голос
/ 03 января 2012

Если длина вашего аудио составляет менее 30 секунд, и он имеет линейный формат PCM или IMA4 и упакован в формат .caf, .wav или .aiff, вы можете использовать системные звуки:

ИмпортAudioToolbox Framework

В вашем .h файле создайте эту переменную:

SystemSoundID mySound;

В своем файле .m внедрите его в свой метод init:

-(id)init{
if (self) {
//Get path of VICTORY.WAV <-- the sound file in your bundle
 NSString* soundPath = [[NSBundle mainBundle] pathForResource:@"VICTORY" ofType:@"WAV"];
//If the file is in the bundle
if (soundPath) {
    //Create a file URL with this path
    NSURL* soundURL = [NSURL fileURLWithPath:soundPath];

    //Register sound file located at that URL as a system sound
    OSStatus err = AudioServicesCreateSystemSoundID((CFURLRef)soundURL, &mySound);

        if (err != kAudioServicesNoError) {
            NSLog(@"Could not load %@, error code: %ld", soundURL, err);
        }
    }
}
return self;
}

В вашемМетод IBAction, который вы называете звуком с помощью этого:

AudioServicesPlaySystemSound(mySound);

Это работает для меня, воспроизводит звук довольно близко к тому моменту, когда нажимается кнопка.Надеюсь, это поможет вам.

0 голосов
/ 22 сентября 2010

Это иногда случается и в симуляторе для меня тоже.Кажется, все работает нормально на устройстве.Вы тестировали на реальном оборудовании?

...