lunes, 27 de agosto de 2012

Capturar audio de línea de entrada con Java

Hace poco publiqué un artículo en donde muestro la manera de cómo graficar archivos de audio. En este post voy a mostrarles la manera de cómo graficar audio capturado desde un micrófono. La aplicación que usaré será la misma que está posteada en el artículo anterior, con una ligera modificación. Aunque pueda parecer un proceso tedioso, el capturar y graficar audio en tiempo real es una tarea relativamente sencilla. Lo primero que debemos hacer es capturar la entrada de audio de nuestra computadora indicándole un formato determinado.

private void capturarAudio() {
    try {
        final AudioFormat format = getFormat();
        DataLine.Info info = new DataLine.Info(
                TargetDataLine.class, format);
        final TargetDataLine line = (TargetDataLine) AudioSystem.getLine(info);
        line.open(format);
        line.start();
        Runnable runner = new Runnable() {

            int bufferSize = (int) format.getSampleRate()
                    * format.getFrameSize();
            byte buffer[] = new byte[bufferSize];

            public void run() {
                out = new ByteArrayOutputStream();
                running = true;
                try {
                    while (running) {
                        int count =
                                line.read(buffer, 0, buffer.length);
                        if (count > 0) {
                            out.write(buffer, 0, count);
                        }
                        graficarBytes(buffer);
                    }
                    out.close();
                } catch (IOException e) {
                    System.err.println("I/O problems: " + e);
                    System.exit(-1);
                }
            }
        };
        Thread captureThread = new Thread(runner);
        captureThread.start();
    } catch (LineUnavailableException e) {
        System.err.println("Line unavailable: " + e);
        System.exit(-2);
    }
}

Ahora debemos determinar el formato de la captura de audio. Lo podemos hacer mediante el siguiente método:

private AudioFormat getFormat() {
    float sampleRate = 8000;
    int sampleSizeInBits = 8;
    int channels = 1;
    boolean signed = true;
    boolean bigEndian = true;
    return new AudioFormat(sampleRate,
            sampleSizeInBits, channels, signed, bigEndian);
}

Hecho esto ya podemos acceder al arreglo de bytes que componen los frames de audio que han sido capturados. Para realizar la graficación del espectro podemos utilizar la aplicación  que de la que comenté al incio de este post. Aquí les comparto un video que muestra el funcionamiento del software grabando voces en una casa en la que según me dijeron habitan fantasmas y cuya historia compartiré en otro post.


También les dejo el archivo del proyecto desarrollado en netbeans para que puedan tener una idea más clara de este proceso y lo puedan aplicar en otras situaciones.

 

11 comentarios:

Anónimo dijo...

Hola, me llamo Manuel y en primer lugar, muchas gracias por tu aportación, me resulta de gran ayuda ya que no es fácil encontrar muchos aportes sobre este tema en JAVA. Estoy trabajando en un proyecto que captura el sónido del micrófono y que al mismo tiempo tiene que hacer dos cosas, por un lado grabar el audio en un fichero y por otro representar en tiempo real en un Vúmetro el volumen de la señal entrada. Mas o menos lo voy consiguiendo, pero tengo un problema y es que si lanzo las dos tareas de forma simultanea el pintado es muy lento y no resulta real y la grabación pierde calidad. Mi duda es si es posible trabajar con dos hilos sobre la misma entrada y compartir el mismo TargetDataLine y si no es posible hacerlo, ¿como se debería hacer? porque me da la impresión que usando el mismo TargetDataLine se pierden muestras y pierdo calidad en ambas tareas. No se si me he conseguido explicar.
Muchas gracias y un saludo.

Rolando Palermo Rodríguez Cruz dijo...

Buenos días amigo, te dejo unos enlaces que podrían ser de utilidad:
http://www.jsresources.org
http://www.jsresources.org/examples/SimpleAudioRecorder.java.html
http://www.developer.com/java/other/article.php/2173111/Java-Sound-Playing-Back-Audio-Files-using-Java.htm
No dejes de comentar los avances en tu proyecto.

