Crear, Guardar y Reproducir Audio
Descripción
Los equipos actuales cuentan por lo general con un micrófono y alto-parlante. En algunos casos el equipo cuenta con dos canales de micrófono permitiendo grabar en estéreo. En forma similar pueden contar con dos alto-parlantes permitiendo reproducir en estéreo.
En la mayoría de equipos, que no requieren de una alta calidad, se emplean micrófonos tipo electret que se basan en un capacitor y un transistor para amplificar la señal.
Los alto-parlantes integrados en los computadores personales son por lo general de mala calidad. Por ello se observa frecuentemente que se conecten alto-parlantes externos que por lo general incluyen amplificación y pueden hasta incluir un woofer que mejora la emisión en frecuencias entre 60 y 250 Hz.
Java permite escribir rutinas capaces de
- leer la señal de los micrófonos,
- escribir en distintos formatos la información en un archivo
- leer el archivo de audio
- reproducir el contenido del archivo de varios formatos
ID:(1249, 0)
Extensiones de Archivos de Audio
Descripción
Uno de los problemas con archivos de datos es que pueden llegar a usar mucho espacio. Por ello existen algoritmos de compresión que reducen el tamaño de los archivos y con ello ahorran espacio en disco ademas de acelerar la lectura. Por ello existen tres tipos de formatos:
- archivos sin compresión
- archivos comprimidos sin modificación de información
- archivos comprimidos con modificación de información
Ejemplos de los primeros tipos de formatos son WAV (Waveform Audio File Format - asociado a Microsoft e IBM), AIFF (Audio Interchange File Format asociado a Apple),y AU (asociado a SUN).
En el caso se algoritmos de compresión sin modificación de la información se habla de lossless (loss=perdida, less=menor) y archivos tipicos de este tipo de formato son FLAC (Free Lossless Audio Codec)), APE (Monkey's Audio), WV (WavPack), TTA (True Audio), MPEG-4 (Moving Picture Experts Group) y WMA-lossless (Windows Media Audio).
En el caso de algoritmos de compresión con modificación de la información se habla de lossy (lossy=suelto, perdido). La modificación se realiza de modo de reducir el tamaño sin afectar demasiado la calidad del sonido. Ejemplos tipicos son Opus (de Xiph.Org Foundation), MP3 (asociado a los MPEG de Moving Picture Experts Group), Vorbois (de Xiph.Org Foundation), AAC (Advanced Audio Coding), ATRAC (Adaptive Transform Acoustic Coding) y WMA-lossy (Windows Media Audio).
ID:(8824, 0)
Archivos de Audio
Descripción
El archivo de audio contiene por un lado las definiciones que permiten interpretar los datos con que se controla el alto parlante como los datos de la evolución temporal de la amplitud de la señal.
Dentro de los datos que caracterizan esta la frecuencia de muestreo (sampleRate) que indica las veces por segundo que se esta midiendo. Para una grabación simple bastan 8 kHz o 8000 Hz, para una de alta fidelidad se necesita de mínimo 16kHz.
```
float sampleRate = 8000;
```
La medición tiene una exactitud en si. Mientras mayor la exactitud mas tiempo de muestreo se requiere.
Si se desea grabar en mono se debe indicar que se empelara solo un canal de lo contrario se debe indicar 2
```
int channels = 1;
```
Por ello la frecuencia de muestreo y la exactitud del valor medido estan limitados por la velocidad de procesamiento del equipo. La amplitud se maneja en números enteros que pueden o no tener signo (signed) y que tiene un numero de bits definidos (ej. 8 bit).
```
int sampleSizeInBits = 8;
```
La forma como se ordenan los valores en memoria dependen de la convención empelada. Se conocen como el método Big Endian (bigEndian) (se guardan los valores mayores en la memorias mas bajas) y el Little Endian (se guardan los valores menores en las memorias mas bajas)
```
boolean bigEndian = true;
```
La asignación se realiza con la clase AudioFormat.
```
AudioFormat af = new AudioFormat(sampleRate,sampleSizeInBits,channels,signed,bigEndian);
```
Adicionalmente puede ser indicado si se desea firmar o no el registro indicando para la variable signed si es verdad o falsa.
ID:(1248, 0)
Iniciar la Captura
Descripción
Para captar el solido se abre una linea. Para ello se toma el formato que se definió y se configura la linea:
```
AudioFormat format = getAudioFormat();
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
```
luego se obtiene el puntero, se abre y se inicia la captura:
```
line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format);
line.start(); // start capturing
```
ID:(382, 0)
Finalizar la Captura
Descripción
Para terminar se debe detener la grabación y cerrar la linea:
```
line.stop();
line.close();
```
ID:(8825, 0)
Ejemplo Grabar Audio
Descripción
Un ejemplo de capturador de audio con java se presenta a continuación:
import javax.sound.sampled.*;
import java.io.*;
/**
* Programa simple
* author@codejava.net
*/
public class JavaSoundRecorder {
// definir tiempo de grabacion
static final long RECORD_TIME = 60000; // 1 minuto
// crear archivo
File wavFile = new File("E:/Test/RecordAudio.wav");
// crear variable de formato
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
// definir variable para capturar datos
TargetDataLine line;
// definir formato
AudioFormat getAudioFormat() {
float sampleRate = 16000;
int sampleSizeInBits = 8;
int channels = 2;
boolean signed = true;
boolean bigEndian = true;
AudioFormat format = new AudioFormat(sampleRate, sampleSizeInBits,
channels, signed, bigEndian);
return format;
}
// inicio captura
void start() {
try {
AudioFormat format = getAudioFormat();
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
// controlar si sistema soporta
if (!AudioSystem.isLineSupported(info)) {
System.out.println("Line not supported");
System.exit(0);
}
line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format);
line.start(); // start capturing
System.out.println("Start capturing...");
AudioInputStream ais = new AudioInputStream(line);
System.out.println("Start recording...");
// start recording
AudioSystem.write(ais, fileType, wavFile);
} catch (LineUnavailableException ex) {
ex.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
// cierre
void finish() {
line.stop();
line.close();
System.out.println("Finished");
}
public static void main(String[] args) {
final JavaSoundRecorder recorder = new JavaSoundRecorder();
// crear un thread
Thread stopper = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(RECORD_TIME);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
recorder.finish();
}
});
stopper.start();
// detener la grabación
recorder.start();
}
}
ID:(380, 0)
Reproducir Audio
Descripción
Primero se debe cargar los datos, ya sea desde un archivo que puede estar en cualquier lugar (incluido la web):
```
URL url = this.getClass().getClassLoader().getResource("gameover.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
```
o de la memoria
```
byte audio[] = out.toByteArray();
InputStream input = new ByteArrayInputStream(audio);
final AudioFormat format = getFormat();
final AudioInputStream ais = new AudioInputStream(input, format, audio.length / format.getFrameSize());
```
Para reproducir el sonido es necesario cargar el archivo al stream y luego leerlo segmento por segmento: .. se abre la linea
```
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
final SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);
line.open(format);
line.start();
```
ID:(381, 0)
Ejemplo Reproducir Audio
Descripción
Un ejemplo de reproducir audio con java se presenta a continuación:
```
import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;
import javax.swing.*;
public class SoundClipTest extends JFrame {
public SoundClipTest() {
// Frame
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Test Sound Clip");
this.setSize(300, 200);
this.setVisible(true);
try {
// Abrir una secuencia de lectura de audio.
URL url = this.getClass().getClassLoader().getResource("gameover.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
// Obtener recurso de clip de sonido.
Clip clip = AudioSystem.getClip();
// Abra el clip de audio y cargue las muestras de la secuencia de entrada de audio.
clip.open(audioIn);
clip.start();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new SoundClipTest();
}
}
```
ID:(8822, 0)
Ejemplo completo
Descripción
Un modelo simple que captura y reproduce lo grabado se presenta a continuación:
```
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.sound.sampled.*;
public class Capture extends JFrame {
protected boolean running;
ByteArrayOutputStream out;
public Capture() {
super("Capture Sound Demo");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container content = getContentPane();
final JButton capture = new JButton("Capture");
final JButton stop = new JButton("Stop");
final JButton play = new JButton("Play");
capture.setEnabled(true);
stop.setEnabled(false);
play.setEnabled(false);
ActionListener captureListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
capture.setEnabled(false);
stop.setEnabled(true);
play.setEnabled(false);
captureAudio();
}
};
capture.addActionListener(captureListener);
content.add(capture, BorderLayout.NORTH);
ActionListener stopListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
capture.setEnabled(true);
stop.setEnabled(false);
play.setEnabled(true);
running = false;
}
};
stop.addActionListener(stopListener);
content.add(stop, BorderLayout.CENTER);
ActionListener playListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
playAudio();
}
};
play.addActionListener(playListener);
content.add(play, BorderLayout.SOUTH);
}
private void captureAudio() {
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);
}
}
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);
}
}
private void playAudio() {
try {
byte audio[] = out.toByteArray();
InputStream input = new ByteArrayInputStream(audio);
final AudioFormat format = getFormat();
final AudioInputStream ais = new AudioInputStream(input, format,
audio.length / format.getFrameSize());
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
final SourceDataLine line = (SourceDataLine)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() {
try {
int count;
while ((count = ais.read(buffer, 0, buffer.length)) != -1) {
if (count > 0) {
line.write(buffer, 0, count);
}
}
line.drain();
line.close();
} catch (IOException e) {
System.err.println("I/O problems: " + e);
System.exit(-3);
}
}
};
Thread playThread = new Thread(runner);
playThread.start();
} catch (LineUnavailableException e) {
System.err.println("Line unavailable: " + e);
System.exit(-4);
}
}
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);
}
public static void main(String args[]) {
JFrame frame = new Capture();
frame.pack();
frame.show();
}
}
```
ID:(1804, 0)