音声ファイルをJavaで自作したいと思います。始めるにあたって基本的な知識が必要です。Javaに限らず一般的な情報なのですでに知っていることもあるかと思います。
一般にコンピューターで扱う音声はデジタル信号です。デジタルの音声の品質を決めるにあたって大きな要素が三つあります。サンプルレートとサンプルサイズ、チャンネル数です。一つ一つ説明していきます。
サンプルレート sample rate
音声を記録するときの「時間あたりの細かさ」を表します。デジタルの音声信号はその時その時の音の大きさを数字の情報で記録します。その情報を1秒に何回記録するかによって音の品質が変わってきます。
これは画像でいうと解像度にあたります。解像度が低いとイメージがモザイクがかって見えますが逆に高いと精密に見えます。サンプルレートの違いによってこれと同じようなことが音声でも起こります。
CDは一秒間に44100回分の数字情報を保持しています。一般には44.1kHzと表記されます。Hzは周波数の単位に使われているものですが「1秒あたりの情報の量」という意味に置き換えられて使われています。
なぜ44100という数字になったのかはCDの規格が作られた当時の状況があるようですが一番大きなポイントとしては人の可聴域によるものです。可聴域とは人の聞き取ることのできる周波数の範囲のことですが周波数の高い方が20kHzあたりであることが知られています。サンプルレートはその数の半分までの音を再現できます。このあたりは込み入った話なので省略します。
44.1kHzのサンプルレートの音声は高い音域が22.05kHzまでの高さの音を保持することができ可聴域をカバーすることができます。
サンプルサイズ sample size
サンプルレートは「時間あたりの細かさ」についてでしたがサンプルサイズはサンプルするデータ「一つあたりの情報の細かさ」についての表現になります。一つの音声信号をどのくらいの細かさでとるかということですが画像でいうと色の多さ、色合いの豊富さに相当します。ビットデプスbit depthともいわれてていますが「深さ」を表現していると言っても良いでしょう。
サンプルサイズはビットbitで表します。実際には8ビットを一まとまりとして考えるバイトbyteの単位で変化するのでサンプルサイズは8の倍数になります。CDでのサンプルレートは16ビットですがこれは2の16乗つまり65536通りの整数型の音の情報を保持することができます。これはJavaの基本データ型でいうとshortにあたります。
最近のハイレゾは24bitや32bitのものがあります。24bitは2の24乗つまり16777216通りの整数型の音の情報を保持することができます。32bitは一般には整数型ではなく浮動小数点を使っています。Javaの基本データ型でいうとfloatにあたります。
チャンネル数
サンプルを同時にいくつ保持するかを表します。通常は使用するスピーカーの数と同じです。ステレオであればチャンネル数は2、モノラルであれば1です。
データ量
以上の観点から音声ファイルのデータ量を計算することができます。
例えばCDの品質であればサンプルレートは1秒に44100回、サンプルサイズは16ビットつまり2バイト、チャンネルは2なので
44,100 x 2 x 2 = 176,400(バイト)
3分の曲を保存するには180(秒)をかけて31,752,000バイト、およそ30メガバイトのデータ量になります。結構なデータ量になることがわかります。
これは圧縮していない、つまりリニアPCMという形式での状態です。通常音楽を聞く場面ではmp3などで圧縮していますのでもっとデータ量はすくなくなります。
ただ音声を編集する場合にはそのままの状態、リニアPCMで扱います。windowsではwavという拡張子になっているものです。macではaiffという拡張子のファイルもありますが録音機器ではwavのほうが広く普及しています。
AudioFormatの定義
Javaではオーディオの形式をAudioFormatというクラスで定義します。例えばCD音質のオーディを形式は以下のようにします。
float sample_rate = 44100; int sample_size_byte = 2; int channels = 2; boolean signed = true; boolean big_endian = false; AudioFormat format = new AudioFormat(sample_rate, sample_size_byte * 8, channels, signed, big_endian);
signedは通常trueにします。これは無音の状態が0という意味になります。big_endianは複数バイトの順序を表していて通常の順序、つまり大きい桁が最初にきて小さい桁が後にくるものであればtrueになります。