使用 Web 音频 API 使用 start/noteOn 进行非法调用

Illegal invocation with start/noteOn using Web Audio API

本文关键字:使用 非法 调用 noteOn Web 音频 API start      更新时间:2023-09-26

所以基本上我已经在 Chrome 中对此进行了测试,也许代码的顺序是关闭的或其他什么,由于范围请求错误,试图使用"网络音频"覆盖 HTML5 音频的一些功能,用于制作具有循环音效和音乐的游戏......

我收到"非法异常"错误。代码如下:

    var url='example.mp3';
    var a_result=new Object();
    a_result.loaded=false;
    a_result.evalstring='';
    a_result.loop=false;
    a_result.play=function(){
        var asrc=a_result.source;
        asrc.loop=a_result.loop;
        //try{
            var playfunc=asrc.start||asrc.noteOn;
            playfunc(0);
        //}catch(e){
            /* do nothing */
        //}
    }
    a_result.pause=function(){
        var asrc=a_result.source;
        try{
            var stopfunc=asrc.stop||asrc.noteOff;
            stopfunc(0);
        }catch(e){
            /* do nothing */
        }
    }
    var asrc=actx.createBufferSource();
    asrc.connect(actx.destination);
    var req=new XMLHttpRequest();
    req.open('GET',url,true);
    req.responseType='arraybuffer';
    req.onload=function(){
        if(a_result.loaded==false){
            asrc.buffer=actx.createBuffer(req.response,false);
            a_result.source=asrc;
            a_result.loaded=true;
        }
        var cont=a_result;
        eval(cont.evalstring);
    }
    req.onerror = function() {
        if(a_result.loaded==false){
            a_result.loaded=true;
        }
    }
    try{
        req.send(null);
    }catch(e){
        req.onerror();
    }
    return a_result;

然后稍后在声音加载后,我会执行以下操作:

a_result.play();

而不是播放它会产生错误。

这是一个声音测试,它使用上述代码和下面建议的修复程序,它可以在 Chrome 中工作,成功地解决了蹩脚的网络服务器上的范围请求问题。这是另一个有问题的问题(在asrc.buffer=actx.createBuffer(req.response,false)上抛出某种"无效字符串"错误;在Iron中并在Chrome中默默地搞砸了)。

以下是根据建议编辑的代码:

    var url='example.mp3'
    var a_result=new Object();
    a_result.loaded=false;
    a_result.evalstring='';
    a_result.loop=false;
    a_result.play=function(){
        var asrc=a_result.source;
        asrc.loop=a_result.loop;
        try{
            if(asrc.start){
                asrc.start(0);
            }else{
                asrc.noteOn(0);
            }
        }catch(e){
            /* do nothing */
        }
    }
    a_result.pause=function(){
        var asrc=a_result.source;
        try{
            if(asrc.stop){
                asrc.stop(0);
            }else{
                asrc.noteOff(0);
            }
        }catch(e){
            /* do nothing */
        }
    }
    var asrc=actx.createBufferSource();
    asrc.connect(actx.destination);
    var req=new XMLHttpRequest();
    req.open('GET',url,true);
    req.responseType='arraybuffer';
    req.onload=function(){
        actx.decodeAudioData(req.response,function(buffer){
            if(buffer){
                if(a_result.loaded==false){
                    asrc.buffer=buffer;
                    a_result.source=asrc;
                    a_result.loaded=true;
                }
                var cont=a_result;
                eval(cont.evalstring);
            }
        });
    }
    req.onerror = function() {
        if(a_result.loaded==false){
            a_result.loaded=true;
        }
    }
    try{
        req.send(null);
    }catch(e){
        req.onerror();
    }
    return a_result;
它似乎

不再有语法错误,但是,它似乎没有解决Chrome上的可玩性问题(上面的第二个测试用例更新了)。具体来说,声音停止后,它不想再次播放。-显然是因为它在规格中。每次播放时,都必须将缓冲区应用于新的声源。

在新页面中,您将在XMLHTTPRequest的结果上调用createBuffer(data,false)。你几乎肯定想在这些结果上调用decodeAudioData(),相反 - createBuffer 没有 2 参数版本,并且即使您尝试将任意数据推送到缓冲区中,也与您传递的参数不匹配。 从代码浏览中可以看出,您正在下拉 MP3 或 Ogg 文件 - 您需要解码它们。

play方法(start()或noteOn())需要在buffersourcenode对象上调用,而不是与其分离。 您有以下几种选择:

1)我强烈建议只包含我的音频上下文猴子补丁库(https://github.com/cwilso/AudioContext-MonkeyPatch/)并使用新的(start())语法。 没有糊涂,没有大惊小怪。

2)你可以只使用if语句而不是使用playfunc来切换:

if (asrc.start)
    asrc.start(0);
else
    asrc.noteOn(0);

3)你可以将play函数绑定到对象上,并保持你的代码基本相同:

var playfunc=asrc.start ? asrc.start.bind(asrc) || asrc.noteOn.bind(asrc);
playfunc(0);

4)您可以将playfunc()方法推送到对象本身上(我认为这将起作用):

asrc.playfunc=asrc.start||asrc.noteOn;
asrc.playfunc(0);