Reproducir música (mp3, ogg, wav) en Java

Una de las formas más sencillas de reproducir música (wav, mp3, ogg) en Java, es haciendo uso de «Java Sound» y alguna librería de extensión.

En este caso usaremos la implementación Java Sound, «Tritonus» y la librería de reproducción de mp3 MP3SPI (en caso de querer reproducción OGG deberíamos incluir también VorbisSPI). Para simplificar el proceso, usaremos una librería que proporciona una API de alto nivel para no tener que programar las funciones básicas, BasicPlayer, que usa para ello JLayer.

Resumiendo, descargate jlGui y en el directorio lib tendrás todos los jar que necesitas ;)

Hagamos un ejemplo simple, una clase llamada «Reproductor» controlará la librería y la clase «Test» ordenará cosas a «Reproductor». En este supuesto solamente se podría escuchar una canción al mismo tiempo y no nos preocuparemos de fallos no relacionados directamente con el ejemplo.

En la clase Reproductor, deberíamos tener una variable de Clase de tipo «BasicPlayer» que instanciaremos en el constructor para trabajar con la API BasicPlayer:

1
2
3
4
private BasicPlayer basicPlayer;
public Reproductor() {
 basicPlayer = new BasicPlayer();
}

Deberíamos crear también métodos públicos para «Play», «Stop», «Pause» y «Resume» que seguirían todos la misma estructura:

1
2
3
4
5
6
7
 public void play() {
 try {
  basicPlayer.play();
 } catch (BasicPlayerException e) {
  // TODO Auto-generated catch block  e.printStackTrace();
 }
}

Además de lo anterior, deberemos crear un método para «abrir» el fichero:

1
2
3
public void loadFile(String ruta) throws BasicPlayerException {
 basicPlayer.open(new File(ruta));
}

Con esto, nuestra clase «Test» simplemente tendría que instanciar «Reproductor», llamar a «loadFile» pasándole la ruta a un fichero mp3, ogg o wav y a continuación hacer uso de «Play».

Ahora bien, es muy posible que queramos hacer una interfaz gráfica y añadir una barra de desplacamiento, es decir, saber en punto de la reproducción se encuentra el fichero.

Para ello deberemos implementar la interfaz «BasicPlayerListener» en la clase que elijamos. En el ejemplo la implementaremos en «Reproductor». Por tanto sería:

1
public class Player implements BasicPlayerListener {

Lo que nos obliga a implementar una serie de métodos, pero antes de implementarnos, en el contructor suscribiremos a la clase al reproductor BasicPlayer (recordad que en nuestro diseño solo hay un BasicPlayer al mismo tiempo, pero podría haber varios):

1
2
3
4
5
public Reproductor() {
 basicPlayer = new BasicPlayer();
 // Me suscribo al reproductor para obtener sus eventos.
 basicPlayer.addBasicPlayerListener(this);
}

Además, crearemos la variable de clase bytesLength de tipo double para almacenar el tamaño del fichero. Lo haremos porque BasicPlayer nos dice cuantos bytes ha reproducido hasta el momento.

Uno de los métodos que nos obliga a implementar la interfaz es «opened», que se ejecuta cuando BasicPlayer abre un fichero. Lo usaremos para leer en ese momento los bytes del fichero:

1
2
3
4
5
6
7
 /** * Necesario por implementar BasicPlayerListener. Es ejecutado una vez se
 * carga un fichero. En este caso, obtiene el tamaño en bytes del fichero. */
public void opened(Object arg0, Map arg1) {
 if (arg1.containsKey("audio.length.bytes")) {
  bytesLength = Double.parseDouble(arg1.get("audio.length.bytes").toString());
 }
}

El último método que nos interesa, es «progress», al cual BasicPlayer llama de forma automática varias veces por segundo durante la reproducción. Lo usaremos para obtener el progreso de la canción:

1
2
3
4
5
6
7
8
9
 /** * Necesario por implementar BasicPlayerListener. Según la documentación,
 * este método es llamado varias veces por segundo para informar del
 * progreso en la reproducción. */
public void progress(int bytesread, long microseconds, byte[] pcmdata,  Map properties) {
 float progressUpdate = (float) (bytesread * 1.0f / bytesLength * 1.0f);
 int progressNow = (int) (bytesLength * progressUpdate);
 // Descomentando la siguiente línea se mosrtaría el progreso
 // System.out.println(" -> " + progressNow);
}

Imaginad que queréis usarlo en un jSlider, solamente habría que fijar el máximo del slider en bytesLength y el valor actual en lo que diga progressNow ;)

En fin, espero que os haya sido útil. Si tenéis cualquier duda, ya sabéis que podéis dejar comentarios.

About the Author

Me llamo Pablo Carballude González, soy graduado en computación con master en HCI y Seguridad Informática. Actualmente trabajo para Amazon en Seattle como Software Developer Engineer. Soy de esas personas que no saben si los textos autobiográficos deben ser en primera o tercera persona. Lo intenté en segunda, pero no le entendí nada :P