我制作了一个javascript录音机,用于在服务器上录制音频文件和存储。为此,我使用了此示例中的代码:https://webaudiodemos.appspot.com/AudioRecorder/index.html。
它记录了16位wav文件,并且在chrome和firefox中都可以完美运行。但是,我需要它来记录8位wav文件。
我在recorderworker.js中进行了以下更改:
1)我更改了encodeWav函数,以便在wav文件的标题中有信息,它是一个8位文件,而不是16位:
function encodeWAV(samples, mono){
var buffer = new ArrayBuffer(44 + samples.length * 2);
var view = new DataView(buffer);
/* RIFF identifier */
writeString(view, 0, 'RIFF');
/* file length */
view.setUint32(4, 32 + samples.length * 2, true);
/* RIFF type */
writeString(view, 8, 'WAVE');
/* format chunk identifier */
writeString(view, 12, 'fmt ');
/* format chunk length */
view.setUint32(16, 16, true);
/* sample format (raw) */
view.setUint16(20, 1, true);
/* channel count */
view.setUint16(22, mono?1:2, true);
/* sample rate */
view.setUint32(24, sampleRate, true);
/* byte rate (sample rate * block align) */
view.setUint32(28, sampleRate * 4, true);
/* block align (channel count * bytes per sample) */
view.setUint16(32, 4, true);
/* bits per sample */
view.setUint16(34, 8, true);
/* data chunk identifier */
writeString(view, 36, 'data');
/* data chunk length */
view.setUint32(40, samples.length * 2, true);
floatTo8BitPCM(view, 44, samples);
return view;
}
2)我创建了一个函数floatTo8BitPCM来替换floatTo16BitPCM,它看起来像这样:
function floatTo8BitPCM(output, offset, input){
for (var i = 0; i < input.length; i++, offset++){
var s = Math.max(-1, Math.min(1, input[i]));
output.setInt8(offset, (s * 128) + 128);
}
}
当我录制声音时,它总是在chrome中运行,但有时只在firefox中运行。而且,生成的文件也应该是它应该的两倍。上半场是我录制的,下半场是沉默的。
我尝试将缓冲区大小设置为44 + sample.length而不是44 + sample.length * 2,并将文件长度设置为32 + sample.length而不是32 + sample.length * 2.
编辑:另外,当我按照我提到的方式缩小文件大小和缓冲区大小时,当我在iTunes中播放文件时,文件的停留时间延长了2倍,但是当我在浏览器中播放它时,它缩短了2倍,我听到的只是第一次一半。
答案 0 :(得分:1)
8位的样本大小就是8位。它嵌入在块对齐,字节速率和每个样本的位中。如果您同时支持单声道和立体声,则还需要更加注意频道数。
int bytesPerSample = 1;
int channelCount = mono ? 2 : 1;
int blockAlign = bytesPerSample * channelCount;
int bitsPerSample = bytesPerSample * 8;
var buffer = new ArrayBuffer(44 + samples.length*blockAlign);
...
/* channel count */
view.setUint16(22, channelCount, true);
/* byte rate (sample rate * block align) */
view.setUint32(28, sampleRate*blockAlign, true);
/* block align (channel count * bytes per sample) */
view.setUint16(32, blockAlign, true);
/* bits per sample */
view.setUint16(34, bitsPerSample, true);
...
/* data chunk length */
view.setUint32(40, samples.length*blockAlign, true);
作为旁注,您从float到byte的转换可能会溢出。考虑到最大浮点样本值可以是1.0,那么你的公式将转换为256,这太大了。
1.0 * 128 + 128 = 256
-1.0 * 128 + 128 = 0
您需要选择以下之一。我不知道是否有一个标准定义是正确的:
1.0 * 127 + 128 = 255
-1.0 * 127 + 128 = 1
1.0 * 127 + 127 = 254
-1.0 * 127 + 127 = 0