2011-04-19 29 views
4

バイト配列にpcmオーディオを格納しています。 1サンプルあたり16ビットです。私はそれを8ビット/サンプルのオーディオにしたい。16ビットpcmを8ビットに変換する

誰もそれを行うための良いアルゴリズムを提案できますか?

私はビットレートについて言及していませんが、それはアルゴリズムにとって重要ではないと思っています - そうですか?

+1

ビットレートは重要です(必ずしもそうではありません)。 A/Dコンバータを扱うとき(最終的にオーディオをA/D経由で出力する場合)、サンプルレートを65k倍(正確に計算した場合)に増やして、より少ないビットで高解像度を得ることができます)。 – flolo

+1

これはjavaではありませんが、ffmpegがどのように実装しているかを見てください。 http://ffmpeg.org/doxygen/0.5/pcm_8c-source.html – Aleadam

+0

@gosho_ot_pochivka 16ビットpcmを24ビットに変換する方法を教えてください。ありがとう – ravi

答えて

7

今は、上位バイトを取るだけでは十分ではない、つまり各サンプルの下位8ビットを破棄する理由がわかりません。

もちろん、サンプルは線形であると仮定します。もしそうでなければ、ビットを落とす前に線形化するために何かをする必要があるかもしれません。

short sixteenBit = 0xfeed; 
byte eightBit = sixteenBit >> 8; 
// eightBit is now 0xfe. 

コメントにAShellyによって示唆されるように、我々が廃棄しているバイトが高いの半分よりもその最大値である場合、すなわち1を追加し、丸めるのは良い考えかもしれません:

eightBit += eightBit < 0xff && ((sixteenBit & 0xff) > 0x80); 

テスト0xffに対してはクランプが実装されているので、1を0xffに追加し、それを0x00にラップすることは悪くありません。

+1

また、切り捨ての代わりに丸くすることもできます。 'eightbit + =(16ビットと0x80)>> 7;'を追加します。下位バイトがその範囲の半分より大きい場合は1を加算します。 – AShelly

+1

@AShelly:true、それは良いアイデアかもしれません...あなたのコードは、0xff00から0xffffの範囲の値を0x00にラップすることになりますが、これはまったく丸められないよりも悪いです。私は編集します。感謝の気持ちです。 – unwind

+0

ありがとうございます。入力がバイト配列(byte [] arr shortではない)の場合、これはバイトの半分、つまりarr [0]、arr [2]、arr [4]などを取り除くことを意味しますか? –

1

16ビットのサンプルを標準化してから、8ビットのサンプルの最大値で再スケールします。

これにより、各サンプルの下位8ビットが破棄されないため、より正確な変換が行われます。しかし、私のソリューションは、選択された答えよりも計算上高価です。

6

通常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ビットサウンドに変換するときにディザリングが行うことができる品質の違いに驚かれることでしょう。

1
byteData = (byte) (((shortData +32768)>>8)& 0xFF) 

これは私に役立ちました。

関連する問題