upsample
Version:
upsample your wav file!
178 lines (145 loc) • 7.33 kB
JavaScript
let INITIAL_NUMERATOR_UPSAMPLE = [0, 1.6344e-06, -1.3929e-20, -1.5509e-05, -4.0224e-05, -4.5982e-05, 4.7602e-19, 9.7257e-05, 0.00018729, 0.00017511, -3.9189e-19, -0.00028703, -0.00050711, -0.00044227, 8.4101e-19, 0.000652, 0.0011049, 0.00092935, -1.5214e-18, -0.0012896, -0.0021302, -0.0017506, 2.4551e-18, 0.0023329, 0.0037859, 0.0030611, -3.6255e-18, -0.0039651, -0.0063562, -0.0050829, 4.9681e-18, 0.006465, 0.01029, 0.0081824, -6.3721e-18, -0.010341, -0.016455, -0.013111, 7.6941e-18, 0.016784, 0.027032, 0.021913, -8.7808e-18, -0.029691, -0.050039, -0.043226, 9.4959e-18, 0.07394, 0.15813, 0.22471, 0.25, 0.22471, 0.15813, 0.07394, 9.4959e-18, -0.043226, -0.050039, -0.029691, -8.7808e-18, 0.021913, 0.027032, 0.016784, 7.6941e-18, -0.013111, -0.016455, -0.010341, -6.3721e-18, 0.0081824, 0.01029, 0.006465, 4.9681e-18, -0.0050829, -0.0063562, -0.0039651, -3.6255e-18, 0.0030611, 0.0037859, 0.0023329, 2.4551e-18, -0.0017506, -0.0021302, -0.0012896, -1.5214e-18, 0.00092935, 0.0011049, 0.000652, 8.4101e-19, -0.00044227, -0.00050711, -0.00028703, -3.9189e-19, 0.00017511, 0.00018729, 9.7257e-05, 4.7602e-19, -4.5982e-05, -4.0224e-05, -1.5509e-05, -1.3929e-20, 1.6344e-06, 0];
export const upSample = (data, UPSAMPLE_RATIO = 2, NUMERATOR_UPSAMPLE = INITIAL_NUMERATOR_UPSAMPLE, DENOMINATOR_UPSAMPLE = [1]) => {
//start upSampling
// let dataLen = data.length
// let sub = (dataLen - 22) * 2
let wavheader = data.slice(0, 22);
console.log(data.length)
let originalDoublesData = data.slice(22)
let len = originalDoublesData.length * UPSAMPLE_RATIO - UPSAMPLE_RATIO + 1;
let upSampledDoublesData = new Float64Array(len);
for (var i = 0; i < originalDoublesData.length; i++) {
upSampledDoublesData[i * UPSAMPLE_RATIO] = originalDoublesData[i];
}
upSampledDoublesData = filtFilt(NUMERATOR_UPSAMPLE, DENOMINATOR_UPSAMPLE, upSampledDoublesData, true);
let convertedUpSample = upSampledDoublesData.map(convert)
let orginalUpSampledData = new Int16Array(convertedUpSample)
const int32toint16 = (x) => {
let int32 = new Int32Array([x])
return new Int16Array(int32.buffer)
}
let chunkSize = int32toint16((orginalUpSampledData.length * 2) + 44 - 8)
let subChunk2Size = int32toint16(orginalUpSampledData.length * 2)
wavheader[2] = chunkSize[0]
wavheader[3] = chunkSize[1]
wavheader[12] = wavheader[12] * UPSAMPLE_RATIO
wavheader[14] = wavheader[14] * UPSAMPLE_RATIO
wavheader[20] = subChunk2Size[0]
wavheader[21] = subChunk2Size[1]
// let str = ''
// for (let i of wavheader) {
// str += i + '\n';
// }
// let a = document.createElement('a');
// a.href = "data:application/octet-stream," + encodeURIComponent(str);
// a.download = 'abc.txt';
// a.click();
let upSampled = new Int16Array([...wavheader, ...orginalUpSampledData])
return upSampled;
}
const convert = (n) => {
var v = n < 0 ? n * 32768 : n * 32767; // convert in range [-32768, 32767]
return parseInt(v); // clamp
}
const filtFilt = (b, a, rawData, doNormalize) => {
//First index of a must be 1 --> a = a(:)/a(1) --> b = b(:)/a(1) ((MATLAB SYNTAX))
// a is DENOMINATOR b is NUMERATOR
let len_buffer = rawData.length;
let len_a = a.length;
let len_b = b.length;
let nfilt = Math.max(len_a, len_b);
let nfact = 3 * (nfilt - 1); // length of edge transients
// if (len_buffer<=nfact) % input data too short!
// error('Data must have length more than 3 times filter order in Fir Filter .');
// end
/////////////////////////////////////////////////////////////
//////////Prepare for Filtering
let X = new Float64Array(len_buffer + nfact * 2);
let len_X = X.length;
for (let i = 0; i < nfact; i++) {
////////// IN some case need First Equ. but in General case use Second Equ.
// First Equ
// X[i] = 2 * x[0] - x[nfact - i];
// X[len_X - 1 - i] = 2 * x[len_buffer - 1] - x[len_buffer - 2 - i];
// Second Equ
X[i] = -rawData[nfact - i];
X[len_X - 1 - i] = -rawData[len_buffer - 2 - i];
}
// System.arraycopy(rawData, 0, X, nfact, len_buffer);
for (let i = 0; i < len_buffer; i++) {
X[nfact + i] = rawData[0 + i]
}
//////////////////////////////////////////////////////////////
////////// Filtering
// Filter, reverse data, filter again, and reverse data again
/// First Filter
let X2 = new Float64Array(nfilt - 1 + len_X);
// System.arraycopy(X, 0, X2, nfilt - 1, len_X);
for (let i = 0; i < len_X; i++) {
X2[nfilt - 1 + i] = X[0 + i]
} //for full convolution zero padding
let yfilt1 = new Float64Array(len_X + len_a - 1);
let yfilt1_reverse = new Float64Array(len_X + nfilt - 1); //for full convolution zero padding
let matrixMult = 0;
for (let i = 0; i < len_b; i++) {
matrixMult += b[len_b - 1 - i] * X2[i];
}
yfilt1[len_a - 1] = matrixMult;
yfilt1_reverse[len_X + nfilt - 2] = yfilt1[len_a - 1];
for (let i = 1; i < len_X; i++) {
let matrixMult_b = 0;
let matrixMult_a = 0;
for (let j = 0; j < len_b; j++) {
matrixMult_b += b[len_b - 1 - j] * X2[i + j];
}
for (let j = 0; j < len_a - 1; j++) {
matrixMult_a += a[len_a - 1 - j] * yfilt1[i + j];
}
yfilt1[i + len_a - 1] = matrixMult_b - matrixMult_a;
yfilt1_reverse[len_X + nfilt - i - 2] = yfilt1[i + len_a - 1];
}
//////////////////////////////////////////////////////////
/// Second Filter
let yfilt2 = new Float64Array(len_X + len_a - 1);
let yfilt2_reverse = new Float64Array(len_X);
matrixMult = 0;
for (let i = 0; i < len_b; i++) {
matrixMult += b[len_b - 1 - i] * yfilt1_reverse[i];
}
yfilt2[len_a - 1] = matrixMult;
yfilt1_reverse[len_X - 1] = yfilt2[len_a - 1];
for (let i = 1; i < len_X; i++) {
let matrixMult_b = 0;
let matrixMult_a = 0;
for (let j = 0; j < len_b; j++) {
matrixMult_b += b[len_b - 1 - j] * yfilt1_reverse[i + j];
}
for (let j = 0; j < len_a - 1; j++) {
matrixMult_a += a[len_a - 1 - j] * yfilt2[i + j];
}
yfilt2[i + len_a - 1] = matrixMult_b - matrixMult_a;
yfilt2_reverse[len_X - i - 1] = yfilt2[i + len_a - 1];
}
//////////////////////////////////////////////////////////////
////////// Remove extrapolated pieces of final data (yfilt2_reverse -> filteredData)
let filteredData = new Float64Array(len_buffer);
// System.arraycopy(yfilt2_reverse, nfact, filteredData, 0, len_buffer);
for (let i = 0; i < len_buffer; i++) {
filteredData[0 + i] = yfilt2_reverse[nfact + i]
}
//////////////////////////////////////////////////////////////
if (doNormalize) {
////////// Normalize between -1, 1
let maxValue = 0;
for (let upSampledDoublesDatum of filteredData) {
let absValue = Math.abs(upSampledDoublesDatum);
if (absValue > maxValue) {
maxValue = absValue;
}
}
for (let i = 0; i < len_buffer; i++) {
filteredData[i] = filteredData[i] / maxValue;
}
}
return filteredData;
}