我来到这里希望你们这里可爱的人们可以帮我解决一些我遇到的问题。
具体来说,每次我尝试使用webkitAudioContext的decodeAudioData方法时,它总是会触发错误处理程序并返回null错误。这是我目前正在使用的代码:
var soundArray;
var context = new webkitAudioContext();
function loadSound(soundName) {
var request = new XMLHttpRequest();
request.open('GET',soundName);
request.responseType = 'arraybuffer';
request.onload = function() {
context.decodeAudioData(this.response, function(buf) {
sounds[soundName] = buf;
},function(err) { console.log("err(decodeAudioData): "+err); });
}
request.send();
}
此时,它会不断将错误消息记录到控制台,说err(decodeAudioData) = null
,主要是因为这就是我决定记录它的方式。
在任何情况下,任何想法为什么会这样?
我正在使用Chrome Canary,v20.0.1121.0来尝试获得一些有用的功能。但是,显然,它不起作用!那么,任何想法我可以做什么?如果需要任何新信息,请告诉我,我会根据需要进行更新。
答案 0 :(得分:24)
真正的原因是createBuffer和decodeAudioData现在都有一个Bug,并为他们通常应该播放的文件抛出奇怪的模糊DOM异常12。 但是我们应该意识到这是一种新的和不断发展的技术,即使对于网络音频api也要感恩,因为它现在发生在我们身上的小奇迹。
他们在标题边界上缺少流同步,任何合理的流式音频格式解码器都应该从这开始。 而mp3或许多aac / adts文件都是流式文件格式。流意味着你可以在任何地方剪切或插入任何东西(各种标签甚至图像艺术品)解码器不应该关心未知数据。解码器应该只是寻找,直到他找到他知道并可以解码的标题。
我把这个临时解决方案放在一起,寻求最近的帧头开始并仅从该偏移量传递数据。
对于每个音频帧(每个大约200字节),mp3或mp2都会在oxFFF同步字上使用0XFFE和aac(adts)开始标题,这正是因为这个原因。因此两者都将在0xFFE上同步。 这是我目前用于播放以前未播放文件的代码。我讨厌的是,arrayBuffer没有subarray(),就像它的类型子节点一样,只返回不同偏移量的不同视图,而不是slice()返回的全新数组副本。如果只有webaudio api接受typedarrays作为输入,但不幸的是,创建arraybuffer的唯一方法似乎是巨大的slice()副本。 幸运的是,通常只需要一两次寻求。
node={};
node.url='usual_mp3_with_tags_or_album_artwork.mp3';
function syncStream(node){ // should be done by api itself. and hopefully will.
var buf8 = new Uint8Array(node.buf);
buf8.indexOf = Array.prototype.indexOf;
var i=node.sync, b=buf8;
while(1) {
node.retry++;
i=b.indexOf(0xFF,i); if(i==-1 || (b[i+1] & 0xE0 == 0xE0 )) break;
i++;
}
if(i!=-1) {
var tmp=node.buf.slice(i); //carefull there it returns copy
delete(node.buf); node.buf=null;
node.buf=tmp;
node.sync=i;
return true;
}
return false;
}
function decode(node) {
try{
context.decodeAudioData(node.buf,
function(decoded){
node.source = context.createBufferSource();
node.source.connect(context.destination);
node.source.buffer=decoded;
node.source.noteOn(0);
},
function(){ // only on error attempt to sync on frame boundary
if(syncStream(node)) decode(node);
});
} catch(e) {
log('decode exception',e.message);
}
}
function playSound(node) {
node.xhr = new XMLHttpRequest();
node.xhr.onload=function(){
node.buf=node.xhr.response;
node.sync=0;
node.retry=0;
decode(node);
}
node.xhr.open("GET", node.url, true);
node.xhr.responseType = "arraybuffer";
node.xhr.send();
}
答案 1 :(得分:5)
我在Chrome 19中使用webkitAudioContext
。今天我升级到了Chrome 20,我遇到了和你一样的问题。
我已经拍摄了另一个MP3文件,它再次起作用。两个文件之间的唯一区别是嵌入在错误的MP3文件中的封面。
我已取下封面,再次有效。