1

下の画像に示すようなグレースケール スペクトログラム (非複雑で 0 から 1 の間の値) を表すマトリックスを、wav ファイルなどのサウンド ファイルに変換する方法はありますか? この投稿seewaveでは、関数を使用してスペクトログラムでそれを行う方法について説明しistftます。ただし、私の場合、解決する必要がある2つの問題があります。

  1. 元のスペクトログラム ( で取得signal::specgram) は失われ、行列の次元は元のスペクトログラムとは異なります (つまり、周波数と時間の両方がアップ/ダウンサンプリングされます)。ただし、各行と各列の正確な周波数と時間の値はわかっています。
  2. マトリックス値の範囲は 0 ~ 1 であり、必要なほど複雑ではありません。istft

さらに、元のスペクトログラムの次元、元の波形オブジェクトのサンプル周波数、および元のスペクトログラムを取得するために使用されるウィンドウの長さとオーバーラップが既知です。

ありがとうございました!

ここに画像の説明を入力

4

1 に答える 1

1

オーディオは時間の経過とともにぐらつく曲線であり、このぐらつきは鼓膜またはマイクのピックアップ膜を反映しています...この信号は時間領域にあり、軸は X に時間、Y に曲線の高さです...典型的な CD 品質のオーディオには 44,100 サンプルがあります毎秒とは、毎秒このオーディオ曲線上のポイント数をキャプチャすることを意味します...キャプチャされるのはオーディオ曲線の高さですが、各サンプルが既知のサンプルレートでキャプチャされることを知っていると、時間が暗示されます...したがって、サンプルレートはデジタル オーディオの 2 つの重要なオーディオ属性 ... ビット深度はもう 1 つの属性です ... 2 バイト (16 ビット) を CD 品質曲線の高さの記録に使用すると、2 の 16 乗 (2^16 == 65536) が得られます。曲線の高さを格納するための個別の可能な値

生のオーディオ信号が時間領域にあることを強調することが重要です (X は時間 Y は曲線の高さです) ... これらのサンプルのセットを fft 呼び出しに送信すると、データは周波数領域に変換されます (X は周波数 Y です)はマグニチュード [エネルギー]) であるため、時間の直接的な次元はなくなりますが、周波数ドメイン データ全体の概念に焼き付けられます ... fft 呼び出しに供給するサンプル数の両方を決定する際には、トレードオフがあります ( sample window size ) つまり、freq ドメイン信号の周波数解像度を上げる ( incr_freq を下げる) には、 fft 呼び出しに入力するオーディオ サンプルを増やす必要がありますが、freq ドメインで時間的特異性を得るには、支払うサンプルをできるだけ少なくする必要がありますより低い周波数分解能とより低いピーク周波数 (ナイキスト下限) を取得することにより

スペクトログラムを生成するには、この曲線の高さ配列 (時間ドメイン) の 4096 サンプルのメモリ バッファーをフーリエ変換 ( fft ) にフィードします。これは、同じ数の配列要素の配列 ( freq ドメイン ) を返しますが、今回は各要素大きさ ( エネルギー レベル ) と位相を計算できる複素数を格納します ... 配列要素 0 は、無視できる DC バイアスです ... 各配列要素は、周波数増分を計算できる個別の周波数を表します

毎秒 44100 サンプルの sample_rate と 1 秒相当のサンプル ( 44100 )
を使用すると、1 ヘルツの周波数インクリメント分解能が得られます ... つまり、各周波数ビンは 1 ヘルツ離れています

incr_freq := sample_rate / number_of_samples

nyquist_limit_index := int(number_of_samples / 2)

ここでは、配列 complex_fft を反復処理する方法を示します (in go not r)

for index_fft, curr_complex := range complex_fft { // we really only use half this range + 1

    if index_fft <= nyquist_limit_index && curr_freq >= min_freq && curr_freq < max_freq {

        curr_real = real(curr_complex) // pluck out real portion of complex number
        curr_imag = imag(curr_complex) // ditto for imaginary portion

        curr_mag = 2.0 * math.Sqrt(curr_real*curr_real+curr_imag*curr_imag) / number_of_samples

        curr_theta = math.Atan2(curr_imag, curr_real)

        curr_dftt := discrete_fft{

            real:      2.0 * curr_real,
            imaginary: 2.0 * curr_imag,
            magnitude: curr_mag,
            theta:     curr_theta,
        }

時間の経過とともに、次の 4096 サンプルのセットを fft api 呼び出しに供給する上記のプロセスを繰り返し、時間領域配列のペアとそれに対応する周波数領域表現のセットを収集します。

プロットを作成したプロセスはこの繰り返しプロセスを実行したため、時間が X 軸として表示されます...プロットでは、データの各垂直バーは単一の fft 呼び出しからの出力を表し、その結果の大きさはその垂直の暗い部分として表示されますバーとプロット上の明るいドットは、より低いエネルギー周波数を示しています...そのプロットを生成したプロセスが時間の経過とともに進行した後にのみ、プロットが左から右に進行するため、次の垂直バーをプロットするためにデータが利用可能になりました。下の X 軸

もう1つの重要な洞察は、オーディオ(時間領域)から始めることができることに注意することです...サンプルのウィンドウ(たとえば4096)を入力し、この配列をfft呼び出しに送信して、それぞれの周波数の新しい配列(周波数領域)を取得しますその大きさと位相...ここに純粋な魔法があります。次に、この周波数ドメイン配列に対して逆フーリエ変換( ifft )を実行して、元の入力オーディオに(1次近似に)一致する時間ドメインの配列を取得できます信号

したがって、あなたの場合、プロットの左から右にデータを横切り、単一の周波数領域配列である垂直方向の大きさの値の各セット (グレースケールで示されます) に対して、この逆フーリエ変換を実行します。これにより、生のオーディオ信号 (時間)ドメイン ) 非常に短い時間セグメントのみ (4096 オーディオ サンプルなどで定義) ... この生のオーディオは wav ファイルのペイロード部分です ... データの次の垂直列に対してこのプロセスを繰り返します。プロット全体を左から右に歩いてきました...この一連のペイロード バッファを wav ファイルにつなぎ合わせます

于 2020-10-04T13:35:29.197 に答える