comment diffuser le son en java, sans délai, à l'aide de SourceDataLine
Je veux générer des sons, basé sur action de l'utilisateur en Java. Même si j'ai mis la taille de la mémoire tampon dans SourceDataLine à la plus petite valeur possible (1 image) j'ai encore du retard d'environ 1 seconde.
À cause d'un fragment de code est une image vaut mille mots (ou était-ce une image?), voici le code:
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
import javax.swing.JFrame;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class SoundTest {
private static int sliderValue = 500;
public static void main(String[] args) throws Exception {
final JFrame frame = new JFrame();
final JSlider slider = new JSlider(500, 1000);
frame.add(slider);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
sliderValue = slider.getValue();
}
});
frame.pack();
frame.setVisible(true);
final AudioFormat audioFormat = new AudioFormat(44100, 8, 1, true, true);
final DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat, 1);
final SourceDataLine soundLine = (SourceDataLine) AudioSystem.getLine(info);
soundLine.open(audioFormat);
soundLine.start();
byte counter = 0;
final byte[] buffer = new byte[1];
byte sign = 1;
while (frame.isVisible()) {
if (counter > audioFormat.getFrameRate() / sliderValue) {
sign = (byte) -sign;
counter = 0;
}
buffer[0] = (byte) (sign * 30);
soundLine.write(buffer, 0, 1);
counter++;
}
}
}
Essayez de déplacer le curseur tout en écoutant le son. Est-il possible, ou dois-je créer des tampons de mémoire et de les encapsuler dans les occurrences d'élément?
OriginalL'auteur andi | 2011-08-08
Vous devez vous connecter pour publier un commentaire.
La solution est de spécifier la taille de la mémoire tampon dans le
open(AudioFormat,int)
méthode. Un délai de 10 ms à 100 ms, sera acceptable pour audio temps réel. Très faibles latences, comme ne fonctionnera pas sur tous les systèmes informatiques, et 100ms ou plus probablement être gênant pour vos utilisateurs. Un bon compromis est, par exemple, 50ms. Pour votre format audio, 8 bits, mono à 44100Hz, une bonne taille de la mémoire tampon est de 2 200 octets, ce qui est presque 50ms.Également noter que les différents OS ont différentes capacités audio en Java. Sur Windows et Linux, vous pouvez travailler avec de très petites tailles de tampon, mais OS X utilise un vieux de la mise en œuvre avec beaucoup plus de retard.
Aussi, l'écriture de données octet par octet à la SourceDataLine est très inefficace (la taille de la mémoire tampon est définie dans le
open()
méthode, pas danswrite()
), comme une règle que j'avais toujours écrire une pleine taille de la mémoire tampon pour la SourceDataLine.Après la mise en place de la SourceDataLine, utilisez ce code:
merci pour cet exemple. Et ce qui signifie que si
int n=soundLine.write(buffer, 0, bufferSize);
n renvoie la valeur 0 après 2 premier à écrire?par la spécification de SourceDataLine.write(), il ne peut revenir à moins de la taille de mémoire tampon spécifiée en cas d'erreur (incorrect des paramètres) ou si le SourceDataLine a arrêtés, rincé, ou fermé. Si vous êtes sûr à 100% qu'aucune de ces conditions s'applique, il y a peut-être un bug dans l'implémentation Java de SourceDataLine.
OriginalL'auteur Florian