pcmオーディオをバイト配列に格納しています。サンプルあたり16ビットです。サンプルオーディオあたり8ビットにしたい。
誰かがそれを行うための良いアルゴリズムを提案できますか?
アルゴリズムにとって重要ではないと思うので、ビットレートについては触れていません。
上位バイトを取得するだけでは不十分な理由、つまり各サンプルの下位8ビットを破棄するだけでは不十分な理由は今のところわかりません。
もちろん、これはサンプルが線形であることを前提としています。そうでない場合は、ビットをドロップする前に、線形化するために何かを行う必要があるかもしれません。
short sixteenBit = 0xfeed;
byte eightBit = sixteenBit >> 8;
// eightBit is now 0xfe.
AShellyがコメントで示唆しているように、丸めるのは良い考えかもしれません。つまり、破棄するバイトが最大値の半分よりも大きい場合は1を追加します。
eightBit += eightBit < 0xff && ((sixteenBit & 0xff) > 0x80);
0xffに対するテストではクランプが実装されているため、0xffに1を追加し、それを0x00にラップするリスクはありません。これは悪いことです。
16ビットサンプルは通常符号付きで、8ビットサンプルは通常符号なしであるため、最も簡単な答えは、16ビットサンプルを符号付きから変換する必要があるということです(16ビットサンプルはほとんどの場合、-32768から+32767)符号なしにして、結果の上位8ビットを取得します。Cでは、これはoutput =(unsigned char)((unsigned short)(input + 32768)>> 8)として表すことができます。これは良いスタートであり、あなたのニーズには十分かもしれませんが、あまりいい音にはなりません。「量子化ノイズ」のためにラフに聞こえます。
量子化ノイズは、元の入力とアルゴリズムの出力の差です。何をしてもノイズが発生し、平均して「半分」のノイズになります。それについてできることは何もありませんが、ノイズを目立たなくする方法はあります。
量子化ノイズの主な問題は、パターンを形成する傾向があることです。入力と出力の差が完全にランダムである場合、実際には問題なく聞こえますが、代わりに、出力は波形の特定の部分では高すぎ、次の部分では低すぎます。あなたの耳はこのパターンを拾います。
良い音を出すには、ディザリングを追加する必要があります。ディザリングは、量子化ノイズを平滑化しようとする手法です。最も単純なディザリングは、ノイズパターンが実際の信号パターンの邪魔にならないように、ノイズからパターンを削除するだけです。より良いディザリングは、さらに一歩進んで、複数のサンプルからのエラー値を合計し、合計エラーが修正する価値があるほど大きくなったときに修正を追加することによって、ノイズを減らすための手順を実行できます。
さまざまなディザリングアルゴリズムの説明とコードサンプルをオンラインで見つけることができます。調査するのに適した領域の1つは、SoXツール(http://en.wikipedia.org/wiki/SoX )です。ソースのディザリング効果を確認し、ディザリングを有効にした場合と無効にした場合で、さまざまなサウンドを16ビットから8ビットに変換してみてください。8ビットサウンドに変換するときにディザリングによって生じる品質の違いに驚かれることでしょう。
byteData = (byte) (((shortData +32768)>>8)& 0xFF)
これは私のために働いた。
16ビットサンプルを正規化してから、8ビットサンプルの最大値で再スケーリングします。
これにより、各サンプルの下位8ビットが破棄されないため、より正確な変換が可能になります。ただし、私のソリューションは、選択した回答よりも計算コストが高くなります。