Closed cmdedj closed 4 years ago
The sample rate is dictated by your browser/OS/microphone.
Recorder.js will record at whatever sample rate is supported by your browser/OS/mic. You’ll most commonly see 44.1 kHz and 48kHz audio recordings but I've seen 16kHz as well.
This Recorder.js demo shows the sample rate in real time.
@octavn i know your mean, but i want to change the code to change the sample. i had try it, but i false.now i want to change the default sample.
@cmdedj 我感觉可以参考一下这篇文章,魔改了一下Recorder.js http://www.cnblogs.com/blqw/p/3782420.html 或许用 OfflineAudioContext 可以尝试一下?
After more digging I've found the default sample rate is the one set in your OS for your playback device (as per the spec and this comment from a Chrome developer)
@octavn i know the default sample rate is by device, now can i by change the js code to change the default sample rate? now i transfer the wav file to backend and change the sample rate by sox.http://sox.sourceforge.net/. but i don't want to handle the sample rate on backend, i want to change it on web frontend.
Before calling encodeWav(), resample the buffer to change sample rate:
function downsampleBuffer(buffer, rate) {
if (rate == sampleRate) {
return buffer;
}
if (rate > sampleRate) {
throw "downsampling rate show be smaller than original sample rate";
}
var sampleRateRatio = sampleRate / rate;
var newLength = Math.round(buffer.length / sampleRateRatio);
var result = new Float32Array(newLength);
var offsetResult = 0;
var offsetBuffer = 0;
while (offsetResult < result.length) {
var nextOffsetBuffer = Math.round((offsetResult + 1) * sampleRateRatio);
// Use average value of skipped samples
var accum = 0, count = 0;
for (var i = offsetBuffer; i < nextOffsetBuffer && i < buffer.length; i++) {
accum += buffer[i];
count++;
}
result[offsetResult] = accum / count;
// Or you can simply get rid of the skipped samples:
// result[offsetResult] = buffer[nextOffsetBuffer];
offsetResult++;
offsetBuffer = nextOffsetBuffer;
}
return result;
}
Then call encodeWav with the new sample buffer:
var downsampledBuffer = downsampleBuffer(interleaved, targetRate);
var dataview = encodeWAV(downsampledBuffer);
Also, use new sample rate when encoding:
/* sample rate */
view.setUint32(24, newRate, true);
/* byte rate (sample rate * block align) */
view.setUint32(28, newRate * 4, true);
@ilikerei Thanks, your code works well! But how can I change sampleRate to 8000? Because my browser sample rate varies, sometimes it is 44100 and sometimes it can be 8000, so I have to change the sampleRate to 8000 uniformly. I don't know how your code works, can you explain it clearly or show some docs for this?
@losymear
Just change targetRate to 8000 when you call downsampleBuffer(interleaved, 8000)
Also:
/* sample rate */ view.setUint32(24, 8000, true); /* byte rate (sample rate * block align) */ view.setUint32(28, 8000 * 4, true);
The code reduces samples based on rate ratio. For example, 16000->8000, the code generate a new sample buffer by using average value of every 2 samples (Or you can simple get rid of 1 of every 2 samples). So the buffer size is 8000/16000 = 1/2
@losymear Just change targetRate to 8000 when you call downsampleBuffer(interleaved, 8000) Also:
/* sample rate */ view.setUint32(24, 8000, true); /* byte rate (sample rate * block align) */ view.setUint32(28, 8000 * 4, true);
The code reduces samples based on rate ratio. For example, 16000->8000, the code generate a new sample buffer by using average value of every 2 samples (Or you can simple get rid of 1 of every 2 samples). So the buffer size is 8000/16000 = 1/2
Please can you tell where to include this code? Seems like encodeWAV is an internal method of the library. The readme just mentions rec.exportWAV([callback][, type]). I'm using npm to add the library to my project. So does your solution mean modifying the library's code instead of taking it from npm?
@ilikerei Thank you, your code works well. ):
Before calling encodeWav(), resample the buffer to change sample rate:
function downsampleBuffer(buffer, rate) { if (rate == sampleRate) { return buffer; } if (rate > sampleRate) { throw "downsampling rate show be smaller than original sample rate"; } var sampleRateRatio = sampleRate / rate; var newLength = Math.round(buffer.length / sampleRateRatio); var result = new Float32Array(newLength); var offsetResult = 0; var offsetBuffer = 0; while (offsetResult < result.length) { var nextOffsetBuffer = Math.round((offsetResult + 1) * sampleRateRatio); // Use average value of skipped samples var accum = 0, count = 0; for (var i = offsetBuffer; i < nextOffsetBuffer && i < buffer.length; i++) { accum += buffer[i]; count++; } result[offsetResult] = accum / count; // Or you can simply get rid of the skipped samples: // result[offsetResult] = buffer[nextOffsetBuffer]; offsetResult++; offsetBuffer = nextOffsetBuffer; } return result; }
Then call encodeWav with the new sample buffer:
var downsampledBuffer = downsampleBuffer(interleaved, targetRate); var dataview = encodeWAV(downsampledBuffer);
Also, use new sample rate when encoding:
/* sample rate */ view.setUint32(24, newRate, true); /* byte rate (sample rate * block align) */ view.setUint32(28, newRate * 4, true);
@ilikerei good job, it works well.
And for anyone comes in to this issue, I've forked this repo and add the sample changing behavior using the above code. Also add a TypeScript definition file for it.
such as i want to change the sampleRate from 44100 to 16000