2010-09-22 18 views
2

J'utilise AVAudioPlayer de iOS SDK pour lire des sons courts à chaque clic dans les lignes de tableView. J'ai fait @selector sur le bouton dans chaque ligne qui lance la méthode playSound: (id) receiver {}. Du récepteur, je reçois une URL sonore pour que je puisse jouer.L'application iPhone AVAudioPlayer gèle à la première lecture

Cette méthode ressemble que:

- (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]; 
    } 
} 

Tout fonctionne bien, sauf pour le premier jeu de certains sons. L'application se bloque pendant environ 2 secondes et le son est joué. Deuxième et tous les autres jeux de sons fonctionne juste après avoir cliqué sur le bouton sonore.

Je me demande pourquoi il y a environ 2 secondes de gel à la première lecture lorsque l'application démarre?

Si vous pensez que je prends une mauvaise solution s'il vous plaît me dire la bonne ...

Cordialement

Répondre

2

De votre extrait de code, audioPlayer doit être un ivar, n'est-ce pas?

En haut de la méthode, vous appelez -prepareToPlay sur l'instance audioPlayer existante (qui peut être nulle, au moins lors du premier passage). Plus tard dans la méthode, vous remplacez ce lecteur audio existant par une toute nouvelle instance de AVAudioPlayer. Le précédent -prepareToPlay est gaspillé. Et vous perdez de la mémoire avec chaque nouveau AVAudioPlayer. Au lieu de mettre en cache des données sonores ou des URL, je vais essayer de créer un cache d'objets AVAudioPlayer, un pour chaque son. Dans votre méthode -playSound:, obtenez une référence au lecteur audio approprié pour la ligne du tableau et -play.

Vous pouvez utiliser -tableView:cellForRowAtIndexPath: comme point approprié pour obtenir l'instance de AVAudioPlayer pour cette ligne, en créant peut-être paresseusement l'instance et en la mettant en cache là aussi.

Vous pouvez essayer -tableView:willDisplayCell:forRowAtIndexPath: comme point d'appel de -prepareToPlay sur l'instance AVAudioPlayer de la ligne.

Ou vous pouvez simplement faire la préparation dans -tableView:cellForRowAtIndexPath:. Expérimenter et voir ce qui fonctionne le mieux.

+0

Merci, je vais essayer ça ... –

0

Cela arrive parfois dans le simulateur pour moi aussi. Tout semble fonctionner correctement sur l'appareil. Avez-vous testé sur le matériel réel?

+0

Vous avez raison. Probablement je devrais tester ceci sur un vrai appareil. Merci pour la suggestion ... –

2

Vérifiez si vous obtenez des données de manière asynchrone en fonction ..

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

Si vous obtenez de manière asynchrone l'exécution sera bloquée jusqu'à ce qu'il obtiendra des données.

+0

Cela devrait aussi être un problème. Je vais essayer de changer ça ... –

1

Si votre audio est inférieure à 30 secondes de long en longueur et est au format PCM ou IMA4 linéaire, et est emballé comme un .caf, .wav ou .aiff vous pouvez utiliser les sons système:

Importer la AudioToolbox Framework

Dans votre.fichier h créer cette variable:

SystemSoundID mySound; 

Dans votre fichier .m mettre en œuvre dans votre méthode 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; 
} 

Dans la méthode IBAction vous appelez le son avec ceci:

AudioServicesPlaySystemSound(mySound); 

Cela fonctionne pour moi, joue le son sacrément proche de quand le bouton est pressé. J'espère que cela vous aide.