Cómo capturar, codificar, decodificar y reproducir audio en formato ALAW para sesiones RTP usando Peers

Vamos a ver cómo utilizar la librería del softphone Peers para realizar las tareas de captura y reproducción de audio, además de la codificación y decodificación desde audio linear a ALAW y viceversa.

¿Qué es cada cosa de las que hemos hablado ahora? He aquí las definiciones:

  • Peers es un softphone funcional y portable totalmente desarrollado en Java.
  • ALAW es un codec de compresión de audio usado principalmente para la transmisión de voz en llamadas VoIP.

Para usar la librería de Peers basta con bajar el paquete del softphone desde Sourceforge e importar el JAR de la aplicación (peers.jar) dentro de nuestro proyecto Eclipse o Netbeans, así de facil. Con ésto ya tendremos toda la potencia de Peers disponible para nuestra aplicación.

Y ahora vamos ahora a lo interesante, el código (es bastante autoexplicativo):

Inicializando el sistema

Para inicializar el sistema de audio de Peers haremos lo siguiente:

// Logger para Peers
// Se ha de crear el directorio "./logs" o fallará
(new File("logs")).mkdir();
Logger loggerInterno = new Logger(null);

// Inicializamos el audio
soundManager = new SoundManager(false, this.loggerInterno, ".");
soundManager.openAndStartLines();

Decodificando y reproduciendo audio RTP

Para decodificar y reproducir los datos RTP que hayamos recibido a través de nuestra sesión RTP haremos lo siguiente:

while(recibimosPaquetesRTP)
{
	// Recibimos el paquete desde la fuente RTP
	byte[] paquete = null;

	// ...
	// NOTA: Fuera del ámbito de éste post, deberás escribir tú éste fragmento de código
	// ...

	// Procesamos el paquete
	RtpParser rtpParser = new RtpParser(loggerInterno);
	RtpPacket rtpPacket = rtpParser.decode(paquete);

	// Decodificamos los datos
	Decoder decoder = null;

	switch (rtpPacket.getPayloadType())
	{
		case RFC3551.PAYLOAD_TYPE_PCMU:
		{
			decoder = new PcmuDecoder();
			break;
		}

		case RFC3551.PAYLOAD_TYPE_PCMA:
		{
			decoder = new PcmaDecoder();
			break;
		}
	}

	byte[] rawBuf = decoder.process(rtpPacket.getData());
	soundManager.writeData(rawBuf, 0, rawBuf.length);
}

Capturando desde el micro y codificando audio antes de enviar

Para recibir datos del micrófono y codificar el audio en ALAW para enviar a través de nuestra sesión RTP haremos lo siguiente:

Encoder encoder = new PcmaEncoder(null, null, false, this.padre.loggerInterno, ".", new CountDownLatch(3));

while(queremosLeerDesdeElMicro)
{
	// Leemos del micro
	byte[] paquete = this.padre.soundManager.readData();

	// Codificamos
	byte[] codificado = encoder.process(paquete);

	// Enviamos el paquete por la sesión RTP

	// ...
	// NOTA: Fuera del ámbito de éste post, deberás escribir tú éste fragmento de código
	// ...
}

¡Espero que os sirva de ayuda! ¡Happy coding!

RTP y RTSP con Java, parte 2: Gestión del hardware

Antes de empezar, vamos a investigar cómo podemos coger audio del micrófono y enivar audio al altavoz del ordenador. Lo haremos analizando directamente unos fragmentos de código, que es la mejor forma de ver éstas cosas icon smile RTP y RTSP con Java, parte 2: Gestión del hardware

Recibiendo audio desde el micro

Usaremos el código siguiente para recibir desde el micro. En los comentarios se explican los detalles de las operaciones que se realizan y los recursos que se utilizan.

// Especificamos el formato
AudioFormat formato=new AudioFormat(this.sampleRate, 16, 1, true, true);

// Accedemos a la línea de entrada desde el AudioSystem
DataLine.Info info = new DataLine.Info(TargetDataLine.class, formato);

