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:

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:

 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:

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:

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):

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:

 /** * 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:

 /** * 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.

Por Carballude

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

74 comentarios

  1. Hola Carballude. Yo también tengo problemas con el método opened.

    public void opened(Object arg0, Map arg1) {
    if (arg1.containsKey(«audio.length.bytes»)) {
    bytesLength = Double.parseDouble(arg1.get(«audio.length.bytes»).toString());
    System.out.println(bytesLength);

    }
    }

    El problema es que no entra en el if. Y si comento el if cuando va a calcular bytesLength me devuelve java.lang.NullPointerException. Asique supongo que el problema está en «audio.length.bytes». Alguna idea de como solucionarlo y poder obtener el valor de bytesLength. Lo necesito para poder usar el progress.

    Muchas gracias por tu trabajo y por tu tiempo. Me ha ayudado mucho. 1 Saludo

  2. Hola

    He utilizado tu código y funciona correctamente, consigo reproducir cualquier sonido en mp3 o wav, pero tarda demasiado en reproducirse… Casi un segundo…

    ¿Sabéis algún modo de que se reproduzca el sonido justo en el instante en el que se ejecuta el «basicPlayer.play();»?

    Muchas gracias.

  3. Hola! muchas gracias por compartir esta infromacion!. Una consulta, estoy intentando crear un programa que trabaja con mp3 pero me gustaria agregarle la posibilidad de poder hacer que el archivo que se este reproduciendo vaya mas rapido, se te ocurre alguna forma de poder lograrlo? Saludos y discupla la molestia!

  4. o_meigo: Tendrías que usar otro motor de reproducción, uno nativo. Así que tendrías que tirar de JNI y perderla portabilidad.

    link: Bufff… que va, hace mucho que publiqué esto y ya no tengo los fuentes.

    Luis Emilio: Desgraciadamente JLayer no tiene implementada esa funcionalidad. Me temo que tendrás que buscar otro motor de reproducción o bien añadirle esa funcionalidad tú mismo.

    shimo: Puedes escribir plugins para ampliar la compatibilidad… pero tendrías que escribir un plugin por formato. No hay soluciones mágicas :(

  5. Thanks a bunch for sharing this with all people you really understand what you’re speaking about! Bookmarked. Please additionally visit my web site =). We can have a link trade arrangement among us

  6. Hola muy buenas

    Alguien sabe si existe un reproductor de archivos OGG
    para celulares ???

    Esos que usan «.jad + .jar» , ya que tengo como 12 horas buscando por la red y aun no consigo nada , puros reproductores para Symbian u.u

  7. Buenas, necesito una ayuda con la opcion del JSlider ya que no me sirve y no he podido hacer que el bytesLenght muestre algo, Gracias

  8. Hola , como haria para adelantar y retroceder haciendo uso de un JSlider?, e hecho que este se actualise en el método opened y cuando capturo el evento click sobre el JSlider para obtener el tiempo para moverme sobre la cancion sòlo me devuelve el tiempo por donde realmente está, por ejm, quiero ir al minuto 3 de la cancion y van reproduciendoe 5 segundos, me arroja los 5 segundos y la cancion no se fue donde queria.
    Ya realize la prueba de no actualizar el slider en el metodo opened y si funciona, pero yo quisiera que asi como el slider funcione como ayuda grafica para saber cuanto esta avanzando la canciòn, sirva para correr a varios tiempos sobre ella… de antemano gracias

  9. Buen día.
    Tengo que hacer un reproductor que tenga los siguientes puntos:
    -play
    -next
    -previous
    -salir
    -pause
    -stop
    -agregar carpeta
    -eliminar canciones
    -lista nueva
    -guardar lista
    -abrir lista
    -acerca de
    -volumen
    -random
    -buscar
    -agregar después de actual.

    No se por donde empezar, que opinas?

  10. Hola, estos tutoriales me han ayudado muchísimo. Pero me gustaría saber si alguien me puede ayudar a mostrar en un JLabel el tiempo de reproducción de la canción.

    Tu blog esta super bueno. Muchas gracias.

  11. hola Pablo, estoy usando la librería javazoom, la cual reproduce el sonido perfectamente dentro del ide eclipse, pero el problema es que cuando exporto el proyecto como jar ejecutable el sonido no funciona y la app funciona mal. estoy casi seguro que es la librería «common loggin» el problema ya que al probarlo en otros equipos (con las librerías necesarias) el error que me lanza es precisamente esa librería.

    por lo tanto solo funciona en mi pc dentro de eclipse, y te agradecería mucho si pudieras darme alguna solución ya que es para un trabajo de la facultad.

    Gracias.

  12. hola me ha gustado leer varios de tus códigos basados en java acerca de las varias funciones para crear un reproductor mp3 y me a sido de mucha ayuda, quisiera saber si tienes un blog o pagina donde estén todos estos códigos que has subido según su categoría, no se si me expliqué bien, es que solo vi material del reproductor mp3 no se si tienes una pagina de otras cosas interesantes que llamen mi atención y así conocer cosas nuevas! de ante mano agradezco por la información, estoy estudiando programación y me gustan muchos tus post desearía un profesor así ;) !

  13. Воспитание и дрессировка – не жесткая муштра.
    Воспитание животного следует основывать на однократно установленных правилах.

    Если вы завели собаку, можете попробовать начать дрессировать
    ее дома. Если вам нужна исключительно сторожевая собака,
    вместо йоркширского терьера лучше выбрать другую породу собак,
    которая не подвержена риску проблем со здоровьем, если
    она слишком долго живет одна на улице.
    Кулика. Он увидел в Африке необычную собаку, которая, вместо лая, издавала странные
    звуки. Он не натирает шею и помогает развернуть питомца в
    нужную сторону, когда он пытается идти
    в другую. Если вы взяли щенка до 2
    месяцев, то может показаться,
    что он любит спать больше всего на свете.

    Советы кинологов говорят, что для выполнения
    охранных функций собака изначально должна быть недоверчива и до известной
    степени злобной к чужим. Абсолютно любая
    собака должна пройти курс дрессуры,
    независимо от того, будет ли животное участвовать в выставках или просто радовать хозяев.

    Международный курс «Собака-компаньон» – это курс,
    который выгодно отличается тем, что в
    процессе его освоения вам с собакой расскажут
    и покажут, как правильно себя вести не только на дрессировочной площадке,
    но и на улицах города.

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *