J'implémente une application qui enregistre et analyse l'audio en temps réel (ou au moins aussi près du temps réel que possible), en utilisant la mise à jour 201 du JDK version 8. Lors d'un test qui simule des cas d'utilisation typiques de l'application, j'ai remarqué qu'après plusieurs heures d'enregistrement audio en continu, un retard soudain de une à deux secondes a été introduit. Jusqu'à ce point, il n'y avait pas de retard notable. Ce n'est qu'après ce point critique d'enregistrement pendant plusieurs heures que ce retard a commencé à se produire.
Pour vérifier si mon code de synchronisation de l'enregistrement des échantillons audio est incorrect, j'ai commenté tout ce qui concerne la synchronisation. Cela m'a laissé essentiellement avec cette boucle de mise à jour qui récupère les échantillons audio dès qu'ils sont prêts (Remarque: code Kotlin):
while (!isInterrupted) {
val audioData = read(sampleSize, false)
listener.audioFrameCaptured(audioData)
}
Voici ma méthode de lecture:
fun read(samples: Int, buffered: Boolean = true): AudioData {
//Allocate a byte array in which the read audio samples will be stored.
val bytesToRead = samples * format.frameSize
val data = ByteArray(bytesToRead)
//Calculate the maximum amount of bytes to read during each iteration.
val bufferSize = (line.bufferSize / BUFFER_SIZE_DIVIDEND / format.frameSize).roundToInt() * format.frameSize
val maxBytesPerCycle = if (buffered) bufferSize else bytesToRead
//Read the audio data in one or multiple iterations.
var bytesRead = 0
while (bytesRead < bytesToRead) {
bytesRead += (line as TargetDataLine).read(data, bytesRead, min(maxBytesPerCycle, bytesToRead - bytesRead))
}
return AudioData(data, format)
}
Cependant, même sans aucun timing de ma part, le problème n'a pas été résolu. Par conséquent, j'ai continué à expérimenter un peu et à laisser l'application s'exécuter en utilisant différents formats audio, ce qui conduit à des résultats très confus (je vais utiliser un format audio stéréo 16 bits signé PCM avec peu d'endian et une fréquence d'échantillonnage de 44100,0 Hz par défaut, sauf indication contraire):
Ces résultats me permettent de conclure que la durée pendant laquelle je peux enregistrer de l'audio avant que ce problème ne se produise dépend de la machine sur laquelle l'application est exécutée et dépend du taux d'octets (c'est-à-dire la taille de la trame et la fréquence d'échantillonnage) du format audio. Cela semble vrai (bien que je ne puisse pas le confirmer complètement pour l'instant) car si je combine les modifications apportées en 2 et 3, je supposons que je puisse enregistrer des échantillons audio quatre fois plus longtemps (ce qui se situerait entre 26 et 27 heures) que lorsque j'utilise mon format audio "par défaut" avant que le délai ne commence à apparaître. Comme je n'ai pas encore trouvé le temps de laisser l'application s'exécuter aussi longtemps, je peux seulement dire qu'elle s'est bien déroulée pendant environ 15 heures avant de devoir l'arrêter en raison de contraintes de temps de mon côté. Cette hypothèse reste donc à confirmer ou à infirmer.
Selon le résultat du point 13, il semble que tout le problème n'apparaisse que lorsque vous utilisez Windows. Par conséquent, je pense qu'il pourrait être un bug dans la plate-forme spécifique parties de l'API javax.sound.sampled.
Même si je pense que j'ai pu trouver un moyen de changer lorsque ce problème commence à se produire, je ne suis pas satisfait du résultat. Je pourrais périodiquement fermer et rouvrir la ligne pour éviter que le problème ne commence à apparaître. Cependant, cela entraînerait un peu de temps arbitraire où je ne serais pas en mesure de capturer des échantillons audio. De plus, le Javadoc indique que certaines lignes ne peuvent plus être rouvertes après avoir été fermées. Par conséquent, ce n'est pas une bonne solution dans mon cas.
Idéalement, tout ce problème ne devrait pas se produire du tout. Y a-t-il quelque chose qui me manque complètement ou suis-je confronté à des limites de ce qui est possible avec l'API javax.sound.sampled? Comment puis-je me débarrasser de ce problème?
Edit: Par suggestion de Xtreme Biker et gidds, j'ai créé un petit exemple d'application. Vous pouvez le trouver dans ce dépôt Github .
J'ai (une) assez grande expérience avec Java interface audio. Voici quelques points qui peuvent être utiles pour vous guider vers une solution appropriée: