Jouez un son toutes les N millisecondes

Je développe une application de métronome. L’utilisateur peut sélectionner le bpm au moment de l’exécution et mon application lira le son “tick” en conséquence. Le “tick” est un métronome unique “shot” (mp3). J’ai essayé de l’implémenter en utilisant Handler et MediaPlayer, mais le métronome n’est pas précis du tout. J’ai donc pensé à changer l’approche: lorsque l’utilisateur choisit une nouvelle valeur bpm, je synthétise un nouveau son en répétant le tic-tac X fois toutes les N millisecondes, puis en passant en boucle sur ce son créé à l’exécution. Est-ce une alternative valable? Comment peut-il être mis en œuvre dans Android?

L’alternative consistant à passer en boucle à travers un son synthétisé semble être le meilleur choix pour le moment. Il existe une session audio exceptionnelle sur l’audio haute performance sur Google I / O 2013, que je conseillerais certainement de surveiller pour mieux comprendre le fonctionnement du système et les problèmes auxquels les développeurs seront confrontés en cas de latence audio. Vers 17h00 de la vidéo, un graphique montre la gigue par rapport aux rappels. Dans un monde parfait qui n’existe pas (oh vraiment?), La gigue serait nulle pour tous les rappels audio programmés. Mais ce n’est pas le cas, car il ya une instabilité pouvant aller jusqu’à 35 millisecondes ou même plus, car les données du graphique ont été générées à l’aide d’un dispositif ICS non spécifié et il existe certainement des scénarios pires que cela.

Donc, comme un métronome est un outil de précision et que ces craintes ne sont pas bonnes du tout, l’approche de lecture programmée doit être laissée de côté. J’ai même fait un métronome raisonnablement réaliste avec un son synthétisé en utilisant AudioTrack .

J’espère que ça aide ^^

Vous pouvez essayer d’utiliser une tâche de timer planifiée pour une exécution à taux fixe sur une timer .

Timer et TimerTask font tous deux partie du SDK Android (et de Java SE). Les exécutions ne tardent pas à cause de l’heure d’exécution de l’événement précédent.

 Timer timer = new Timer("MetronomeTimer", true); TimerTask tone = new TimerTask(){ @Override public void run(){ //Play sound } }; timer.scheduleAtFixedRate(tone, 500, 500); //120 BPM. Executes every 500 ms. 

Vous pouvez ensuite annuler la tâche de timer lorsque vous devez modifier le MPM.

 tone.cancel(); tone = new TimerTask(){...} timer.scheduleAtFixedRate(tone, 1000, 1000); //60 BPM. Executes every 1000 ms. 

Une autre possibilité susceptible de répondre à vos exigences (à partir de vos commentaires) est de filer un fil et de vérifier System.nanoTime () et de dormir par incréments, mais en tournant lorsque vous vous apprêtez à vous lever.

 long delayNanos = 500000000; long wakeup = System.nanoTime() + delayNanos; //Half second from right now long now; while(!done){ now = System.nanoTime(); //If we are less than 50 milliseconds from wake up. Spin away. if(now <= wakeup - 50000000){ //Sleep in very small increments, so we don't spin unrestricted. Thread.sleep(10); } if(now >= wakeup){ //Play sound wakeup += delayNanos; } } 

Quand ce son de jeu s’appelle

 mSoundManager.playSound(1); 

Android attend que l’appel soit terminé, puis vous appelez

 mHandler.postAtTime(this, SystemClock.uptimeMillis() + 200); 

Toutefois, si vous inversez ces appels, vous constaterez peut-être que le minutage est plus précis.

 mHandler.postAtTime(this, SystemClock.uptimeMillis() + 200); mSoundManager.playSound(1); 

Vous ne pouvez pas espérer que votre son prenne exactement le même temps, alors il est préférable de dire au gestionnaire de publier en premier. Toujours pas idéal, cependant.