0

簡単に言うと、オーディオ信号出力を int r にしています。つまり、r の値は 32768 ~ - 32768 です。

正規化ルーチンを作成しようとしましたが、何らかの理由で次のコードが半波を生成し、上部のみが表示されます。つまり、0 より上のすべてが負の値ではありません。

ここにあります(difはint、dif_vorherも)

if (r * 8 > 32768)
  dif = dif_vorher;
else if (r * 8 < -32768)
  dif = dif_vorher;
else
  dif = r * 8;        
dif_vorher = dif;

次に、raw ファイルに書き込む準備ができています。

if (dif != 0)
{
  putc((char) ( (unsigned)dif       & 0xff),ausgabe);
  putc((char) (((unsigned)dif >> 8) & 0xff),ausgabe);
}    

この生ファイルには上限値しかありません。私も試しました

if (r * 8 > 32768)
  dif = 32768;
else if (r * 8 < -32768)
  dif = -32768;
else
  dif = r * 8;        

if (r * 8 > 32768 || r * 8 < -32768)
  dif = -32768;
else
  dif = r * 8;  

私が使用する場合を除いて、同じ結果

if (r * 8 > 32768)
  dif = 32768;
else if (r * 8 < -32768)
  dif = -32768;
else
  dif = r * 8;   

上部も歪んでいます。

なぜ負の部分が省略されているのですか?

編集: r * 8 の最大値は 524272 で、最小値は 0 であることがわかりました。したがって、r_max = 524272/8 = 65534; 65534/2 = 32767 ですので、32768 だけ負の値にならないように値をシフトさせているようです。

4

1 に答える 1

0

重要な問題は、小さなスペースに大きな数を入れようとしていることにあると思います。つまり、最初に元の数値をストレージに快適に収まるサイズに縮小しないとchar、int データの一部の情報が切り捨てられ、大きな負の値がゼロとして解釈されます。ちなみに、負の値のいずれかが -128 より大きい場合、式:
(char) ( (unsigned)dif & 0xff) は負の値を返すと思います。

そもそもその式で正確に何をしているのかはまだわかりません。つまり、正規化関数からスケーリングされたデータ値が既にある場合 (機能すると仮定して)、それをファイルに入れませんか?

いずれにせよ、私が知る限り、あなたは 2 つのことを達成しようとして
います。に保存しchar、 を使用してそのデータを putc()ファイルに書き込みます。スケーリングの問題を解決すれば、
正と負の結果をファイルに書き込んでも問題ありません。

+/- 32768 から char が保持する値、つまり 127 から -128 までの範囲の入力をスケーリングするには、データ内の各値にこれら 2 つの値の比率を掛けることができます。何かのようなもの:

char ScaleToChar(int x); //prototype

char ScaleToChar(int x)
{
    int a = x;
    float ratio;
    //bound a:  -32768 to 32768
    if (abs(x) > 32768)
    {
        a = (x >= 0) ? (32768) : (-32768);
    }
    //scale x: -128 to 127
    ratio = (a <= 0) ? (128.0/32768.0) : (127.0/32768);

    return (char)(a * ratio);
}

これを使用して、あなたの行:

  putc((char) ( (unsigned)dif       & 0xff),ausgabe);
  putc((char) (((unsigned)dif >> 8) & 0xff),ausgabe);  

なるだろう

  putc(ScaleToChar(dif),ausgabe);

(2 番目の呼び出しで何をしているのかわかりませんが、必要に応じて shift と & op を実行してから を呼び出すことができますScaleToChar())

[編集]

最初に提案したスケーリングのアプローチではなく、波形をフィルタリングする必要があると思います。つまり、データの配列をインクリメントし、波形が限界 (負または正の限界) に近づいたら、最後の 10 ~ 15 の配列値などの履歴を使用して、潜在的に誤った値のトレンドを決定する方法を決定します。制限に違反しないようにします。このようにして、大量のデータに触れる必要がなくなります。これにより、忠実度を維持することができます (スケーリング アプローチとは異なります)。同時に、変更されたデータへの変更は、波形の違反セクションの中心付近に広がる所定の領域内にあるデータに限定されます。

FIR フィルター アプローチが思い浮かびますが、移動平均のような単純なものでも機能します。制限に違反する危険にさらされていないデータの値は、フィルターによって処理される必要はありません。コンセプトとしては、このアプローチはそれほど複雑に思えません。しかし、どうやってそれを解決するかを考え始めたとき、かなり複雑になる可能性があることに気付きました (たとえば、予測分析にカルマン フィルターを適用するなど)。そうは言っても、単純な移動平均など、かなり単純に保つこともできます。

于 2013-10-25T18:37:32.023 に答える