4

私がやったことについて少し混乱しています..私の知る限り、Java、特にDataOutputStreamはビッグエンディアンで値を書き込みます。

小さな信号発生器を作成していて、ファイルをリトル エンディアンで保存する必要があります。これまでのところ問題ありません。バイトを交換するだけです。

writeShort()「上位バイトを最初に書き込む」とも言います。

たとえば、10 進数の '2' は通常、次のように格納されます。

00 02 (big endian)
02 00 (little endian) is what I need.

だから私はバイトを交換します:

public static short swap (short value)
{
        int b1 = value & 0xff;
        int b2 = (value >> 8) & 0xff;

        return (short) (b1 << 8 | b2 << 0);
}

短く書いてください:

dos.writeShort(swap(x[t]));

16 進エディターは、次の形式でファイルを表示します。02 00

生成されたオーディオ ファイルを開こうとすると、何も聞こえません。(大胆な生データのインポートとサンプルレートなどの設定はすべて正しい)。

00 02ビッグエンディアンのファイルを取得して、バイトスワッピングを削除しました。

audacity を再度開いたところ、同じ構成でトーンが聞こえました。間違いなくリトルエンディアンを設定しました!

ファイルを Windows にコピーし (Mac で作業しています)、Cool Edit 2000 でファイルを開き、16khz、16 ビット符号なし pcm、リトル エンディアン (16 ビット LSB、MSB) を選択しました。ビッグエンディアンを何も選択せずに、再びトーンが聞こえました。

私の失敗はどこですか?これは私が説明したように機能しないはずなので、何かが私を混乱させます..

トーンの生成:

// x(t) = A*cos (2*pi * f * t + phi)
        // 
        if(null != dos) 
        {
            double sampPeriod = 1.0/16000;
            short x[] = new short[16000]; // 16k samples for 1 second
            for(int t=0; t < x.length; t++)
            {
                double time = t * sampPeriod;
                x[t] = (short) (amplitude * Math.sin(2.0*Math.PI*frequenz*time+phase));
            }

            for(int t=0; t < x.length; t++)
            {
                try {
                    dos.writeShort(x[t]);
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }

編集済み 2:16pm 02/04/13: 私の理解では何かが失敗であると想定して読んでいたところ、ウィキペディアで次の写真を見つけました。

読み取りアクセス

次の投稿の問題の答えを参照してください。

4

1 に答える 1

2

この質問に従ってください。

失敗は、リトル エンディアンまたはビッグ エンディアンとは関係ありません。LE と BE からわかったことはすべて正しかった。(しかし、読み取りアクセスについての最後の仮定ではありません。説明を探していたので、それは私の心をだましました..)

失敗は信号の振幅に関するものでした。

振幅が低すぎる場合 - ボリューム自体 (振幅によって生成される) が低すぎます。だから何も聞こえなかった。書き込まれたビッグ エンディアン ファイルをリトル エンディアンとして解釈すると、ファイル内のすべての短いサンプルがより大きなものになりました (zch のコメントに戻ります: リトル エンディアンとして解釈される場合、00 02 は 512 です)。

これにより、その時点でより高いサンプリング値が生成され、何かが聞こえました。

一般的に振幅高く設定し、バイトスワップをリトル エンディアンに正しく設定することで、再び何かを聞くことができました。したがって、主な失敗はエンディアンに関するものではありませんでした。

zch のコメントは私を何度も何度も陰気にし、値を読み取るウィンドウ上の小さな C++ コードを作成し、ネイティブの LE 解釈が zch が言ったのと同じであることを確認しました。それが私を振幅点に導き、今私は問題を見つけました。他の誰もこの愚かな失敗をしたり、この投稿を見つけて将来知ったりしないことを願っています:-)

于 2013-04-02T18:18:25.193 に答える