私は、署名されたショートパンツの配列が受信されるサウンド変換アルゴリズムを研究しています。
アルゴリズムの特定の時点で、サンプルを16ビットから14ビットに変換し、次のようにします。
int16_t sample = (old_sample + 2) >> 2;
最下位2ビットを削除したいので、シフトが必要であることは明らかですが、+2
そこはどうでしょうか。
シフトダウンすると、最下位2ビットが失われます。シフトするだけで、下の2ビットが両方とも設定されている場合でも、常に切り捨てられます。失われるビットの大きい方が設定されている場合は、2を加算すると切り上げられます。
(ビット数を減らすためのより良い方法は、ディザリングを使用することです。つまり、サンプルサイズを減らす前にランダムな(そして非常に少量の)ノイズを追加することです。これにより、音が周期的であるため、多くの場合、丸めは特定の周波数で一貫して上または下になり、サウンドに知覚可能な歪みが生じる可能性があります。リンクされているwikipediaの記事では、私よりもよく説明されています!)
丸めの効果があると思いますか?old_sample
私は彼らが以上であるというケースを考慮したことを願っていMAX_INT16 - 2
ます。そうしないと、オーバーフロー時に問題が発生する可能性があります。
他の人が指摘しているように、+ 2は、右シフトで最も近い除算を実行するための試みです。ただし、2つの問題があります。
32766または32767の入力サンプルはint
、2が追加されるとオーバーフローする可能性があります(int
32767までの数値を表すことができることが保証されているだけです)。
負の数の右シフトの動作は、実装によって定義されます。
これらの問題を回避するには、次のようにする必要があります。
int16_t sample = (old_sample > 0 ? old_sample + 2L : old_sample - 2L) / 4;
(シフト演算子とは異なり、C99の除算演算子はゼロに丸めるように定義されています)。
そのコードの意図は、他の応答に示されているように、おそらく丸められています。しかし、これは確かにそれの非常に悪い例です。ここでは、元のプログラマーがおそらく意図していなかったことが2つあります。
int
および再割り当てint16_t
signed
値の右シフトランダムなプラットフォームでの着陸の精度がわからないためint
、(+2
これは単なる)への昇格はここでは良くありません。int
int
値が負の場合、値の右シフトsigned
はコンパイラーに依存するため、結果もプラットフォームごとに異なる可能性があります。