Web Audio API - Javascript 创建的 WAV 文件长度不正确且无声
Web Audio API - Javascript-created WAV file incorrect length and silent
>问题
Javascript创建的WAV文件长度不正确且无声。
详
我一直在使用JavaScript Web Audio API创建一个Web应用程序,该应用程序可以获取多个声音文件,从每个文件中随机获取一个块,然后将它们"混合"到采样器中(串行,即file1 + file2 + ... + fileN(,就像各种混搭一样。声音可以成功加载到我的自定义 SoundPlayer 对象中,并且可以播放它们。但是,当您将它们实际混合在一起时,生成的 WAV 文件的长度错误并且完全静音。
该界面允许以自己的音量加载和播放多达 10 种声音。您单击一个按钮将它们一起制作采样器 WAV,它会动态创建一个链接来下载它。我也有办法查看结果文件的十六进制转储,它在底部显示一堆 00 甚至一些 NaN,所以显然我的算法有缺陷,但我只是不知道如何。
当您单击"制作采样器!"按钮时,它将运行以下函数(使用包含音频缓冲区的自定义 SoundPlayer 对象数组作为其参数(:
function createSampler(sndArr) {
var numberOfChannels = _getSoundChannelsMin(sndArr);
var sndLengthSum = (function() {
var lng = 0;
for (var i = 0; i < sndArr.length; i++) {
lng += sndArr[i].audioBuffer.length;
}
return lng;
})();
var samplerBuffer = getAudioContext().createBuffer(
numberOfChannels,
sndLengthSum,
sndArr[0].audioBuffer.sampleRate
);
for (var i = 0; i < numberOfChannels; i++) {
var channel = samplerBuffer.getChannelData(i);
channel.set(sndArr[0].audioBuffer.getChannelData(i), 0);
for (var j = 1; j < sndArr.length; j++) {
channel.set(sndArr[j].audioBuffer.getChannelData(i), sndArr[j-1].audioBuffer.length);
}
}
// encode our newly made audio blob into a wav file
var dataView = _encodeWavFile(samplerBuffer, samplerBuffer.sampleRate);
var audioBlob = new Blob([dataView], { type : 'audio/wav' });
// post new wav file to download link
_enableDownload(audioBlob);
}
使用此功能获取通道数(单声道/立体声/等(:
function _getSoundChannelsMin(sndArr) {
var sndChannelsArr = [];
sndArr.forEach(function(snd) {
sndChannelsArr.push(snd.audioBuffer.numberOfChannels);
});
return Math.min.apply(Math, sndChannelsArr);
}
WAV 使用以下函数进行编码:
function _encodeWavFile(samples, sampleRate) {
var buffer = new ArrayBuffer(44 + samples.length * 2);
var view = new DataView(buffer);
// RIFF identifier
_writeString(view, 0, 'RIFF');
// file length
view.setUint32(4, 36 + 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);
// stereo (2 channels)
view.setUint16(22, 2, true);
// sample rate
view.setUint32(24, sampleRate, true);
// byte rate (sample rate * block align)
view.setUint32(28, sampleRate * 4, true);
// block align (channels * bytes/sample)
view.setUint16(32, 4, true);
// bits/sample
view.setUint16(34, 16, true);
// data chunk identifier
_writeString(view, 36, 'data');
// data chunk length
view.setUint32(40, samples.length * 2, true);
// write the PCM samples
_writePCMSamples(view, 44, samples);
return view;
}
WAV 文件中的字符串是这样处理的:
function _writeString(view, offset, string) {
for (var i = 0; i < string.length; i++){
view.setUint8(offset + i, string.charCodeAt(i));
}
}
PCM 样品随此一起交付:
function _writePCMSamples(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 文件变成了一个链接:
function _enableDownload(blob, givenFilename) {
var url = (window.URL || window.webkitURL).createObjectURL(blob);
var link = document.getElementById("linkDownloadSampler");
var d = new Date();
var defaultFilename = "sampler" + d.curDateTime() + ".wav";
link.style.display = "inline";
link.href = url;
link.download = givenFilename || defaultFilename;
}
这是我得到的十六进制转储的片段:
52 49 46 46 FFFD FFFD 02 00 57 41 56 45 66 6D 74 20 RIFF....WAVEfmt
10 00 00 00 01 00 02 00 FFFD FFFD 00 00 00 FFFD 02 00 ................
04 00 10 00 64 61 74 61 FFFD FFFD 02 00 00 00 00 00 ....data........
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
如果有人能帮助我看到我的方式的错误,我将不胜感激。很抱歉这篇文章很长,但我想提前发布所有相关细节和代码。
谢谢!
您忽略了在写出波次数据时增加偏移量。
试试这个:
output.setInt16(offset + i, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
^^^^
如果不移动写入位置,您只会继续覆盖文件中的相同偏移量,直到最终它被最后一个样本的值覆盖。
另外,我看到您已经发布了_writePCMSamples
代码,但调用者被注释掉了,您显然只是想内联做同样的事情。内联代码具有相同的错误。
- 使用压缩的JavaScript文件(不是运行时压缩)
- Connect-busboy:当管道文件写入蒸汽时,文件为空或不正确,具体取决于类型
- 将ng2图表添加到Typescript/ Angular 2项目引用路径和.js文件的路径不正确
- 使用 WebAPI 和 IE8/9 上传剑道文件不正确的错误消息
- Require JS with Knockout组件正在查找路径不正确的JS文件
- 当 Express 发送带有参数的静态 html 文件时,路径不正确
- Web Audio API - Javascript 创建的 WAV 文件长度不正确且无声
- 使用AngularJS循环访问JSON文件时出现“格式不正确”的Firefox错误
- "格式不正确的JSON流”;当从SharePoint 2013 REST API对文件使用moveto或cop
- 尽管文件顺序正确,但$highcharts不是一个函数
- 为什么合并的 JavaScript 临时文件格式不正确
- javascript从桌面拖动文件:draginter/dragleave不正确地触发
- Firefox在另存为类型-另存为对话框中的文件类型不正确
- Javascript外部文件链接不正确
- DataTable不是一个函数,引用的文件被正确加载
- 已转换的blob正在以不正确的格式获取文件
- Javascript文件路径链接不正确
- Webresource文件不能正确加载,抛出404错误,然后声明javascript文件没有在下面定义
- Node.JS post到JSON文件格式不正确
- 节点流添加标头发送文件不正确