Download Sonido en Java. - Página personal de Carlos Prades del Valle.

Document related concepts
no text concepts found
Transcript
Sonido en JAVA.
Escrito por:
Carlos Prades del Valle.
Versión 1.0.0.
Enero de 2001.
Sonido en Java.
Versión 1.0.1 Enero 2000
Historial del documento.
Versión
Autor
Resumen de la modificación.
Fecha
1.0.0.
CPV
Guía para el programador de sonido con Java.
19−12−2000
1.0.1.
CPV
Revisión de estilos para subirlo a la web.
31−01−2001
Autores del documento.
CPV:
Carlos Prades del Valle.
e−mail: [email protected]
Sitio web: http://cprades.eresmas.com/
Resumen.
Este documento es una guía para el programador que quiere empezar a utilizar el
sonido que le proporciona el sistema multimedia que utiliza.
Palabras relacionadas.
Java, programación, sonido, procesado, voz, señal, api.
Carlos Prades del Valle.
Pag 2 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
Índice.
1INTRODUCCIÓN.___________________________________________________________7
2CLASES PRINCIPALES._____________________________________________________8
2.1FORMATOS DE AUDIO.________________________________________________________8
2.2ARQUITECTURA DE LOS SISTEMAS.________________________________________________9
2.3MIXERS__________________________________________________________________9
2.4LINES__________________________________________________________________10
2.5CLASES DATALINE_________________________________________________________11
3ACCESO A LOS COMPONENTES DEL SISTEMA_____________________________12
3.1OBTENCIÓN DE LOS RECURSOS._________________________________________________13
4REPRODUCCIÓN DE SONIDO.______________________________________________15
4.1REPRODUCCIÓN DEL SONIDO MEDIANTE SOURCEDATALINE_____________________________15
4.2SINCRONIZACIÓN DE LÍNEAS.__________________________________________________17
4.3CAPTURA DE SONIDO._______________________________________________________17
4.4PROCESADO DE LA SEÑAL.____________________________________________________18
Carlos Prades del Valle.
Pag 3 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
Glosario.
API: Application Program Interface. Es la interfaz proporcionada por un sistema al
programador para poder acceder a los servicios de ese sistema.
Array: Es un grupo de datos de un tipo determinado puestos uno a continuación de
otro. Coincide con los tipos de datos array de Java.
Java: Lenguaje de programación orientado a objetos.
JDK: Java Development Kit. Es el entorno de desarrollo para Java proporcionado por
Sun.
MIDI: Estándar para el almacenamiento y transporte de música para o desde un
sintetizador.
Package: Paquete. Agrupamiento especificado por el programador de clases con
características comunes.
Sun: Empresa norteamericana que desarrolló el lenguaje de programación Java.
Thread: Hilo de ejecución.
Carlos Prades del Valle.
Pag 4 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
Ámbito y alcance del documento.
Este documento pretende mostrar cómo utilizar las herramientas del API de Java
para la adquisición el manejo y la reproducción de sonido, el texto se limita a esta
función quedando fuera del propósito el almacenamiento, la síntesis de sonido, el
tratamiento de secuencias MIDI, el tratamiento (reconocimiento y síntesis) de la señal
de voz, etc. No es una descripción detallada de todos las clases, métodos y variables que
proporciona el sistema sino una guía útil para el programador que pretenda iniciarse en
el procesado de sonido con Java o cómo texto de referencia para el programador más
experto.
La versión de Java que soporta este API como aquí se cuenta es la 2 y el entono
de desarrollo utilizado es el JDK 1.3.
Este documento presupone que el lector tiene un conocimiento medio sobre el
lenguaje Java siendo recomendable un conocimiento básico del API más común. Por
otro lado el lector deberá tener un conocimiento mínimo sobre las características de la
señal de sonido y el tratamiento digital de la señal.
Carlos Prades del Valle.
Pag 5 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
Convenciones del documento.
En este documento se intentará traducir los términos en inglés siempre que sea
posible, exceptuando aquellos términos en inglés que, por el uso común en nuestro
idioma, no necesitan tal traducción. Estos vocablos están escritos en cursiva. Por otro
lado los nombres propios de las compañías comerciales o de las marcas de sus
productos también son puestos en cursiva.
La parte de código y los ejemplos están escritos con fuente de letra Curier.
Cuando se habla de una clase o de un objeto se considera un nombre propio por lo que
no se traduce, aún así en determinados casos se especifica la traducción de forma
aclaratoria. Los nombre de paquetes y ficheros también se consideran nombres propios,
pero al no pertenecer exclusivamente al código se muestran con fuente de letra normal
en cursiva (como productos software que son).
Carlos Prades del Valle.
Pag 6 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
1 Introducción.
El API de Java dedicada al sonido es la llamada Java Sound API proporcionado
ya con el entorno de desarrollo de Sun. Este API se compone de 4 packages (paquetes):
javax.sound.sampled.
javax.sound.sampled.spi.
javax.sound.midi.
javax.sound.midi.spi.
El primero, javax.sound.sampled, contiene las clases necesarias para el manejo
del sonido muestreado, esto incluye la captura, la mezcla y la reproducción de audio,
proporcionando además algún control y efecto sobre el sonido así como interfaces para
el almacenamiento, será el package estudiado en este documento. El package
javax.sound.midi proporciona las interfaces de síntesis, secuenciamiento y transporte
MIDI. Los packages javax.sound.sampled.spi y javax.sound.midi.spi proporcionan una
interfaz para los desarrolladores de servicios basados en las interfaces anteriores.
Carlos Prades del Valle.
Pag 7 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
2 Clases principales.
Como paso previo es necesario contar cómo funcionan algunos de los objetos de
javax.sound.sampled necesarios para comprender después cada uno de los
procedimientos a seguir.
2.1 Formatos de audio.
Los objetos de la clase AudioFormat definen el formato de una señal de
audio, esto es, el número de canales, el número de bits por muestra, frecuencia de
muestreo, el tamaño de la trama de voz y su frecuencia, formato de almacenamiento de
los datos en memoria (big endian o little endian) y el tipo de codificación (ley a, ley µ,
PCM). Para guardar el tipo de codificación hay un objeto de la clase
AudioFormat.Encoding con esta información. Obteniendo este objeto se puede
mirar si es igual (función boolean equals(Object) ) a una de las constantes
definidas en la clase AudioFormat.Encoding (ALAW, ULAW, PCM_SIGNED,
PCM_UNSIGNED). La clase AudioFormat aparte del constructor, al que hay que
pasarle los parámetros para la iniciación de las variables, tiene los siguientes métodos:
int getChanels();
/* Devuelve el número de canales. */
AudioFormat.Encoding getEncoding(); /* Devuelve objeto con información
sobre el tipo de codificación.*/
float getFrameRate();
/* Devuelve la frecuencia de trama de la señal.
*/
int getFrameSize();
/* Devuelve tamaño de la trama en bytes. */
float getSampleRate();
/* Devuelve la frecuencia de muestreo. */
int getSampleSizeInBits(); /* Devuelve el tamaño en bits de cada
muestra de sonido. */
boolean isBigEndian();
/* Devuelve true alineamiento big endian y
false little endian. */
Además de los métodos boolean maches(AudioFormat) y String
toString() y los heredados de la clase Object.
Por otro lado existe la clase AudioFileFormat para definir el formato de un
fichero de audio, esta clase permite utilizar las clases AudioImputStream y
AudioOutputStream, que heredan de ImputStream y OutputStream
respectivamente, permitiendo usar los métodos estándar para la lectura y escritura del
audio en ficheros. El funcionamiento de estas clases se escapa al ámbito de este
documento.
Carlos Prades del Valle.
Pag 8 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
2.2 Arquitectura de los sistemas.
La arquitectura de los sistemas de audio de audio se basa en mezcladores, clase
Mixer, que son dispositivos a los que llegan líneas, objetos de clase Line, procesan
los datos y salen otros objetos de clase Line.
La jerarquía de estas clases es la siguiente:
Object
Line
Port
Mixer
DataLine
SourceDataLine
TargetDataLine
Clip
2.3 Mixers
Como se puede ver los Mixer (mezcladores) son unos casos particulares de los
Lines. Estos Mixer son dispositivos hardware o software por lo que pueden ser
proporcionados por el sistema. Los objetos Mixer contienen un objeto de la clase
Mixer.Info con información del tipo de Mixer. Los métodos de la clase Mixer
son los siguientes:
Line getLine(Line.Info); /* Obtiene, si exixte, un Line del tipo
indicado en el parámetro. */
int getMaxLines(Line.Info);
/* Indica el numero de lineas que se
pueden tener de un tipo dado.*/
Mixer.Info getMixerInfo();
/* Obtiene el objeto que indica el
tipo de Mixer que es. */
Line.Info [] getSourceLineInfo(); /* Obtiene array con información de
los SourceLines disponibles. */
Line.Info [] getSourceLineInfo(Line.Info); /* Array con información de
los SourceLines de un tipo. */
Line [] getSourceLines(); /* Obtiene array con los SouceLines
disponibles. */
Line.Info [] getTargetLineInfo(); /* Obtiene array con información de
los TargetLines disponibles. */
Line.Info [] getTargetLineInfo(Line.Info); /* Array con información de
los TargetLines de un tipo. */
Line [] getTargetLines(); /* Obtiene array con los TargetLines
disponibles. */
boolean isLineSupported(Line.Info); /* Devuelve true si tiene un Line
del tipo especificado. */
boolean isSincronizationSupported( Line[], boolean); /* Devuelve true
Carlos Prades del Valle.
Pag 9 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
si se soporta sincronización entre las
lineas especificadas en el primer parámetro,
el segundo parámetro indica el tipo de
sincronización: muestra a muestra si es true
o sólo en los metodos start() y stop() si es
false. */
void sincronize(Line[], boolean); /* Sincroniza las lineas especificadas
en el primer parámetro, el segundo
parámetro indica el tipo de sincronización:
muestra a muestra si es true o sólo en los
metodos start() y stop() si es false. */
void unsincronize(Line[]);
/* Desincroniza las lineas indicadas. */
2.4 Lines
Un Line (línea) es una conexión por la que pasa la señal desde o hacia un
Mixer. Los tipos de Lines son los siguientes:
Port: Puertos de entrada o salida del sistema como el micrófono, la salida de
línea, el altavoz, etc.
DataLine: Líneas de datos, pueden ser Clips que almacenan un sonido
completo, SourceDataLine que proporcionan un buffer de entrada a un Mixer y
TargetDataLine que proporcionan el buffer de salida de un Mixer.
Mixer: Mezclador que representa un dispositivo hardware o software del
sistema.
Los Lines proporcionan cierta funcionalidad al sistema por medio de objetos
Control que incluyan capaces de variar alguna característica del sonido (ganancia,
reverberación, etc.), del estado (el Status) que puede ser abierto y cerrado (Open y
Closed) de tal manera que si el Line está cerrado no consume recursos del sistema y
por último por medio de los objetos Event (eventos) lanzados que permiten
comunicación y sincronización con otros objetos.
Como ya veremos los objetos Line tienen un objeto (de clase Line.Info) de
información sobre ellos. Como ocurre con la mayor parte de los atributos y métodos, el
objeto de información se redefine en los objetos que lo heredan siendo de tipo
Mixer.Info, Port.Info, etc. en cada uno de los casos.
Los métodos de la clase Line son:
void addLineListener( LineListener); /* Especifica un objeto al que se le
envían los Event generados. */
void close();
/* Cierra (pasa a Status Closed) el objeto Line.
*/
Carlos Prades del Valle.
Pag 10 de 19
Sonido en Java.
Control getControl( Control.Type);
tipo
Versión 1.0.1 Enero 2000
/* Devuelve un objeto Control del
especificado. */
Control [] getControls();
/* Devuelve un array con los objetos
Control disponibles. */
Line.Info getLineInfo();
/* Devuelve información del objeto. */
boolean isControlSupported(Control.Type); /* Devuelve true si soporta el
tipo de Control especificado. */
boolena isOpen(); /* Devuelve true si el Status es Open. */
void open();
/* Abre (pasa a Status Open) el objeto Line.*/
void removeLineListener(LineListener); /* Deja de enviar objetos Event al
LineListener especificado. */
2.5 Clases DataLine
La los objetos de la clase DataLine son las conexiones entre los Mixer y
nuestro sistema. Estos objetos tienen un buffer de datos, un proceso de control interno,
y una interfaz con el usuario. Como es lógico heredan todos los métodos de la clase
Line pero además implementan los siguientes:
int available();
/* Indica el número de bytes que que están libres
en el buffer interno. */
void drain();
/* Este método sirve bloquea el objeto hasta que
quede limpio el buffer. */
void flush();
// Este metodo limpia el buffer.
int getBufferSize();
// Devuelve el tamaño del buffer en bytes.
AudioFormat getFormat(); // Devuelve el formato del audio manejado.
int getFramePosition(); // Devuelve la posición de la trama
float getLevel();
// Devuelve el nivel de la señal
long getMicrosecondPosition(); /* Obtiene la posición actual de los datos
de audio en microsegundos. */
boolean isActive();
/* Devuelve true si estan pasando datos
(ejecutado el comando start) */
boolean isRunning();
// Devuelve true si está abierto
void start();
// Comienza la reproducción
void stop();
// Termina la reproducción
Carlos Prades del Valle.
Pag 11 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
3 Acceso a los componentes del sistema
Para acceder a los componentes del sistema la clase AudioSystem
proporciona a la aplicación un punto de entrada a los componentes instalados en el
sistema. Se puede obtener información de los objetos Mixer instalados y objetos Line
(sin tener que especificar el Mixer al que están asociados), proporciona métodos para
realizar las conversiones de formato y métodos para trasladar el sonido a objetos
Stream o File para el transporte, comunicación o almacenamiento. Los métodos
accesibles de esta clase son:
static AudioFileFormat getAudioFileFormat(java.io.File);
static AudioFileFormat getAudioFileFormat(java.io.InputStream);
static AudioFileFormat getAudioFileFormat(java.net.URL);
/* Devuelven un objeto con el formato del fichero especificado en el
parámetro. */
static AudioFileFormat.Type[] getAudioFileTypes();
static AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream);
/* Devuelve los tipos de ficheros soportados por el sistema (sin
parámetro) o por el parámetro. */
static AudioInputStream getAudioInputStream(AudioFormat, AudioInputStream
);
static AudioInputStream getAudioInputStream(AudioFormat.Encoding,
AudioInputStream);
// Devuelve un AudioImputStream
static AudioInputStream getAudioInputStream(java.io.File);
static AudioInputStream getAudioInputStream(java.io.InputStream);
static AudioInputStream getAudioInputStream(java.net.URL);
// Devuelve un AudioInputStream asuciado a un fichero
static Line getLine(Line.Info);
// Obtiene un objeto Line del tipo especificado en el parámetro.
static Mixer getMixer(Mixer.Info);
// Obtiene un objeto Mixer del tipo especificado en el parámetro.
static Mixer.Info[] getMixerInfo();
/* Obtiene un array con la información de los objetos Mixer existentes
en el sistema. */
static Line.Info[] getSourceLineInfo(Line.Info p1);
/* Obtiene un array con la información de los objetos Line existentes
en el sistema. */
static AudioFormat.Encoding[] getTargetEncodings(AudioFormat);
static AudioFormat.Encoding[] getTargetEncodings(AudioFormat.Encoding);
/* Obtiene los tipos de codificación sopurtados para un determinado
formato de audio. */
static AudioFormat[] getTargetFormats(AudioFormat.Encoding, AudioFormat);
/* Obtiene los objetos AudioFormat de un determinado tipo. */
static Line.Info[] getTargetLineInfo(Line.Info);
Carlos Prades del Valle.
Pag 12 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
/* Obtiene información de los objetos TargetLine de un determinado
tipo. */
static boolean isConversionSupported(AudioFormat, AudioFormat);
static boolean isConversionSupported(AudioFormat.Encoding, AudioFormat);
/* Devuelve true si se permite la canversión entre los formatos
especificados. */
static boolean isFileTypeSupported(AudioFileFormat.Type);
static boolean isFileTypeSupported(AudioFileFormat.Type,
AudioInputStream);
/* Devuelve true si se soporta el tipo de formato de fichero (para el
AudioInputStream en el segundo caso). */
static boolean isLineSupported(Line.Info);
/* Devuelve true si en el sistema existe un objeto Line del tipo
especificado. */
static int write(AudioInputStream, AudioFileFormat.Type, java.io.File);
static int write(AudioInputStream, AudioFileFormat.Type,
java.io.OutputStream);
/* Graba los datos de audio en un fichero o en un OutputStream según
el formato especificado. Devuelve el número de datos guardados. */
Para poder acceder a los distintos objetos del sistema se crean las clases de
información, cuyas instancias proporcionan información sobre las distintas interfaces.
Estas interfaces son Line.Info y las clases derivadas Mixer.Info, Port.Info y
DataLine.Info.
3.1 Obtención de los recursos.
Para obtener un objeto de la clase Mixer se puede conseguir un array de
objetos Mixer.Info con todos los Mixer soportados por el sistema por medio del
método getMixerInfo() de la clase AudioSystem. Con este array podemos
elegir el Mixer que nos interese y obtenerlo con el método getMixer(
Mixer.Info) de la clase AudioSystem.
Para obtener un objeto Line de un determinado tipo podemos obtenerlo de un
Mixer (ver apartado dedicado a los objetos Mixer) o de la clase AudioSystem con
el método getLine(Line.Info). Se puede construir un objeto DataLine.Info
indicando
en
el
constructor
la
clase
del
objeto
del
que
informa
(TargetDataLine.class o SourceDataLine.class) y un objeto de la clase
AudioFormat. Es conveniente ver si un objeto Line del tipo deseado se soporta por
el sistema, para ello se utiliza el método isLineSupported() de la clase
AudioSystem antes de intentar obtenerlo. La clase Port.Info proporciona unas
constantes (instancias final static de clase Port.Info) que definen algunas
Carlos Prades del Valle.
Pag 13 de 19
Sonido en Java.
líneas
básicas
Versión 1.0.1 Enero 2000
(Port.Info.COMPACT_DISC,
Port.Info.HEADPHONE,
Port.Info.LINE_IN, Port.Info.LINE.OUT y Port.Info.SPEAKER).
Para obtener un array con información de las líneas existentes en el sistema se
usan las funciones getTargetLineInfo() y getSourcetLineInfo(), de la
clase AudioSystem, pasándoles los tipos de líneas que nos interesan. Por otro lado,
los objetos Mixer implementan los métodos getTargetLineInfo() y
getSourcetLineInfo() que no necesitan parámetros y que devuelven
información sobre sus objetos Line. Con el método getLine(), del objeto Mixer,
pasando como parámetro el Line.Info adecuado se obtiene la referencia al objeto
Line deseado.
Con estos datos es posible obtener un Line y manipularlo abriéndolo,
cerrándolo, etc. Hay que advertir que no es aconsejable cambiar el Status de los Ports
ya que un usuario puede tener abierto o cerrado estos puertos por conveniencia
molestándole si la aplicación los cambia de estado sin su consentimiento.
Carlos Prades del Valle.
Pag 14 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
4 Reproducción de sonido.
Antes de entrar en la reproducción de sonido por medio de objetos
SourceDataLine hay que hacer mención as los objetos Clip. Un objeto de esta clase
está pensado para almacenar el audio grabado de principio a fin, es la mejor solución
cuando se conoce de antemano el tamaño de la señal a almacenar y es única, así como
cuando se desea repetir un sonido varias veces (por ejemplo en un lazo). Los ejemplo
típico de utilización es la reproducción de sonido de ficheros no demasiado grandes, en
este caso se lee el contenido del fichero en un clip y luego se reproduce, el control es
más sencillo y los recursos utilizados son menores. Sin embargo en los casos donde el
audio es continuo o en ficheros de un gran tamaño es preferible usar los otros tipos de
DataLine (SourceDataLine o TargetDataLine) con el fin de no ocupar
demasiada memoria del sistema. En nuestro caso nos centraremos en este segundo caso
ya que nuestra fin es la adquisición tratamiento y reproducción de la señal siéndonos de
poca utilidad la clase Clip.
4.1 Reproducción del sonido mediante SourceDataLine
Los objetos SourceDataLine son la entrada de objetos Mixer, siendo
necesario escribir en ellos los datos que se introducen en el Mixer. Los métodos de
estos objetos son:
void open(AudioFormat);
void open(AudioFormat, int);
// Redefinen el metodo de abir de Line pasando el formato de audio
//que van a manejar y, opcionalmente, el tamaño en bytes del buffer.
int write(byte [ ], int, int);
// Escribe los datos en el buffer (ver texto a continuación).
El proceso a realizar para la escritura de datos en el SourceDataLine una
vez obtenido es el siguiente:
Se procede a abrirlo con el método propio open(AudioFormat) o
open(AudioFormat, int) donde el entero indica el tamaño del buffer en bytes, si
no se utilizan argumentos se pone un formato por defecto. Para conocer estos datos se
pueden utilizar los métodos getFormat() y getBufferSize() del objeto
SourceDataLine.
Con el método start() la línea empezará a reproducir sonido en cuanto tenga
algo en el buffer. Para poner datos en el buffer se usa el método int write(byte
[] b, int offset, int length) donde b es el array de datos, offset indica a
Carlos Prades del Valle.
Pag 15 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
partir de donde, en el array b, se debe empezar a leer datos y length indica cuantos
datos deben ser leídos. Esta función devuelve el número de datos leídos. Es muy
importante tener en cuenta que todos estos datos vienen en bytes y no en número de
muestras.
Cuando sale la primera muestra del objeto Mixer (un instante después de salir
del SourceDataLine) se produce un evento de tipo START que puede ser recogido
por el proceso a la salida del Mixer.
El método write() vuelve sólo cuando ha escrito todos los datos en el buffer.
Si se intenta escribir más datos de los que caben en el buffer el método se bloquea hasta
terminar. Para evitarlo con el método available() se obtiene, en bytes, el tamaño
de la parte que queda libre en el buffer.
Con el método drain() el programa se bloquea hasta reproducir el sonido,
vaciando el buffer antes de volver. Con el método stop() se para la reproducción, sin
limpiar el buffer, y con start() continúa dónde se quedó, para evitar la reproducción
de un segmento antiguo al llamar a start() se puede utilizar el método flush()
que limpia el buffer. Todos estos métodos de SourceDataLine son heredados de
DataLine.
Cuando deja de salir señal del Mixer procedente del SourceDataLine se
genera un evento de tipo STOP.
El método isActive() devuelve true si están saliendo datos (entre los
eventos de tipo START y STOP), el método isRunning() devuelve true si la línea
está abierta. Además Line genera eventos de tipo OPEN y CLOSE al llamarse a las
funciones correspondientes. Todos los eventos pertenecen a la clase LineEvent y les
debe de atender un objeto que implemente la interfaz LineListener. Para
registrarlos se llama a la función de la clase Line, addLineListener(), pasando
como parámetro el objeto LineListener.
La
interfaz
LineListener
sólo
define
un
método:
void
update(LineEvent). Los objetos LineEvent implementan los métodos:
final long getFramePosition(); // Obtiene la osicion de la trama
final Line getLine();
// Obtiene el objeto Line que lanzó el evento.
final LineEvent.Type getType(); // Obtiene el tipo de evento
LineEvent(Line, LineEvent.Type, long); // Constructor
java.lang.String toString();
// Obtiene un String para la
representación
Carlos Prades del Valle.
Pag 16 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
El tipo de evento es un objeto de clase LineEvent.Type, esta clase tiene
definida las constantes LineEvent.Type.CLOSE, LineEvent.Type.OPEN,
LineEvent.Type.START y LineEvent.Type.STOP.
4.2 Sincronización de líneas.
La sincronización de líneas permite que la reproducción se realice al mismo
tiempo, esta sincronización puede ser mantenida o no. La sincronización se llama
mantenida cuando es una sincronización muestra a muestra, es decir, durante toda la
reproducción las muestras de ambas líneas salen a la par. La sincronización no
mantenida es aquella en la que sólo se sincronizan los procesos de start() y
stop().
Para ver si varios objetos Line se pueden sincronizar se utiliza el método, del
un
objeto
Mixer,
isSinchronizationSupported()(
Line
[],
boolean) al que se le pasa un array con los objetos a sincronizar y un boolean que
indica si la sincronización es mantenida (valor true) o no (valor false), como es
lógico devuelve true si se pueden sincronizar y false si no.
4.3 Captura de sonido.
Tras lo expuesto anteriormente en el apartado de reproducción vale con una
pequeña referencia al apartado de captura de sonido ya que todo se hace prácticamente
igual.
En la captura de audio los Ports (puertos) ponen datos en el Mixer y este en
un objeto TargetDataLine que tiene los métodos:
void open(AudioFormat);
void open(AudioFormat, int);
// Redefinen el metodo de abir de Line pasando el formato de audio que
//van a manejar y, opcionalmente, el tamaño en bytes del buffer.
int read(byte [ ], int, int);
// Lee los datos desde el buffer (ver texto a continuación).
Aparte de los métodos heredados. Así se puede observar la cantidad de datos en
el buffer con available() y leerlos con read().
Lo primero es obtener un objeto TargetDataLine (antes es necesario
DataLine.Info) y abrirlo con open(), indicando, si es necesario, el formato de
audio (si no, pone uno por defecto) y el tamaño del buffer. Para leer los datos de
TargetDataLine hay que utilizar el método read() donde el primer parámetro es
Carlos Prades del Valle.
Pag 17 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
el array de bytes donde dejar los datos, el segundo es el offset a partir del que se
dejan los datos en el array y el tercero indica el número de datos a leer.
Para limpiar el buffer se utiliza el método drain().
Esta clase genera los mismos eventos que los que hemos visto en el caso anterior
LineEvent, con los mismos valores como LineEvent.Type (START, STOP,
OPEN y CLOSE).
4.4 Procesado de la señal.
Una vez capturada la señal y/o antes de la reproducción tenemos la señal en un
array, momento que podemos aprovechar para el procesado de la señal, en el caso de un
proceso que no sea en tiempo real este array puede ser almacenado para el procesado
posterior o el procesado por parte de otro thread del programa.
Existe la posibilidad de usar los el procesado soportado por los Mixer o los
DataLine mediante el uso de los objetos de clase Control, esto permite utilizar
funciones básicas de estos objetos como la ganancia (gain) o la reverberación (reverb).
Todo objeto Line puede implementar este procesado. Los objetos Control en un
Mixer pueden afectar sólo a algunos Line asociados a él. La jerarquía de estas clases
es:
Control
BooleanControl
FloatControl
EnumControl
ComponentControl
Cada clase hija de Control tiene un una clase Type incluida que define
constantes para cada tipo de control. Para obtener un Control de un Line se puede
usar el método de ese Line getControl(Control.Type) que devuelve la
instancia del Control, si queremos ver que controles soporta cada Line podemos
llamar al método de Line getControls() que devuelve un array con todos los
objetos Control soportados. Para saber que tipo de Control es el método del
Control getType() devuelve un objeto de clase Control.Type y con el
método de Object getClass() se puede saber la clase derivada a la que pertenece
el objeto. Para cambiar los parámetros de un objeto Control se utiliza el método
setValue() el tipo del parámetro de este método depende de la clase del método.
Carlos Prades del Valle.
Pag 18 de 19
Sonido en Java.
Versión 1.0.1 Enero 2000
Bibliografía.
[1]
Java Sound API Programmer’s Guide [ver 1.0]. Sun Microsystems, Inc.
1999−2000.
[2]
Java
Sound
1.0
API
Specification.
Sun
Microsystems,
Inc.
http://java.sun.com/j2se/1.3/docs/guide/sound/.
[3]
Java
Sound
Home
Page.
Diciembre
2000.
http://java.sun.com/products/java−media/sound/index.html.
Carlos Prades del Valle.
Pag 19 de 19