3

曲からの生の44.1kHzオーディオデータをJavascript配列として持っており、そこからズーム可能なタイムラインを作成したいと思います。

Audacityのタイムラインの例:

Audacityからのサンプル波形

何百万もの時点があるので、通常のJavascriptグラフィックライブラリはおそらくそれをカットしません:私は、確かではありませんが、通常のグラフライブラリはこの多くの時点で死ぬと思います。しかし、JSのこの種の視覚化のためのライブラリはすでに存在しますか?Canvas、webGL、SVGはすべて受け入れ可能なソリューションです。

できればズームとパンを使用したソリューション。

これは厳密にクライアント側で発生し、サーバー側のソリューションにはアクセスできないことに注意してください。

4

3 に答える 3

3

私はこれと同じ問題をかなり広範囲に調査しました。私の知る限り、あなたが望むものに近い既存のプロジェクトはwavesurfer.jsだけです。私はそれを使用していませんが、スクリーンショットと説明は有望に聞こえます。

この質問も参照してください。

幸運を祈ります。

于 2012-07-27T16:40:21.067 に答える
3

波形データを取得してすべてのデータポイントをレンダリングすることはできません。これは非常に非効率的です。

変数の説明:

  • width:描画領域の幅(ピクセル単位)。maxは画面の幅です。
  • 高さ:幅と同じですが、描画領域の高さ
  • spp:ピクセルあたりのサンプル数、これはズームレベルです
  • 解像度:ピクセルあたりのサンプル範囲ごとに取得するサンプル数、パフォーマンスと精度を微調整します。
  • スクロール:パフォーマンスのために仮想スクロールが必要になります。これはピクセル単位のスクロール位置です。
  • データ:生のオーディオデータ配列、おそらく数百万サンプルの長さ
  • drawData:描画に使用される縮小オーディオデータ

ビューポートにあるサンプルのみをオーディオデータから取得し、それらを減らす必要があります。通常、これにより2 *幅のデータセットが生成されます。このデータセットを使用して、画像をレンダリングします。ズームアウトするにはsppを増やし、ズームインするにはそれを減らします。スクロール値を変更するとパンします。

次のコードはO(RN)の複雑さを持っています。ここで、Nは幅、Rは解像度です。最大精度はspp<=解像度です。

コードは次のようになります。これはピーク値を取得します。rmsまたはaverageを実行することもできます。

let reduceAudioPeak = function(data, spp, scroll, width, resolution) {
    let drawData = new Array(width);
    let startSample = scroll * spp; 
    let skip = Math.ceil(spp / resolution);

    // For each pixel in draw area
    for (let i = 0; i < width; i++) {
        let min = 0; // minimum value in sample range
        let max = 0; // maximum value in sample range
        let pixelStartSample = startSample + (i * spp);

        // Iterate over the sample range for this pixel (spp) 
        // and find the min and max values. 
        for(let j = 0; j < spp; j += skip) {
           const index = pixelStartSample + j;
           if(index < data.length) {
               let val = data[index];
               if (val > max) {
                  max = val;
               } else if (val < min) {
                  min = val;
               }
           }
        }

        drawData[i] = [min, max];
    }
    return drawData;
}

このデータを使用すると、次のように描画できます。線、svgなどを使用できます。

let drawWaveform = function(canvas, drawData, width, height) {
   let ctx = canvas.getContext('2d');
   let drawHeight = height / 2;

   // clear canvas incase there is already something drawn
   ctx.clearRect(0, 0, width, height);
   for(let i = 0; i < width; i++) {
      // transform data points to pixel height and move to centre
      let minPixel = drawData[i][0] * drawHeigth + drawHeight;
      let maxPixel = drawData[i][1] * drawHeight + drawHeight;
      let pixelHeight = maxPixel - minPixel;

      ctx.fillRect(i, minPixel, 1, pixelHeight);
   }
} 
于 2017-11-16T20:53:33.360 に答える
0

私はブラウザでのSVGレンダリングにRaphaelJSを使用しましたが、非常にうまく機能しました。それが私が目指すものです。うまくいけば、SVGがその任務を果たせるでしょう。

于 2013-04-04T20:05:09.530 に答える