如何将音频数据数组转换为 wav 文件?

Posted

技术标签:

【中文标题】如何将音频数据数组转换为 wav 文件?【英文标题】:How do I convert an array of audio data into a wav file? 【发布时间】:2013-08-28 12:43:20 【问题描述】:

我有一个为用户记录音频注释的功能。它使用带有 Flash 后备的 html5。我可以通过 getUserMedia() 从 HTML5 版本中获取音频数据,但 Flash 后备以浮点数组的形式提供数据。

我需要这些数据作为 wav 文件,但我不知道该怎么做。非常感谢任何帮助!

【问题讨论】:

【参考方案1】:
var recLength = 0,
recBuffersL = [],
recBuffersR = [],
sampleRate;

this.onmessage = function (e) 
switch (e.data.command) 
    case 'init':
        init(e.data.config);
        break;
    case 'record':
        record(e.data.buffer);
        break;
    case 'exportWAV':
        exportWAV(e.data.type);
        break;
    case 'getBuffer':
        getBuffer();
        break;
    case 'clear':
        clear();
        break;

;

function init(config) 
sampleRate = config.sampleRate;


function record(inputBuffer) 
recBuffersL.push(inputBuffer[0]);
recBuffersR.push(inputBuffer[1]);
recLength += inputBuffer[0].length;


function exportWAV(type) 
var bufferL = mergeBuffers(recBuffersL, recLength);
var bufferR = mergeBuffers(recBuffersR, recLength);
var interleaved = interleave(bufferL, bufferR);
var dataview = encodeWAV(interleaved);
var audioBlob = new Blob([dataview], 
    type: type
);

this.postMessage(audioBlob);


function getBuffer() 
var buffers = [];
buffers.push(mergeBuffers(recBuffersL, recLength));
buffers.push(mergeBuffers(recBuffersR, recLength));
this.postMessage(buffers);


function clear() 
recLength = 0;
recBuffersL = [];
recBuffersR = [];


function mergeBuffers(recBuffers, recLength) 
var result = new Float32Array(recLength);
var offset = 0;
for (var i = 0; i < recBuffers.length; i++) 
    result.set(recBuffers[i], offset);
    offset += recBuffers[i].length;

return result;


function interleave(inputL, inputR) 
var length = inputL.length + inputR.length;
var result = new Float32Array(length);

var index = 0,
    inputIndex = 0;

while (index < length) 
    result[index++] = inputL[inputIndex];
    result[index++] = inputR[inputIndex];
    inputIndex++;

return result;


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);



function writeString(view, offset, string) 
for (var i = 0; i < string.length; i++) 
    view.setUint8(offset + i, string.charCodeAt(i));



function encodeWAV(samples) 
var buffer = new ArrayBuffer(44 + samples.length * 2);
var view = new DataView(buffer);

writeString(view, 0, 'RIFF');
view.setUint32(4, 32 + samples.length * 2, true);
writeString(view, 8, 'WAVE');
writeString(view, 12, 'fmt ');
view.setUint32(16, 16, true);
view.setUint16(20, 1, true);
view.setUint16(22, 2, true);
view.setUint32(24, sampleRate, true);
view.setUint32(28, sampleRate * 4, true);
view.setUint16(32, 4, true);
view.setUint16(34, 16, true);
writeString(view, 36, 'data');
view.setUint32(40, samples.length * 2, true);

floatTo16BitPCM(view, 44, samples);

return view;

用法:

var AudioContext = win.webkitAudioContext,
    recorder, audioContext;


function recordAudio() 
    if (!config.stream) 
        alert('No audio.');
        return;
    
    initAudioRecorder(config.audioWorkerPath);
    audioContext = new AudioContext;
    var mediaStreamSource = audioContext.createMediaStreamSource(config.stream);

    mediaStreamSource.connect(audioContext.destination);
    recorder = new window.Recorder(mediaStreamSource);

    recorder && recorder.record();


function stopAudioRecording() 
    console.warn('Audio recording stopeed');
    recorder && recorder.stop();
    recorder && recorder.exportWAV(function (blob) 
        fileType = 'wav';
        setBlob(blob);
    );
    recorder && recorder.clear();


var writer;

function setBlob(blob) 
    blobURL = blob;

    var config = 
        blob: blobURL,
        type: 'audio/wav',
        fileName: (Math.random() * 1000 << 1000) + '.' + fileType,
        size: blobURL.length
    ;
    writer = RecordRTCFileWriter(config);

    var reader = new win.FileReader();
    reader.readAsDataURL(blobURL);
    reader.onload = function (event) 
        blobURL2 = event.target.result;
    ;


return 
    stopAudio: stopAudioRecording,
    stopVideo: stopVideoRecording,
    recordVideo: recordVideo,
    recordAudio: recordAudio,
    save: saveToDisk,
    getBlob: function () 
        return blobURL2;
    ,
    toURL: function () 
        return writer.toURL();
    
;

【讨论】:

这需要一个 AudioContext,如果可用,这意味着客户端将使用 HTML5 方法,因此不需要转换。不过谢谢。

以上是关于如何将音频数据数组转换为 wav 文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何将wav格式声音文件转换为文本文件

使用 NAudio 将 g722 音频转换为 WAV

如何将wav音频文件格式为pcm转化为ima adpcm格式

如何将 wav 音频文件格式(样本宽度)转换为 8 位格式?

如何将 .wav 音频文件转换为文本并使用 LUIS 识别意图

如何将wav转换成mp3音频格式?