2016-02-05 3 views
0

Я пытаюсь поместить WAV-файл в AudioBuffer, чтобы я мог манипулировать им. Ранее я создал WAV-файлы из AudioBuffer, и это потребовало преобразования Float32Array в DataView, содержащем значения Int16. Я использовал эту удобную функцию я подобран:Javascript: Преобразование из Int16 в Float32

function floatTo16BitPCM(output, offset, input){ 
    for (var i = 0; i < input.length; i++, offset+=2){ 
     var s = Math.max(-1, Math.min(1, input[i])); 
     output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true); 
    } 
} 

Ну, все, что мне нужно сделать сейчас, это реверс (файлы WAV загружаются с сервера, поэтому у меня нет исходных данных больше). Я не могу понять, что на самом деле происходит в этой функции или как данные преобразуются.

ответ

0

Вот что, похоже, работает. Я загружаю данные в ajax-вызов с типом ответа «arraybuffer». В противном случае ответ заканчивается тем, что является строкой, и работать с ней беспорядок. Затем я конвертирую в 16-разрядный массив. Затем я конвертирую это в массив Float32 таким образом, который работает с кодировкой WAV. Мне также нужно было выбросить заголовок WAV и некоторые метаданные в конце его.

// These are ready to be copied into an AudioBufferSourceNode's channel data. 
var theWavDataInFloat32; 

function floatTo16Bit(inputArray, startIndex){ 
    var output = new Uint16Array(inputArray.length-startIndex); 
    for (var i = 0; i < inputArray.length; i++){ 
     var s = Math.max(-1, Math.min(1, inputArray[i])); 
     output[i] = s < 0 ? s * 0x8000 : s * 0x7FFF; 
    } 
    return output; 
} 

// This is passed in an unsigned 16-bit integer array. It is converted to a 32-bit float array. 
// The first startIndex items are skipped, and only 'length' number of items is converted. 
function int16ToFloat32(inputArray, startIndex, length) { 
    var output = new Float32Array(inputArray.length-startIndex); 
    for (var i = startIndex; i < length; i++) { 
     var int = inputArray[i]; 
     // If the high bit is on, then it is a negative number, and actually counts backwards. 
     var float = (int >= 0x8000) ? -(0x10000 - int)/0x8000 : int/0x7FFF; 
     output[i] = float; 
    } 
    return output; 
} 

// TEST 
var data = [ 65424, 18, 0, 32700, 33000, 1000, 50000 ]; 
var testDataInt = new Uint16Array(data); 
var testDataFloat = int16ToFloat32(testDataInt, 0, data.length); 
var testDataInt2 = floatTo16Bit(testDataFloat, 0); 
// At this point testDataInt2 should be pretty close to the original data array (there is a little rounding.) 

var xhr = new XMLHttpRequest(); 
xhr.open('GET', '/my-sound.wav', true); 
xhr.responseType = 'arraybuffer'; 

xhr.onload = function(e) { 
    if (this.status === 200) { 
     // This retrieves the entire wav file. We're only interested in the data portion. 
     // At the beginning is 44 bytes (22 words) of header, and at the end is some metadata about the file. 
     // The actual data length is held in bytes 40 - 44. 
     var data = new Uint16Array(this.response); 
     var length = (data[20] + data[21] * 0x10000)/2; // The length is in bytes, but the array is 16 bits, so divide by 2. 
     theWavDataInFloat32 = int16ToFloat32(data, 22, length); 
    } 
}; 

xhr.send(); 
0

Каждая реальных данных входного массива сводится к интервалу [-1, 1]

  • Math.min (1, х) дает х, если х = < 1 и 1 в противном случае
  • Математика .max (-1, y) дает y, если y> = - 1 и -1 в противном случае

Затем это действительное число между -1 и 1 преобразуется в 16-битовое целое.

Является ли он положительным или отрицательным, умноженным на 32767 или -32768, тогда он сохраняет только целую часть приложением. Это эквивалентно сохранению только 16 значащих бит после десятичной точки в двоичном представлении.

16 бит целые числа хранятся в Little Endian на два байта в буфере, один за другим (в соответствии со смещением, который продвигает два на два)

Для обратной операции, просто поместить два последовательных байтов в int16. Чтобы преобразовать его в реальный различие двух случаев, следующих за знаком и делящихся на 32768 или 32767. Но операция будет выполняться с потерей данных.