if (AudioSystem.isLineSupported(info))
{
	// Cogemos y abrimos la línea de entrada
	TargetDataLine lineaEntrada =
		(TargetDataLine) AudioSystem.getLine(info);
	lineaEntrada.open(formato);
	lineaEntrada.start();

	// Creamos el buffer intermedio
	int tamBuffer=lineaEntrada.getBufferSize()/5;
	byte[] buffer=new byte[tamBuffer];

	while(!this.finalizar)
	{
		// Miramos si hay algo que leer
		int bytesDisp = lineaEntrada.available();

		if(bytesDisp > 0)
		{
			tamBufferActual =
				(bytesDisp > tamBuffer ? tamBuffer : bytesDisp);
			lineaEntrada.read(this.buffer, 0, tamBufferActual);
		}
	}

	// Cerramos el stream
	lineaEntrada.close();
}

Enviando audio al altavoz

Usaremos el código siguiente para recibir desde el micro. De nuevo, en los comentarios se explican los detalles de las operaciones que se realizan y los recursos que se utilizan.

// Especificamos el formato
AudioFormat formato=new AudioFormat(this.sampleRate, 16, 1, true, true);

// Accedemos a la línea de salida desde el AudioSystem
DataLine.Info info = new DataLine.Info(SourceDataLine.class, formato);

if (AudioSystem.isLineSupported(info))
{
	// Cogemos y abrimos la línea de salida
	lineaSalida = (SourceDataLine) AudioSystem.getLine(info);
	lineaSalida.open(formato);
	lineaSalida.start();

	// Creamos el buffer intermedio
	int tamBuffer=lineaSalida.getBufferSize()/5;
	byte[] buffer=new byte[tamBuffer];

	while(!this.finalizar)
	{
		lineaSalida.write(this.buffer, 0, tamBufferActual);
	}

	// Cerramos el stream
	lineaSalida.close();
}

Conclusión

Como podemos ver, con las clases que están en javax.sound.sampled.* podemos acceder a el hardware de sonido de forma sencilla. Con los mixers que nos ofrece podremos acceder a diferentes micros y dispositivos de salida, y con hebras y buffers intermedios podremos convertir, guardar, emitir, etc… cualquier tipo de audio capturaro, simultáneamente.

Próximamente veremos como codificar esos datos de audio capturados en paquetes RTSP, y como recibir datos de un equipo remoto y volcarlos a través del altavoz convertidos en audio.

RTP y RTSP con Java, parte 1: Conceptos iniciales

Siguiendo éste manual crearemos una aplicación Java que sea capaz de leer y transmitir flujos RTP y veremos el soporte de éste protocolo usando componentes de una o más librerías multimedia Java, las cuales evaluaremos con éste ejercicio.

Conceptos iniciales

El estandar RTP es un protocolo para enviar contenidos multimedia sobre redes TCP/IP, y RTSP añade un poco de control de sesión al protocolo RTP. Es muy parecido al protocolo HTTP, pero con transmisiones binarias.

Para tener más información sobre el protocolo puedes leer alguna de las páginas siguientes:

Librerías RTP contempladas

Hay varias librerías que nos pueden ayudar a crear nuestro cliente RTSP, entre las que destacan las siguientes:

Varias de ésas librerías están desfasadas o no implementan RTP/RTSP en su totalidad, pero todas tienen algo que nos puede ser de utilidad para nuestro cometido. Pero su valided o no la iremos detallando poco a poco, a medida que vayamos implementado el ejemplo de acceso y emisión de paquetes RTP/RTSP.


Disclaimer: Las imágenes mostradas en ésta página web se utilizan sólamente con propósitos ilustrativos, y son propiedad de sus respectivos autores (cuando es aplicable).
Hijo de Blog es un producto del Dr. SeROne

Los contenidos se ofrecen bajo una licencia de Creative Commons
Attribution-NonCommercial-NoDerivs 3.0 Unported

salvo que se indique lo contrario

Licencia de Creative Commons