()
| 135 | } |
| 136 | |
| 137 | run() { |
| 138 | const imaSamplesPerChunk = 129; |
| 139 | const imaOutput = "ima" === this.output.format; |
| 140 | |
| 141 | let outputFile = new FILE(this.outputPath, "wb"); |
| 142 | |
| 143 | let header = new DataView(new ArrayBuffer(12)); |
| 144 | header.setUint8(0, 'm'.charCodeAt(0)); |
| 145 | header.setUint8(1, 'a'.charCodeAt(0)); |
| 146 | header.setUint8(2, 1); // version |
| 147 | header.setUint8(3, this.output.bitsPerSample); |
| 148 | header.setUint16(4, this.output.sampleRate, true); // little-endian |
| 149 | header.setUint8(6, this.output.numChannels); |
| 150 | header.setUint8(7, imaOutput ? 1 : 0); // sample format |
| 151 | let sampleCount = Math.floor((this.wav.samples / this.wav.sampleRate) * this.output.sampleRate); |
| 152 | if (imaOutput) |
| 153 | sampleCount = Math.idiv(sampleCount, imaSamplesPerChunk) * imaSamplesPerChunk; // quantize |
| 154 | header.setUint32(8, sampleCount, true) |
| 155 | outputFile.writeBuffer(header.buffer); |
| 156 | |
| 157 | let resampled = this.resampler.outputBuffer; |
| 158 | let finalSamples = (8 === this.output.bitsPerSample) ? new Int8Array(this.wavSamples.length) : new Int16Array(this.wavSamples.length); |
| 159 | |
| 160 | let imaBuffer = new Int16Array(imaSamplesPerChunk); |
| 161 | imaBuffer.samplesInBuffer = 0; |
| 162 | |
| 163 | let totalOut = 0; |
| 164 | while (this.wav.samples) { |
| 165 | // get next buffer of samples |
| 166 | let use = this.wavSamples.length / this.wav.numChannels; |
| 167 | if (use > this.wav.samples) |
| 168 | use = this.wav.samples; |
| 169 | use = Math.min(1024, use); |
| 170 | this.wav.getSamples(this.wavSamples, use); |
| 171 | |
| 172 | // apply output sample rate |
| 173 | use = this.resampler.resampler(use * this.wav.numChannels) / this.wav.numChannels; |
| 174 | |
| 175 | // apply output numChannels (stereo to mono) |
| 176 | if ((2 == this.wav.numChannels) && (1 == this.output.numChannels)) { |
| 177 | for (let i = 0, j = 0; i < use; i++, j += 2) |
| 178 | resampled[i] = (resampled[j] + resampled[j + 1]) / 2; |
| 179 | } |
| 180 | |
| 181 | // apply output bitsPerSample to generate finalSamples |
| 182 | if (16 == this.output.bitsPerSample) { // -32768 to 32767 |
| 183 | for (let i = 0, length = use * this.wav.numChannels; i < length; i++) |
| 184 | finalSamples[i] = resampled[i]; |
| 185 | } |
| 186 | else if (8 == this.output.bitsPerSample) { // -128 to 127 |
| 187 | for (let i = 0, length = use * this.wav.numChannels; i < length; i++) |
| 188 | finalSamples[i] = resampled[i] >> 8; |
| 189 | } |
| 190 | |
| 191 | // output samples |
| 192 | if ("uncompressed" === this.output.format) { |
| 193 | let byteLength = use * ((this.output.bitsPerSample * this.output.numChannels) >> 3); |
| 194 | outputFile.writeBuffer(finalSamples.buffer.slice(0, byteLength)); |
nothing calls this directly
no test coverage detected