I am trying to play wav raw data in the browser, which is transmitted from the nodejs server via socket.io, the main idea is to play the receiving data as soon as posible, so I don't need to wait until receiving data is done. I tried to use blob for this case, but next thing always happens: if I've got a chunk of raw data and I am converting it with blob for playing, then when the second chunk is ready and being converted with blob again, then while playing the audio breaks up for a while.
Also I was trying to use the code below and it's worked, but I could hear a lot of noises while playing it. Can anyone, please, help me with this problem and tell me how can I play audio without noises?
P.S. the timeout in the transmitting is a part of the main idea, I tried playing music without it, but still no luck.
<html>
<head>
<script src="socket.io.js"></script>
<script src=" https://cdnjs.cloudflare.com/ajax/libs/socket.io-stream/0.9.1/socket.io-stream.js">
</script>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
<button id="start">Play music!</button>
<script>
$(function () {
var socket = io.connect("http://localhost:3000");
var stream = ss.createStream();
// receive data
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var audioCtx = new AudioContext();
var audioBuffer = audioCtx.createBuffer(2, 22050, 44100);
var source = audioCtx.createBufferSource();
source.buffer = audioBuffer;
// source.connect(audioCtx.destination);
gainNode = audioCtx.createGain();
gainNode.gain.value = 0;
gainNode.connect(audioCtx.destination);
source.connect(gainNode);
source.start(0);
socket.on('chat message', function (msg) {
console.log(".");
console.log(msg);
playsound(msg)
});
function playsound(raw) {
var context = audioCtx;
var buffer = new Int16Array(raw);
console.log(buffer);
var channel0buffer = new Float32Array(buffer.length / 2);
var channel1buffer = new Float32Array(buffer.length / 2);
var j = 0;
for (var i = 0; i < buffer.length; i++) {
channel0buffer[j] = buffer[i];
i++;
channel1buffer[j] = buffer[i];
j++;
}
var src = context.createBufferSource(),
audioBuffer = context.createBuffer(2, buffer.length, context.sampleRate);
audioBuffer.getChannelData(0).set(channel1buffer);
audioBuffer.getChannelData(1).set(channel0buffer);
src.buffer = audioBuffer;
src.connect(gainNode);
src.start(0);
}
document.getElementById("start").addEventListener('click', function () {
audioCtx.resume().then(() => {
console.log('Playback resumed successfully');
});
});
});
</script>
<p>Volume</p>
<input id="volume" type="range" min="0" max="1" step="0.1" value="0.0" />
<script>
document.getElementById('volume').addEventListener('change', function () {
gainNode.gain.value = this.value;
});
function touchStarted() {
getAudioContext().resume();
}
</script>
</body>
</html>
My server code looks like this:
const fs = require("fs");
var app = require("express")();
var http = require("http").createServer(app);
var io = require("socket.io")(http);
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
io.on("connection", (socket) => {
console.log("a user connected");
socket.on("disconnect", () => {
console.log("user disconnected");
});
socket.on("chat message", (msg) => {
console.log("message: " + msg);
io.emit("chat message", msg);
});
});
http.listen(3000, () => {
console.log("listening on *:3000");
});
const stream = fs.createReadStream("Original1.wav", {
highWaterMark: 640000, // internal buffer size
});
stream.on("data", async (chunk) => {
stream.pause();
let newChunk = new Int16Array(chunk);
await asyncHandle(chunk);
setTimeout(() => {
stream.resume();
}, 1000);
});
async function asyncHandle(chunk) {
console.log(chunk);
io.emit("chat message", chunk);
}