音声音楽スポンサーリンク前回コードも作り実行結果の音声ファイルもできましたがあまり詳しい説明はしていませんでした。ここでは処理の詳細を説明します。Javaで矩形波のWavファイルを作成する(1)周期を求める一定の音の高さの場合波の周期は一定です。一秒間にサンプルする数のことをサンプリングレートと呼んでいますが1周期あたりのサンプル数を求めます。サンプリングレートを周波数で割ります。freq;たいていの場合は割り切れないので結果の値もdouble値にしておきます。音量を求めるサンプルサイズのビット数をxとすると最大音量は以下のように求められました。1これを実際の出力値として使います。最小音量はこの数字を負にしたものとします。最小音量というと無音に近いように思えますが実際には最大値と同じ音圧が負の方向に働いているという意味です。最大値がスピーカーが一番飛び出した状態とすると最小値は一番奥に戻っている状態のことになります。処理は以下のようにしています。1;インデックスを保持するサンプルを取得する際に自分が今どこにいるのかを保持しておきます。0;サンプルを取得するごとにインクリメント、つまり1増やします。1秒分のサンプルを取得するとサンプリングレートと同じ数になります。period;ただ長い時間のサンプルを取るとインデックスの値もどんどん増えていきます。この二番目の処理は周期で割ったあまりをインデックスに設定し直しています。周期は常に繰り返すので1周期のどこに位置すれば良いかが分かれば処理はできます。この結果インデックスは常に0以上、1周期未満の数になります。周期上の位置によって出力する音量を決めるインデックスを元に自分のいる場所を求めます。矩形波は周期の前半であれば最大出力、後半であれば最小出力です。1周期を1とすると0.5より大きいか小さいかを判定します。(long)-volume;}InputStreamの仕様に沿った値を返すInputStreamのreadメソッドを実装するにあたって戻す値を考慮します。IOExceptionもどす値はintですが実際にはbyteの値の範囲内にしなくてはいけません。Javaのbyteは符号があるものなので-128〜127までの値になるのですがこちらのreadメソッドの結果は0〜255の値を返すことになっています。このため通常のbyte値のうち-128〜-1までの値は256を足す必要があります。Byteクラスのstaticメソッドにはこの変換をしてくれるものがあるので利用します。ret;サンプルデータをバッファする一つのサンプルを取得した場合サンプルサイズによって取得できるデータ量が異なります。使う16bitのサンプルデータの場合は8bitが1バイトですから2バイトのサイズになります。上記のreadメソッドが2回呼ばれないとサンプルデータは読めない事になります。このため一度取得したデータをバッファしておきます。ここではArrayListを使っていますが他の方法でも良いと思います。ArrayList<>();long値でサンプルした値をバイトに変換してバッファするには以下のようにします。long値は8バイトのデータ量なのでこれが入りきるバッファを用意します。そこにlong値を入れます。いえ実際に入るデータはサンプルサイズを超えないので下の方の位だけ取得します。16bit2バイトのサンプルサイズの場合は下二桁を取得するようにします。list.add(array[i]);}バッファしたサンプルデータをreadメソッドが呼ばれるごとにint型に変換します。removeメソッドはその値をバッファから消して返します。Byte.toUnsignedInt(list.remove(0));バッファがなくなった場合にサンプルを取ります。if(list.isEmpty()){呼び出し処理を書くこれでおよそ処理内容は書けました。次は実際に呼び出してファイルを作るところです。File("/Users/myaccount/mywork/square_440.wav"));}SampleSquareのコンストラクタは二つの引数を取っています。一つ目は周波数、二つ目はサンプルの秒数です。ここでは440Hzの矩形波を3秒作る事にしています。次にAudioSystem.writeのメソッドを呼んで必要な引数を設定すればファイルが書き出されます。最初の引数はAudioInputStreamです。これにはInputStreamを実装した今回のクラスSampleSquareのインスタンスとオーディオフォーマットとサンプル数を引数に設定します。オーディオフォーマットとサンプル数は計算して設定するようにメソッドを作りました。big_endian);}今回の基本設定は以下のようになっています。1;あとはファイルのフォーマットをWAVに指定して書き出し先のファイルを指定すれば出来上がりです。前回作った文字列から文字を切り出すプログラムの文字を変更してみました。「だるまさんがころんだ」のかわり...記事を読むJavaとMIDI:音階と音階についてMIDIで楽曲を演奏するにあたって今までは全ての音をノート番号で指定していました。前回boolean変数によってif文を作りました。ここでは変数ではなく判定による真偽を使って分岐するようにします。ifによる分岐と真...記事を読むJavaによる録音:外部の音を録音する(2)クラスの定義ができあがりましたのでメインの処理を書きます。今回定義したクラスのインスタンスを作ります。...記事を読むバッファ処理の見直し今まで作ったソースを実行するとバッファ処理に時間がかかっていました。修正することによって早くなるようでしたら修正したいと思います。その前に検...記事を読むテキストファイルへの書き出し前回ファイルからの読み込みをしました。今度は書き出しをします。書き出しはPrintStreamというクラスを使います。このクラスは標準出力と...記事を読むテンポと拍子から時間を計算する前回は小節と拍から演奏する音符の位置を拍の単位で取得することができました。今度はその拍を元に開始からの時間を求めるようにします。楽曲にはテン...記事を読む音の高さを変える(1)今まではずっと同じ周波数の音でしたが今度は高さを変えたいと思います。今回は3秒間のサイン波のwavファイルを作ります。最初は440Hzで2秒...記事を読むクラスにメソッドを定義する前回に続きクラスにメソッドを追加します。その前にざっと使う用語を振り返っておきます。コメントをキャンセルメールアドレスが公開されることはありません。*サイト次回のコメントで使用するためブラウザーに自分の名前、メールアドレス、サイトを保存する。コメントデータの処理方法の詳細はこちらをご覧ください。外国語としてのJavaと音楽%d人のブロガーが「いいね」をつけました。