I'm trying to play some mp3 files in node.js. The thing is that I manage to play them one by one, or even, as I want in parallel. But what I also want is to be able to control the amplitude (gain) to be able to create a crossfade in the end. Could anyone help me understand what it is I need to do? (I want to use it in node-webkit so I need a solution that is node.js based with no external dependencies.)
This is what I've got so far:
var lame = require('lame'), Speaker = require('speaker'), fs = require('fs');
var audioOptions = {channels: 2, bitDepth: 16, sampleRate: 44100};
var decoder = lame.Decoder();
var stream = fs.createReadStream("music/ge.mp3", audioOptions).pipe(decoder).on("format", function (format) {
this.pipe(new Speaker(format))
}).on("data", function (data) {
console.log(data)
})
-
do you want to control the gain in DSP or do you want to just use your operating systems volume control?benathon– benathon2013年12月06日 01:04:28 +00:00Commented Dec 6, 2013 at 1:04
-
In DSP because I want to crossfade two tracksjonepatr– jonepatr2013年12月06日 01:05:25 +00:00Commented Dec 6, 2013 at 1:05
-
1Can you please share the solution to this question if you have found one? I'am facing the same problem at the moment :-(micha– micha2014年02月16日 21:59:57 +00:00Commented Feb 16, 2014 at 21:59
-
What @micha says. Answering your own question is definitely a feature of Stack Overflow. :)jamesmortensen– jamesmortensen2014年02月26日 20:35:05 +00:00Commented Feb 26, 2014 at 20:35
1 Answer 1
I customized the npm package pcm-volume to do that. To crossfade, provide two pcm audio buffers (output of your decoders). Pipe the result to your Speaker object.
Here is the main part of the modifications. In this case the crossfade happens at the scale of the provided buffer, but you can change that.
var l = buf.length;
var out = new Buffer(l);
for (var i=0; i < l; i+=2) {
volumeSunrise = 0.5*this.volume*(1-Math.cos(pi*i/l));
volumeSunset = 0.5*this.volume*(1+Math.cos(pi*i/l));
uint = Math.round(volumeSunrise*buf.readInt16LE(i) + volumeSunset*this.sunsetBuffer.readInt16LE(i));
// you may want to ensure that -32767 <= uint <= 32768 here, in case you use a volume higher than 1
out.writeInt16LE(uint, i);
}
this.push(out);
callback()
Comments
Explore related questions
See similar questions with these tags.