音声音楽スポンサーリンク前回は小節と拍から演奏する音符の位置を拍の単位で取得することができました。今度はその拍を元に開始からの時間を求めるようにします。楽曲にはテンポの設定があるため同じ位置、同じ拍であってもテンポが違えば時間がことなります。拍子の設定と位置の取得ユースケースユースケースを考えます。最初0小節目からbpmが120、拍子を4/4で初めて2小節目で60に変更し、4小節目で拍子を3/4に変更するケースを考えます。小節の数え方を0ベースにすることは前回お話ししました。bpmが120ということは1分間に120の4分音符が演奏されることになるので一つの4分音符は0.5秒です。0小節目は0.5×4で2秒かかります。次の一小節目の開始時間はこのため2秒目となります。2小節目はbpmが60になり4分音符の長さが1秒になります。このため二小節目の長さは1×4で4秒になります。4小節目からはテンポは変わらないのですが拍子が代わり4分音符3つ分になるため1×3で3秒になります。設定は以下のようにできるようにします。最初のテンポはxとするx小節目のy拍目にテンポをzとするプログラムの方では以下のように情報を取得したいと思います。前回小節と拍から拍単位での開始位置を求めることができましたのでここでは通算でx拍目の開始時間はy秒ということがわかれば良いものとします。設定値のためのクラスを作ります。}}ここでtimeという変数を宣言していますがこれは後で使います。各テンポ情報が設定されている拍単位の位置が秒単位で開始後何秒であるかを記憶しておくためのものです。しておくとあとで再計算する必要がなくなります。このクラスを管理するマップクラスを作ります。{ここでの鍵は拍単位での位置になります。小節と拍から拍単位の位置を求めるには前回のTimeSignが必要ですが設定はそれが出来上がる前からおこないたいのでとりあえず配列に入れておきます。settings;コンストラクタは初期のテンポを指定させるようにします。initial));}設定はputメソッドを利用できるようにします。小節と拍とテンポを指定すると内部で配列に追加します。tempo));}TimeSignオブジェクトが確定したところで初めてテンポの設定をすることにします。メソッドは以下の通りです。自分自身を初期化するclearメソッドを実行します。clear();次に配列にある設定値とTimeSignオブジェクトを利用して拍単位の位置を求めそれを鍵としてテンポ情報を値として自分自身に設定していきます。鍵の値が同じ場合は後の値で上書きされます。tempo);}次に各テンポの設定位置を時間単位で計算します。以下のように初期設定をします。0;テンポ情報を順に見ていきその情報が始まるときの時間を計算して設定します。ある時間でbpmを60、その後のある時間で90に設定した場合その間はテンポはリニアに変わっていきます。中間では75になる計算です。nextBeat;}次に拍単位の位置が与えられたときに開始時間を返すメソッドを作ります。totalBeat){まず負の拍は処理中断します。totalBeat);}自分のいる拍の前後のテンポ情報を取得します。ceilingTempo;前の情報は必ず見つかりますが後の情報は設定されていない場合があります。ない場合は前の情報と同じテンポとします。get(ceilingKey);}前の位置と後の位置が同じ場合は前の情報のテンポを現在のテンポとします。それ以外の場合は前と後の情報から按分してテンポを計算します。floorKey);}最後に前の情報の位置とテンポ、現在の位置とテンポから前の位置から現在の位置までの時間を求めます。それに前の情報の開始時間を足せば現在の開始時間が求められます。作りが難しいのですがユースケース通りになるか確認します。mapで2小節のごく手前に120のbpmを指定しているのはここまで一律に120のテンポで演奏してもらうためです。これを指定しないと0小節目の初めから2小節目の初めまでテンポは120から60にスムーズに変動してしまうためです。0)));}実行します。2小節目以降に少し誤差が出ていますがおおよそ問題なくユースケース通りの時間にすることができました。0:0.01:2.02:4.0000000000016663:8.0000000000016664:12.0000000000016665:15.000000000001666ソース以下ソースです。}}次回は今までの実装をまとめて使えるようにします。waveは正弦波とも呼ばれますが音の波として一番シンプルなものとされています。stereo「堅い」「しっかり確立された」という意味の言葉に由来しています。複数のス...記事を読むJavaによる録音:利用できるもののまとめいろいろ音を出せるようになったので録音をしたいと思います。Javaでできる録音は入力の音源からデータを読み込んでファ...記事を読むJavaとMIDI:フォリア(2)次にフレーズを作っていきたいと思います。前の譜例では16小節そのまま書いてありましたが以下のように繰り返しを使ってコー...記事を読むSeleniumで翻訳機を作る(3)では今までのものを実装していきます。動かした様子の動画とソースコードを下に載せておきます。Seleniumがブラ...記事を読む楽器の音色を決める(1)前回では楽器のためのインタフェースを決めました。これを実装したクラスを作って音色のコントロールはこのクラスで行うようにします。楽器クラスが実...記事を読むJavaとMIDI:ハノンの練習曲第一番(1)ハノンの『60の練習曲によるヴィルトゥオーゾ・ピアニスト』はピアノの指の練習に使われます。機械的にスケールを上下する曲で構成されていますがこ...記事を読むパッヘルベルのカノンと通奏低音(2)平均律クラヴィーアBWV846プレリュードの最後の和音をアルペジオのように少しづつずらして各音を鳴らすことがありました。和音をならす処理が洗...記事を読むFM音源のストリングスにローパスフィルターをかける以前FM音源でストリングスを作りました。変調をかけたので高い倍音が増えすぎてしまっていましたがローパスフィルターでこれを抑えたいと...記事を読むFM音源を利用した楽器の作成ここまでに作ったFM音源とエンベロープ・ジェネレーターを使って楽器を作りたいと思います。コメントをキャンセルメールアドレスが公開されることはありません。*サイト次回のコメントで使用するためブラウザーに自分の名前、メールアドレス、サイトを保存する。コメントデータの処理方法の詳細はこちらをご覧ください。外国語としてのJavaと音楽%d人のブロガーが「いいね」をつけました。