9

まず、これは宿題や...プロジェクト用です。

プロジェクトのJavaでサウンドデータウェーブをグラフに描画する方法の背後にある考え方を理解するのに苦労しています。この割り当ては、UIとすべてを使用して完全にゼロから行う必要があるため、基本的に.wavファイルエディターを作成します。 私が抱えている主な問題は、サウンドデータをグラフに取り込んで描画することです。現在、ランダムに生成された値の配列が描画されています。

これまでのところ、wavファイルを実行して検証しているミニプログラムが実際にwavファイルであるかどうかを確認しています。

私はそれをFileInputStreamで読み込んで、検証しています:RIFFバイト(0-3)、FileLength(4-7)、WAVEバイト(8-11)、そしてフォーマットチャンクフォーマット(RIFFチャンクの終わりから開始) ;そして、インデックスをその最後に配置し、フォーマット0〜3、フォーマットチャンクの長さ4〜7を指定し、次に、Waveファイルのすべての仕様に対して次の16バイトを指定し、それらを適切な名前付き変数に格納します。

DATAチャンクとその長さを超えると、すべてのサウンドデータになります。これは、サウンドデータのバイトごとに各バイトを格納する方法や、サウンドデータの振幅に関連する値に変換する方法がわからないためです。音。検証は似ていると思ったので同じだと思いましたが、そうではないようです...それか、私が数日間これを見つめていたので、非常に単純なことを複雑にしてきました。

どんな助けでもありがたいです。

4

3 に答える 3

18

私はJavaプログラマーではありませんが、オーディオのレンダリングについてはかなり知っているので、次のことが役立つかもしれません...

ほとんどの場合、使用可能なピクセルよりもはるかに多くのサンプルがあることを考えると、キャッシュされた削減またはサンプルデータの「要約」から描画するのが賢明な方法です。これは通常、オーディオエディタ(Audacityなど)がオーディオデータをレンダリングする方法です。実際、最も一般的な戦略は、ピクセルあたりのサンプル数を計算し、サイズの各ブロックの最大サンプルと最小サンプルを見つけて、SamplesPerPixel各max-minペアの間に垂直線を引くことです。この縮小をキャッシュするか、ズームレベルごとに一連の縮小をキャッシュすることをお勧めします。Audacityはディスク上の一時ファイル(「ブロックファイル」)にキャッシュします。

ただし、実際には、サイズの1つからではなく、固定サイズのチャンク(たとえば、256サンプル)から初期のmax-minペアを計算する必要があるため、上記はおそらく過度に単純化されていますSamplesPerPixel。次に、キャッシュされた削減からさらに「オンザフライ」削減を計算できます。重要なのはSamplesPerPixel、ユーザーはいつでもキャンバスのサイズを変更できるため、通常は動的な量になるということです(それが理にかなっていることを願っています...)。

また、キャンバスに描画するときは、サンプル値をキャンバスの幅と高さでスケーリングする必要があることにも注意してください。これを行うための最良の方法(少なくとも垂直方向)は、サンプルを正規化してから、キャンバスの高さを掛けることです。16ビットオーディオは[-32768、32767]の範囲のサンプルで構成されているため、正規化するには、浮動小数点を32768で除算するだけです。次に、符号を逆にして(波形をキャンバス座標に反転するため)、1を追加します(補正するため)。負の値の場合) 、キャンバスの高さの半分を掛けます。とにかく、それが私がそれをする方法です。

このページでは、JavaSwingを使用して基本的な波形表示を作成する方法を示します。詳細については説明していませんが、max-minペアを計算するのではなく、データをダウンサンプリングするだけだと思います。もちろん、これはmax-min法ほど正確な削減にはなりませんが、計算は簡単です。

物事を適切に行う方法を知りたい場合は、Audacityソースコードを掘り下げる必要があります(ただし、注意してください-かなり厄介なC ++です)。一般的な概要を知るには、Audacityの原作者であるDominicMazzoniによる「ディスクベースのオーディオ編集のための高速データ構造」をご覧ください。ただし、 CMJから購入する必要があります。

于 2012-10-14T05:19:04.830 に答える
3

標準のWAVファイルの場合、実際には非常に簡単です。ヘッダーを通過すると、16ビットごとに2の補数整数として解釈されます。DataInputStreamを使用することをお勧めします。それ以降は、readShort()を呼び出すのと同じくらい簡単です。

これらは、各サンプルポイントでの振幅値です。ほとんどの場合、水平方向のピクセルよりもはるかに多くのサンプルがあるため、平均化などを行うことをお勧めします。ある種の線グラフにすべてのサンプルをプロットしようとするのは、最善の方法ではない場合があります。

于 2012-10-14T04:51:59.847 に答える
1

最初に行う必要があるのは、生データを読み取ることです。Wavファイルパーサーの作成はそれほど難しくありませんが、javasoundAPIを使用することもできます。このAPIを使用するためのいくつかの素晴らしいヒントとサンプルコードがここにあります:

http://www.jsresources.org/

独自のパーサーを作成する場合は、ここから開始できます。

https://ccrma.stanford.edu/courses/422/projects/WaveFormat/

生データを取得したら、それを時間の関数として表示できます。これを波形と呼びます。

ただし、ユーザーが大量のデータを「ズームアウト」した場合、波形の表示には時間がかかります。この方法でレンダリングするには、1時間分のデータに長い時間がかかります。したがって、ほとんどのアプリケーションは、ズームアウトされたデータの描画を高速化するために、一部のデータを事前計算します。これを行う「正しい」方法は次のとおりです。

  • ファイル内のサンプルのブロックをループします(50〜500程度)
    • サンプルのブロックを読む
    • それらすべてのサンプルの絶対値を取ります
    • 絶対値の最大値を取る
    • そのブロックの「ズームアウト」値として最大値を保存します

私が「正しい」と言うとき、これは誰もが行うことを意味するので、人々が期待しているように見えるビューになります。この仲間が発見したように、何か別のことをすると(たとえば、ピークを探す代わりにログを計算したり、平均化したり)、正しく見えないものが得られます。

波形の描画-DBに変換すると波形が押しつぶされます

于 2012-10-15T15:18:36.607 に答える