Просмотр исходного кода

u-law encoding seems to be working

dds
Matt Bradshaw 6 лет назад
Родитель
Сommit
cf43f1d4da
2 измененных файлов: 38 добавлений и 10 удалений
  1. +5
    -0
      extras/wav2sketch/wav2sketch.html
  2. +33
    -10
      extras/wav2sketch/wav2sketch.js

+ 5
- 0
extras/wav2sketch/wav2sketch.html Просмотреть файл

@@ -13,6 +13,11 @@
<option value="22050">22050</option>
<option value="11025">11025</option>
</select><br/><br/>
<label>Encoding</label>
<select id="encoding">
<option value="u-law">u-law</option>
<option value="PCM">PCM</option>
</select><br/><br/>
<input id="audioFileChooser" name="audioFileChooser" type="file" accept="audio/wav" multiple>
<div id="outputFileHolder"></div>
</form>

+ 33
- 10
extras/wav2sketch/wav2sketch.js Просмотреть файл

@@ -1,6 +1,5 @@
/*
TODO
u-law encoding
browser feature check (offlineaudiocontext might still be a bit niche)
*/

@@ -12,19 +11,21 @@ function readFile() {
for(var i = 0; i < audioFileChooser.files.length; i++) {
var fileReader = new FileReader();
var sampleRateChoice = document.getElementById('sampleRate').value;
var encodingChoice = document.getElementById('encoding').value;
if(sampleRateChoice == "auto") sampleRateChoice = null;
else sampleRateChoice = parseInt(sampleRateChoice);
fileReader.readAsArrayBuffer(audioFileChooser.files[i]);
fileReader.addEventListener('load', function(fileName, ev) {
processFile(ev.target.result, fileName, sampleRateChoice);
processFile(ev.target.result, fileName, sampleRateChoice, encodingChoice);
}.bind(null, audioFileChooser.files[i].name));
}
}

function processFile(file, fileName, sampleRateChoice) {
function processFile(file, fileName, sampleRateChoice, encodingChoice) {
// determine sample rate
// ideas borrowed from https://github.com/ffdead/wav.js
var sampleRate = 0;
var encoding = encodingChoice;
if(!sampleRateChoice) {
try {
var sampleRateBytes = new Uint8Array(file, 24, 4);
@@ -57,9 +58,10 @@ function processFile(file, fileName, sampleRateChoice) {
// NB - would be trivial to add support for n channels, given that everything ends up mono anyway
}
var padLength;
var compressionCode = '0';
var encodingCode = '0';
var sampleRateCode;
if(true) compressionCode = '8'; // add u-law support here later
if(encoding == 'u-law') encodingCode = '0';
else encodingCode = '8'; // PCM
if(sampleRate == 44100) {
padLength = padding(monoData.length, 128);
sampleRateCode = '1';
@@ -73,15 +75,20 @@ function processFile(file, fileName, sampleRateChoice) {

var ulawOut = [];
for(var i = 0; i < monoData.length; i ++) {
ulawOut.push(ulaw_encode(toInteger(monoData[i]*0x7fff)).toString(16));
ulawOut.push(ulaw_encode(toInteger(monoData[i]*0x7fff)));
}
window.ulawOut = ulawOut;
var outputData = createWords(monoData, padLength);
var outputData;
if(encoding == 'u-law') {
outputData = createULawWords(ulawOut, padLength);
} else {
outputData = createWords(monoData, padLength);
}

var statusInt = (monoData.length).toString(16);
while(statusInt.length < 6) statusInt = '0' + statusInt;
if(monoData.length>0xFFFFFF) alert("DATA TOO LONG");
statusInt = '0x' + compressionCode + sampleRateCode + statusInt;
statusInt = '0x' + encodingCode + sampleRateCode + statusInt;
outputData.unshift(statusInt);

var outputFileHolder = document.getElementById('outputFileHolder');
@@ -89,7 +96,7 @@ function processFile(file, fileName, sampleRateChoice) {
var downloadLink2 = document.createElement('a');
var formattedName = fileName.split('.')[0];
formattedName = formattedName.charAt(0).toUpperCase() + formattedName.slice(1).toLowerCase();
downloadLink1.href = generateOutputFile(generateCPPFile(fileName, formattedName, outputData, sampleRate));
downloadLink1.href = generateOutputFile(generateCPPFile(fileName, formattedName, outputData, sampleRate, encoding));
downloadLink1.setAttribute('download', 'AudioSample' + formattedName + '.cpp');
downloadLink1.innerHTML = 'Download AudioSample' + formattedName + '.cpp';
downloadLink2.href = generateOutputFile(generateHeaderFile(formattedName, outputData));
@@ -140,6 +147,22 @@ function createWords(audioData, padLength) {
return outputData;
}

function createULawWords(audioData, padLength) {
var totalLength = audioData.length + padLength;
var outputData = [];
for(var i = 0; i < totalLength; i += 4) {
var a = i<audioData.length ? audioData[i] : 0;
var b = i+1<audioData.length ? audioData[i+1] : 0;
var c = i+2<audioData.length ? audioData[i+2] : 0;
var d = i+3<audioData.length ? audioData[i+3] : 0;
var out = (a + 0x100*b + 0x10000*c + 0x1000000*d).toString(16);
while(out.length < 8) out = '0' + out;
out = '0x' + out;
outputData.push(out);
}
return outputData;
}

// http://2ality.com/2012/02/js-integers.html
function toInteger(x) {
x = Number(x);
@@ -186,7 +209,7 @@ function generateCPPFile(fileName, formattedName, audioData, sampleRate, encodin
var out = "";
out += '// Audio data converted from audio file by wav2sketch_js\n\n';
out += '#include "AudioSample' + formattedName + '.h"\n\n';
out += '// Converted from ' + fileName + ', using ' + sampleRate + ' Hz, 16 bit PCM encoding\n';
out += '// Converted from ' + fileName + ', using ' + sampleRate + ' Hz, 16 bit ' + encodingType + ' encoding\n';
out += 'const unsigned int AudioSample' + formattedName + '[' + audioData.length + '] = {\n';
out += formatAudioData(audioData) + '\n};';
return out;

Загрузка…
Отмена
Сохранить