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.