Anónimo dijo...

Hola,

Gracias por los enlaces, voy a ponerme con ellos y te comento.

Un saludo

Luis dijo...

Hola muy nombre es luis, llevo un par de semanas casi casi un mes para ser exacto, buscando lo forma de ver la frecuencia en Hrz de la entrada de micrófono. ¿cual es el tipo de señal que recoge el programa??
y siendo la que sea como hago para pasarlas en Hrz ¿??

espero puedas ayudarme, mi correo de contacto de_lus_guitar@hotmail.com

Muchas gracias :)

Anónimo dijo...

Hola, mi nombre es Javier. Un muy buen trabajo el que muestras. Me ha servido mucho. Una pregunta, cómo podría cambiar la fuente de grabación, por ejemplo, que en lugar de que grabara lo que se escucha en el equipo, grabara lo que se escucha en el micrófono. O no sé si exista una forma de grabar las dos al mismo tiempo. A mi se me ocurre poner un subproceso distinto a grabar la otra entrada de audio, pero no logro encontrar información de como seleccionar desde Java la fuente de audio que será grabada, ya que por defecto, Java utiliza la que el equipo tiene configurada de forma predeterminada. Bueno, te agradezco cualquier información que puedas proporcionar.

Anónimo dijo...

Hola estoy impresionado con tu trabajo, realmente muy bueno! Tendras el proyeto o codigo fuente entero de este nuevo programa, ya estuve usando el analizador de espectro y me va de maravillas! O me puedes explicar que cambiar en el codigo del analizador para capturar sonido dsd un mic!! Soy nuevo en JAVA!! Graciass

Anónimo dijo...

Hola amigo .... quisiera saber si existe alguna forma de saber la frecuencia de un sonido ingresado a través de un micrófono ... utilizando java .... por ejemplo cuando toco la cuerda de una guitarra ... que me diga entre que frecuencias esta sonando gracias ........ mi correo vemalavers@unc.edu.pe

Alexandro Garcia dijo...

que tal colega es muy interesante tu proyecto actualmente tengo un proyecto en la universidad, el involucra reconocimiento de voz lo cual ya tengo resuelta pero necesito analizar los espectros frecuencia de la voz, para compararlas tu programa gráfica muy bien los espectros y me interesaría utilizarlo y ponerme en contacto contigo para saber mas de el tema y de tu código si te pusieras en contacto con migo seria de mucha utilidad mi correo es alexandro.garcia.mrs@gmail.com

German Rodriguez dijo...

Buenos dias.

Primero que nada, muchas gracias por el aporte,
Actualmente esto haciendo mi resis de grado y la principal caracteristica es que puede comparar sonidos de una guitarra con alguno que este en mi base de datos, con el fin de que el usuario sepa si esta o no tocando bien la guitarra.
He revisado el fuente del reproductor y ahora revisare este, aunque ya con el reproductor pense como utilizarlo en mi tesis, pero en la teoria no se si este correcto
lo que planeo hacer es:
Crear una funcion que obtenga lo mismo que drawSpectrumAnalyser (pero los dos sonidos), hacer el fft.calculate(pSample), y a partir de los datos del fft... ir calculando...
La primera pregunta es: Yo puedo utilizar esos datos para saber si dos sonidos se asemejan ? si son parecidos?, o la comparacion no seria cierta ?
La segunda es: De donde salen los arreglos para stereoMerge(byte[],byte[]) que terminara siendo float[] pSample.

Muchas gracias saludos, seria de gran ayuda para mi tesis.
Mi correo : garodriguezr.11@gmail.com o german_deportivo@hotmail.com

Anónimo dijo...

Donde guarda el audio grabado???????????

Alejandro Mondragon Perez dijo...

me podrían ayudar lo que pasa es que no puedo hacer eso en java con netbeans no se si me podrían pasar algo explicado paso a paso.

Publicar un comentario