1

私はそれが千回前に尋ねられたことを知っています、しかし私はまだ解決策を見つけることができません。SOを検索して、確かにそのアルゴリズムを見つけましたが、それを真に理解するために必要な数学的知識が不足しているため、どうしようもなく迷子になっています。

最初に、私の目標は、スペクトログラム全体を計算して画像に保存し、ビジュアライザーに使用することです。

Sound.computeSpectrumを使用してみましたが、サウンドを再生して終了するまで待つ必要があります。すべての曲を聴くよりも短い時間でスペクトログラムを計算したいと思います。そして私は2時間のmp3を持っています。

私が今していることは、Soundオブジェクトからバイトを読み取り、2つのVectors(。)に分割することです。次に、タイマーを使用して、100ミリ秒ごとに、次のようにアルゴリズムを実装する関数(step1)を呼び出します。

  1. ベクトルごとに(チャネルごとに)、要素にハン関数を適用します。
  2. 各ベクトルについて、虚数部を無効にします(そのための2次ベクトルがあります)
  3. ベクトルごとにFFTを適用します
  4. 各ベクトルについて、最初のN/2要素の大きさを見つけます
  5. ベクトルごとに、大きさの2乗をdBスケールに変換します
  6. 終わり。

しかし、私は負の値しか得られず、結果の30%だけが役立つ可能性があります(残りは同じです)

「ベクトルごと」の部分を取り除くために、1つのチャネルのみのコードを投稿します。

private var N:Number = 512;
private function step1() : void
{
    var xReLeft:Vector.<Number> = new Vector.<Number>(N);
    var xImLeft:Vector.<Number> = new Vector.<Number>(N);

    var leftA:Vector.<Number> = new Vector.<Number>(N);

    // getting sample range
    leftA = this.channels.left.slice(step * N, step * (N) + (N));

    if (leftA.length < N)
    {
        stepper.removeEventListener(TimerEvent.TIMER, getFreq100ms);
        return;
    }
    else if (leftA.length == 0)
    {
        stepper.removeEventListener(TimerEvent.TIMER, getFreq100ms);
        return;
    }

    var i:int;

    // hann window function init
        m_win = new Vector.<Number>(N);
        for ( var i:int = 0; i < N; i++ )
            m_win[i] = (4.0 / N) * 0.5 * (1 - Math.cos(2 * Math.PI * i / N));

    // applying hann window function
    for ( i = 0; i < N; i++ )
    {
        xReLeft[i] = m_win[i]*leftA[i];
        //xReRight[i] = m_win[i]*rightA[i];
    }

    // nullify the imaginary part
    for ( i = 0; i < N; i++ )
    {
        xImLeft[i] = 0.0;
        //xImRight[i] = 0.0;
    }

    var magnitutel:Vector.<Number> = new Vector.<Number>(N);

    fftl.run( xReLeft, xImLeft );

    current = xReLeft;
    currf = xImLeft;

    for ( i = 0; i < N / 2; i++ )
    {
        var re:Number = xReLeft[i];
        var im:Number = xImLeft[i];
        magnitutel[i] = Math.sqrt(re * re + im * im);
    }

    const SCALE:Number = 20 / Math.LN10;
    var l:uint = this.total.length;
    for ( i = 0; i < N / 2; i++ )
    {
        magnitutel[i] = SCALE * Math.log( magnitutel[i] + Number.MIN_VALUE );
    }

    var bufferl:Vector.<Number> = new Vector.<Number>();

    for (i = 0; i < N / 2 ; i++)
    {
        bufferl[i] =  magnitutel[i];
    }

    var complete:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
    complete[0] = bufferl;
    this.total[step] = complete;

    this.step++;
}

この関数は、タイマー(ステッパー)によってディスパッチされたイベントで実行されます。明らかに、私は負の値しかなく、さらに多くの値が1から7000の範囲であると言ったので、何か間違ったことをします(少なくとも)。

よろしくお願いします。

敬意を表して、ポール

4

1 に答える 1

0

負の dB 値は問題ありません。色を付けたいポイントの数が正になるまで、定数 (ボリューム コントロールを表す) を追加するだけです。負のままである残りの値は、通常、スペクトログラムで黒として表示または色付けされます。どんなに負であっても(FFTの数値ノイズである可能性があり、これは巨大な負のdB数、またはlog(0)のNaNまたは-Infでさえある可能性があるため)。

于 2012-06-18T14:24:06.913 に答える