2009-10-26 3 views
0

J'utilise AVAudioPlayer pour lire de la musique dans mon application iPhone.iPhone Synchroniser une séquence de temps avec de la musique

Dans une classe que j'ai écrite, j'ai un tableau qui contient des entiers ascendants aléatoires. (2, 4, 9, 17, 18, 20, ...) Ces entiers représentent les temps dans la chanson où un certain événement devrait se produire. Donc, si vous prenez le tableau ci-dessus, après 2 secondes de la chanson en cours de lecture, une méthode devrait être appelée. Après 4 secondes, une autre méthode devrait être appelée. Etc.

J'ai essayé d'utiliser une répétition NSTimer:

NSTimer *myTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerTick) userInfo:nil repeats:YES]; 

Everytime il se déclenche, il vérifie si la valeur de la Audioplayer et du arrayindex courant sont les mêmes:

- (void) timerTick { 
    if([[myArray objectAtIndex:currentIndex] intValue] == (int)(player.currentTime)) { 
    //here the event-method is called 
    currentIndex++; 
    } 
} 

Ce code fait fonctionne, mais seulement pour un certain temps. Après un certain temps, myTimer et la minuterie qui contrôle le lecteur de musique sont désynchronisés. Il manque donc un élément de myArray et une boucle infinie commence. Je ne sais pas exactement pourquoi ils ne sont pas synchronisés, mais je pense que c'est peut-être parce que le chronomètre et le joueur ne sont pas lancés exactement au même moment ou peut-être à cause de courts délais de performance.

Je pense que je dois aborder cela d'une manière totalement différente. La valeur-clé est-elle un moyen d'y parvenir? Je pourrais ajouter ma classe en tant qu'observateur à l'objet joueur, afin qu'il soit averti quand la valeur de player.currentTime change. Mais cela causerait beaucoup de notifications à envoyer et je pense que ce serait vraiment mauvais pour la performance.

Toute aide très appréciée!

Répondre

1

Ok voici ma solution: J'ai trouvé une application open source qui fait à peu près la même chose que mon appli, ce qui m'a beaucoup aidé. Je vais m'en tenir au code que j'ai déjà, avec une petite modification, ça devrait être assez précis pour mes besoins. Ici, il est:

currentIndex = 0; 
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(timerTick) userInfo:nil repeats:YES]; 


- (void) timerTick { 
if(timerRunning){ 


    if([[myArray objectAtIndex:currentIndex] intValue] <= (int)(player.currentTime*100)) { 
     //some event code 
     currentIndex++; 
    } 
} 
} 

Le changement important est de == à < = dans le cas condition. Quand il devient asynchrone et manque un élément de myArray, l'erreur est corrigée le centième de seconde suivant. Il est assez bien.

Merci pour votre aide!

0

Il se peut que les temporisateurs soient raisonnablement synchronisés, mais que votre code ne prenne que trop de temps à s'exécuter (c'est-à-dire: plus de 1 seconde).

Ne pourriez-vous pas utiliser la minuterie du lecteur de musique, et générer un thread chaque fois qu'un événement se produirait? De cette façon, la minuterie reste ininterrompue, et votre thread fera ce qu'il doit faire (disons les choses lourdes).

Si vous REALL y ont besoin de deux temporisateurs, je suppose que vous pouvez créer un fils de fond qui maintient ces deux horloges synchronisées, mais je pense que vous demandez là des problèmes ..

+0

"Ne pourriez-vous pas utiliser la minuterie du lecteur de musique" J'aimerais! En fait, je n'ai pas besoin d'une autre minuterie. Mais comment dois-je faire cela? Comment puis-je savoir s'il est temps d'appeler ma méthode événementielle? Quand dois-je vérifier si ([[myArray objectAtIndex: currentIndex] intValue] == (int) (player.currentTime))? – avf

0

synchronisation du monde réel avec de la musique est très difficile car les utilisateurs peuvent remarquer des erreurs de synchronisation d'un dixième de seconde ou moins. Vous pourriez trouver que AVAudioPlayer est simple pour ce dont vous avez besoin. Vous devrez peut-être contrôler le taux de lecture de la musique en utilisant AudioQueueServices afin de pouvoir synchroniser la musique sur le code au lieu de l'inverse. Vous pourriez voir le temps de tirer votre code à venir et ensuite commencer les méthodes avant que la musique joue réellement. Fait habilement cela synchroniserait la musique la plupart du temps.

Questions connexes