node.js audio stream pcm web-audio

Reproducción de secuencias PCM desde la API de audio web en Node.js



stream web-audio (1)

Estoy transmitiendo audio PCM grabado desde un navegador con api de audio web.

Lo estoy transmitiendo con binaryJS (conexión websocket) a un servidor nodejs y estoy tratando de reproducir esa secuencia en el servidor usando el módulo npm del altavoz.

Este es mi cliente. Los buffers de audio son al principio PCM lineal IEEE de 32 bits no intercalados con un rango nominal entre -1 y +1 . Tomo uno de los dos canales PCM para comenzar y transmitirlo a continuación.

var client = new BinaryClient(''ws://localhost:9000''); var Stream = client.send(); recorder.onaudioprocess = function(AudioBuffer){ var leftChannel = AudioBuffer.inputBuffer.getChannelData (0); Stream.write(leftChannel); }

Ahora recibo los datos como un búfer e intento escribirlos en un objeto de altavoz del paquete npm.

var Speaker = require(''speaker''); var speaker = new Speaker({ channels: 1, // 1 channel bitDepth: 32, // 32-bit samples sampleRate: 48000, // 48,000 Hz sample rate signed:true }); server.on(''connection'', function(client){ client.on(''stream'', function(stream, meta){ stream.on(''data'', function(data){ speaker.write(leftchannel); }); }); });

El resultado es un chillido de tono alto en los parlantes de mi computadora portátil, que claramente no es lo que se está grabando. No es retroalimentación tampoco. Puedo confirmar que los búferes de grabación en el cliente son válidos, ya que intenté escribirlos en un archivo WAV y se reprodujeron bien.

Los documentos para el orador y los documentos para el AudioBuffer en cuestión

He estado perplejo en esto por días. ¿Puede alguien descubrir qué es lo que está mal o quizás ofrecer un enfoque diferente?

Actualizar con solución

En primer lugar, estaba usando la API de websocket incorrectamente. He actualizado anteriormente para usarlo correctamente.

Necesitaba convertir los buffers de audio en un buffer matricial de enteros. Elijo usar Int16Array . Dado que el búfer de audio dado tiene un rango entre 1 y -1, fue tan simple como multiplicar por el rango del nuevo ArrayBuffer (32767 a -32768).

recorder.onaudioprocess = function(AudioBuffer){ var left = AudioBuffer.inputBuffer.getChannelData (0); var l = left.length; var buf = new Int16Array(l) while (l--) { buf[l] = left[l]*0xFFFF; //convert to 16 bit } Stream.write(buf.buffer); }


Parece que estás enviando tu flujo como meta objeto.

De acuerdo con los documentos, BinaryClient.send toma un objeto de data (la secuencia) y un objeto meta , en ese orden. La devolución de llamada para el evento de stream recibe el flujo (como un objeto BinaryStream , no un Buffer ) en el primer parámetro y el objeto meta en el segundo.

Estás pasando send() la cadena ''channel'' como la transmisión y el objeto Float32Array de getChannelData() como meta objeto. Quizás si tuviera que intercambiar esos dos parámetros (o simplemente usar client.send(leftChannel) ) y luego cambiar el código del servidor para pasar la stream a speaker.write lugar de leftchannel (que probablemente debería ser renombrado a meta , o borrado si no lo hace) No lo necesito), podría funcionar.

Tenga en cuenta que dado que Float32Array no es un objeto de flujo o búfer, BinaryJS podría BinaryClient.send . Es posible que desee enviar leftChannel.buffer ( el ArrayBuffer detrás de ese objeto ) en su lugar.

Hazme saber si esto funciona para ti; No puedo probar tu configuración exacta en este momento.