18

我来到这里希望你们可爱的人在这里可以帮助我解决我遇到的一些问题。

具体来说,每次我尝试使用 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 来尝试让某些东西正常工作。但是,显然,它不起作用!那么,知道我能做什么吗?如果需要任何新信息,请告诉我,我会根据需要进行更新。

4

2 回答 2

25

真正的原因是 createBuffer 和 decodeAudioData 现在都有一个错误,并为它们通常应该播放的文件抛出奇怪的模糊 DOM 异常 12。但我们应该意识到,这是一种新的、不断发展的技术,即使是网络音频 api,也应该感谢它,因为它发生在我们身上的小奇迹。

他们缺少任何合理的流音频格式解码器都应该开始的标头边界上的流同步。mp3 或许多 aac/adts 文件是流文件格式。流媒体意味着您可以在任何地方剪切它们或插入附加任何东西(各种标签甚至图像艺术品)解码器不应该关心未知数据。解码器应该一直寻找,直到找到他知道并且可以解码的标头。

我将这个临时解决方案放在一起,它寻求最近的帧头开始并仅从这个偏移量传递数据。

mp3 或 mp2 都是每个音频帧(每 200 字节左右)的开头标头,oxFFF 同步字上的 0XFFE 和 aac(adts) 正是出于这个原因。因此两者都将在 0xFFE 上同步。这是我目前用来播放以前未播放过的文件的代码。

我讨厌的是 arrayBuffer 没有 subarray() 像它的类型化的孩子一样从不同的偏移量返回不同的视图,而不是 slice() 返回的全新数组副本。如果只有 webaudio api 接受 typedarrays 作为输入,但不幸的是,创建 arraybuffer 的唯一方法似乎是巨大的 slice() 副本。谢天谢地,通常只需要一两次搜索。

强制 Web Audio Api 对文件不挑剔

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();
}
于 2013-01-11T11:19:36.987 回答
5

我使用webkitAudioContext的是 Chrome 19。今天我升级到了 Chrome 20,我遇到了和你一样的问题。

我已经获取了另一个 MP3 文件,它又可以工作了。两个文件之间的唯一区别是嵌入了错误 MP3 文件的封面。

我取下了盖子,它又可以工作了。

于 2012-06-27T15:51:39.483 回答