studio sonidos sonido reproducir programacion móviles desarrollo curso como aplicaciones agregar java swing audio javasound clip

java - sonidos - Reproducción de múltiples clips de sonido con objetos Clip



programacion android pdf 2018 (2)

El clip por botón debería estar bien. Cuando el usuario hace clic en el botón, ejecuta esto para reiniciar el clip:

sound.stop(); sound.setFramePosition(0);// set the location to the start of the file sound.play();// restart your sound

Estoy desarrollando un programa que tiene numerosos objetos JButton, y quiero que cada uno corresponda con su propio archivo .wav . Además, quiero que los sonidos funcionen de manera tal que puedan superponerse con los sonidos de otros botones, pero no puede superponerse consigo mismo (al hacer clic en un botón mientras se reproduce su sonido se reiniciará el sonido).

Intenté usar un solo objeto Clip pero tuve problemas para lograr lo que dije anteriormente. Como resultado, recurrí a declarar un nuevo objeto Clip para cada botón, pero tengo la sensación de que esta es una solución bastante ineficiente para mi problema.

¿Cómo puedo lograr lo que dije en el primer párrafo de la manera más eficiente?


Hay un par de formas en que puede lograr esto, pero la idea básica es que desea registrar un LineListener en un Clip y monitorear el evento LineEvent.Type.STOP y volver a habilitar el botón

Por ejemplo. Esto busca todos los archivos .wav en un directorio dado y crea un botón para cada uno. Cuando se hace clic, el botón (o más importante, la Action subyacente) se desactiva y se reproduce el audio. Cuando se STOP , la Action (y el botón por extensión) se vuelve a habilitar.

Sound API puede reproducir múltiples sonidos simultáneamente de todos modos

import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.Logger; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; import javax.sound.sampled.LineEvent; import javax.sound.sampled.LineListener; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.UnsupportedAudioFileException; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class Test { public static void main(String[] args) { new Test(); } public Test() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { public TestPane() { File[] musicFiles = new File("a directory somewhere").listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.getName().toLowerCase().endsWith(".wav"); } }); setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.fill = GridBagConstraints.HORIZONTAL; for (File music : musicFiles) { try { JButton btn = new JButton(new AudioAction(music.getName(), music.toURI().toURL())); add(btn, gbc); } catch (MalformedURLException ex) { ex.printStackTrace(); } } } } public class AudioAction extends AbstractAction { private URL audio; public AudioAction(String name, URL audioSource) { super(name); this.audio = audioSource; } public URL getAudioSource() { return audio; } @Override public void actionPerformed(ActionEvent e) { setEnabled(false); try (InputStream is = getAudioSource().openStream()) { AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(is); Clip play = AudioSystem.getClip(); play.addLineListener(new LineListener() { @Override public void update(LineEvent event) { System.out.println(event.getFramePosition()); if (event.getType().equals(LineEvent.Type.STOP)) { setEnabled(true); } } }); play.open(audioInputStream); play.start(); } catch (IOException | LineUnavailableException | UnsupportedAudioFileException exp) { exp.printStackTrace(); } } } }

Nota: Intenté usar Clip#drain (en un hilo de fondo), pero solo funcionó para el primer clip, los clips posteriores básicamente omitieron el método, por lo que LineListener

Ahora con mejor gestión de recursos

import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.logging.Level; import java.util.logging.Logger; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; import javax.sound.sampled.LineEvent; import javax.sound.sampled.LineListener; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.UnsupportedAudioFileException; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class Test { public static void main(String[] args) { new Test(); } public Test() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { public TestPane() { File[] musicFiles = new File("...").listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.getName().toLowerCase().endsWith(".wav"); } }); setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.fill = GridBagConstraints.HORIZONTAL; for (File music : musicFiles) { try { JButton btn = new JButton(new AudioAction(music.getName(), music.toURI().toURL())); add(btn, gbc); } catch (MalformedURLException exp) { exp.printStackTrace(); } } } } public class AudioAction extends AbstractAction { private AudioPlayer player; public AudioAction(String name, URL audioSource) { super(name); player = new AudioPlayer(audioSource); } @Override public void actionPerformed(ActionEvent e) { if (player.isPlaying()) { player.stop(); } else { try { player.play(); } catch (IOException | LineUnavailableException | UnsupportedAudioFileException ex) { ex.printStackTrace(); } } } } public class AudioPlayer { private Clip clip; private URL url; public AudioPlayer(URL url) { this.url = url; } public boolean isPlaying() { return clip != null && clip.isRunning(); } protected void open() throws IOException, LineUnavailableException, UnsupportedAudioFileException { clip = AudioSystem.getClip(); clip.open(AudioSystem.getAudioInputStream(url.openStream())); } public void play() throws IOException, LineUnavailableException, UnsupportedAudioFileException { if (clip == null || !clip.isRunning()) { open(); clip.setFramePosition(0); clip.start(); } } public void stop() { if (clip != null && clip.isRunning()) { clip.stop(); clip.flush(); dispose(); } } public void dispose() { try { clip.close(); } finally { clip = null; } } } }