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をスローすることです。しかし、これは新しく進化しているテクノロジーであり、私たちに起こった小さな奇跡以来、現在のWebオーディオAPIにも感謝する必要があります。

それらは、ストリーミングオーディオフォーマットの合理的なデコーダーが開始すべきヘッダー境界でのストリーム同期を欠いています。そしてmp3または多くのaac/adtsファイルはストリーミングファイルフォーマットです。ストリーミングとは、どこにでも切り取ったり、何かを追加したりできることを意味します(画像アートワークでもさまざまなタグ)デコーダーは未知のデータを気にする必要はありません。デコーダーは、自分が知っていてデコードできるヘッダーが見つかるまでシークする必要があります。

最も近いフレームヘッダーの開始を探し、このオフセットからのデータのみを渡すこの一時的なソリューションをまとめました。

mp3またはmp2はすべて、この理由だけで存在するoxFFF同期ワード上の0XFFEとaac(adts)を使用して、すべてのオーディオフレーム(約200バイトごと)のヘッダーを開始します。したがって、両方とも0xFFEで同期します。これは、以前に再生されなかったファイルを再生するために現在使用しているコードです。

私が嫌うのは、arrayBufferには、slice()が返すまったく新しい配列コピーではなく、異なるオフセットから異なるビューを返す、型指定された子のようなsubarray()がないことです。webaudio apiだけがtypedarraysを入力として受け入れたが、残念ながら、arraybufferを作成する唯一の方法は巨大なslice()コピーのようです。ありがたいことに、通常は1つか2つのシークだけが必要です。

WebAudioApiにファイルについてうるさくないように強制する

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

Chrome 19で使用webkitAudioContextしていました。今日、Chrome 20 にアップグレードしましたが、あなたと同じ問題があります。

別の MP3 ファイルを取りましたが、再び機能します。2 つのファイルの唯一の違いは、間違った MP3 ファイルに埋め込まれたカバーです。

カバーを外しましたが、また動きます。

于 2012-06-27T15:51:39.483 に答える