Reputation: 914
I am attempting to downsample the sample rate i am getting from audioContext. I believe it is coming in at 44100, and i want it to be 11025. I thought i could just average every 3 samples and it plays back at the correct rate, but the pitch of is too high, as if we were all on helium.
What is the correct way to downsample a float32Array from 44100 to a int16Array at 11025 samples.
var context = new Flash.audioContext();
var audioInput = context.createMediaStreamSource(stream);
var recorder = context.createScriptProcessor(null, 1, 1);
recorder.onaudioprocess = onAudio;
audioInput.connect(recorder);
recorder.connect(context.destination);
var onAudio = function (e) {
var left = e.inputBuffer.getChannelData(0);
bStream.write(Flash.convertFloat32ToInt16(left));
}
var convertFloat32ToInt16 = function(buffer) {
var l = buffer.length;
var point = Math.floor(l/3);
var buf = new Int16Array(point);
for (var x = l; x > 0;) {
var average = (buffer[x] + buffer[x-1] + buffer[x-2]) / 3;
buf[point] = average*0x7FFF;
point -= 1;
x -= 3;
}
return buf.buffer;
}
Upvotes: 9
Views: 4703
Reputation: 914
For anyone else who needs the answer.
var downsampleBuffer = function (buffer, sampleRate, outSampleRate) {
if (outSampleRate == sampleRate) {
return buffer;
}
if (outSampleRate > sampleRate) {
throw "downsampling rate show be smaller than original sample rate";
}
var sampleRateRatio = sampleRate / outSampleRate;
var newLength = Math.round(buffer.length / sampleRateRatio);
var result = new Int16Array(newLength);
var offsetResult = 0;
var offsetBuffer = 0;
while (offsetResult < result.length) {
var nextOffsetBuffer = Math.round((offsetResult + 1) * sampleRateRatio);
var accum = 0, count = 0;
for (var i = offsetBuffer; i < nextOffsetBuffer && i < buffer.length; i++) {
accum += buffer[i];
count++;
}
result[offsetResult] = Math.min(1, accum / count)*0x7FFF;
offsetResult++;
offsetBuffer = nextOffsetBuffer;
}
return result.buffer;
}
this will return a sample rate smaller than the one passed to it, while also converting it to a int16Array instead of a float32.
Upvotes: 22