次のブログをちらっと見てて、ドレミとかちょっと面白いなと思ったので、PowerShell を使用してコマンドラインでドレミ音を鳴らす方法をやってみました。
ビープをどうやって鳴らすの?
.NETのSystem.Console.Beep()を利用します。
Console.Beep メソッド (Int32, Int32)
PowerShellでStatic Methodを呼び出すには次のようにします。
[console]::Beep(int32 frequency, int32 duration)
frequency型 : System.Int32ビープ音の周波数。37 Hzから32767 Hzの範囲で指定duration型 : System.Int32ビープ音の再生時間。ミリ秒単位で指定
音価を定義
一々音価を書いていられませんので、先に定義してしまいます。 こうすることで、曲のテンポも簡単に調整できます。
#notes $whole = 800 #全音符 $half = $whole / 2 #2分音符 $fter = $whole / 4 #4分音符 $qver = $whole / 8 #8分音符 $haft = $half + $fter #付点付2分音符 $ftqv = $fter + $qver #付点付4分音符
休符はどうする
PowerShellならStart-Sleepがあるので休符に利用します。 .Beep()同様に、ミリ秒で指定も出来るので連動可能です。
-mパラメータを使用してミリ秒で指定できます。Script Blockで定義しておきます。
#rest $fterrest = {sleep -m $fter} #4分休符 $qverrest = {sleep -m $qver} #8分休符
実行するときは"." か "&" を頭につけます。
. $fterrest
キーを定義
キーは周波数で定まります。 440Hz (A4)を基準音といったん決めましょう。最近は440Hzが基準音とは限らないのでご自由にどうぞ。 A3からC5までの周波数を求めます。
3..17 | %{ [int]( [Math]::Pow( 2, $_ / 12.0 ) * 220.0 ) }
int型で算出された周波数をキーに当てはめます。
#keys $do = 262 $dos = 277 $re = 294 $res = 311 $mi = 330 $fa = 349 $fas = 370 $so = 392 $sos = 415 $la = 440 $sif = 466 $si = 494 $doO = 523 $doOs = 554 $reO = 587
ちなみにこんなサイトもありました。
楽譜はどこ
耳コピでも、記憶の通りでもいいです。楽譜を使うのもいいでしょう。
どうやって音をBeep()に渡す
foreachで渡すのはメンテしにくくなります。
foreach($v in @(262,294,330,349,392,440,494,523)){[Console]::beep($v,200)}
ForEach-Objectで渡すと少しは扱いやすくなります。
(262,294,330,349,392,440,494,523) | % {[Console]::beep($_,200)}
変数にセットした、音符と音価を一緒に渡すので2次元配列で書けます。 ※ドレミの初めの2小節
(($do,$ftqv),($re,$qver),($mi,$ftqv),($do,$qver),($mi,$fter),($do,$fter),($mi,$half)) | % {[console]::Beep($_[0],$_[1])}
Get-BeepをFilter化
毎回| % {[console]::Beep($_[0],$_[1])}と書くのはつらいのでfilterにします。 ※filterはForeach-Objectが、実際に行っている中身だと思えばイメージしやすいです。
filter Get-Beep { param( [Parameter(ValueFromPipeline=$true)] [int[]]$keyNote ) [console]::Beep($keyNote[0],$keyNote[1]) }
Beep()に渡す記述がすっきりします。
(($do,$ftqv),($re,$qver),($mi,$ftqv),($do,$qver),($mi,$fter),($do,$fter),($mi,$half)) | Get-Beep
Doremiの歌もFunction化して実行
あとは楽譜通りに入力するだけです。
#notes $whole = 800 #全音符 $half = $whole / 2 #2分音符 $fter = $whole / 4 #4分音符 $qver = $whole / 8 #8分音符 $haft = $half + $fter #付点付2分音符 $ftqv = $fter + $qver #付点付4分音符 #rest $fterrest = {sleep -m $fter} #4分休符 $qverrest = {sleep -m $qver} #8分休符 #keys $do = 262 $dos = 277 $re = 294 $res = 311 $mi = 330 $fa = 349 $fas = 370 $so = 392 $sos = 415 $la = 440 $sif = 466 $si = 494 $doO = 523 $doOs = 554 $reO = 587 filter Get-Beep { param( [Parameter(ValueFromPipeline=$true)] [int[]]$keyNote ) [console]::Beep($keyNote[0],$keyNote[1]) } function doremi-song { param( ) begin{ } process{ 1..2 | %{ (($do,$ftqv),($re,$qver),($mi,$ftqv),($do,$qver),($mi,$fter),($do,$fter),($mi,$half)) | Get-Beep (($re,$ftqv),($mi,$qver),($fa,$qver),($fa,$qver),($mi,$qver),($re,$qver),($fa,$whole)) | Get-Beep . $fterrest (($mi,$ftqv),($fa,$qver),($so,$ftqv),($mi,$qver),($so,$fter),($mi,$fter),($so,$half)) | Get-Beep (($fa,$ftqv),($so,$qver),($la,$qver),($la,$qver),($so,$qver),($fa,$qver),($la,$whole)) | Get-Beep . $fterrest (($so,$ftqv),($do,$qver),($re,$qver),($mi,$qver),($fa,$qver),($so,$qver),($la,$whole)) | Get-Beep . $fterrest (($la,$ftqv),($re,$qver),($mi,$qver),($fas,$qver),($so,$qver),($la,$qver),($si,$whole)) | Get-Beep . $fterrest (($si,$ftqv),($mi,$qver),($fas,$qver),($sos,$qver),($la,$qver),($si,$qver),($doO,$whole)) | Get-Beep (($si,$qver),($sif,$qver),($la,$fter),($fa,$fter),($si,$fter),($so,$fter),($doO,$haft)) | Get-Beep . $fterrest } . $fterrest (($do,$fter),($re,$fter),($mi,$fter)) | Get-Beep (($fa,$fter),($so,$fter),($la,$fter),($si,$fter),($doO,$fter),($doO,$fter),($si,$fter),($la,$fter)) | Get-Beep (($so,$fter),($fa,$fter),($mi,$fter),($re,$fter),($do,$fter),($mi,$fter),($mi,$half)) | Get-Beep (($mi,$fter),($so,$fter),($so,$half),($re,$fter),($fa,$fter),($fa,$half)) | Get-Beep (($la,$fter),($si,$fter),($si,$half),($do,$qver),($mi,$qver),($mi,$fter)) | Get-Beep . $qverrest (($mi,$qver),($so,$qver),($so,$fter)) | Get-Beep . $qverrest (($re,$qver),($fa,$qver),($fa,$fter)) | Get-Beep . $qverrest (($la,$qver),($si,$qver),($si,$fter)) | Get-Beep . $qverrest (($so,$half),($do,$half)) | Get-Beep (($la,$half),($fa,$half),($mi,$half),($do,$half),($re,$whole)) | Get-Beep (($so,$half),($do,$half),($la,$half),($si,$half),($doO,$half),($reO,$half),($doO,$whole)) | Get-Beep } end{ } } doremi-song
まとめ
いい利用例ですね。
次回は、PowerShellでMMLにてドレミの歌を演奏してみます。