PowerShellで曲の長さを計算する関数を書いてみた
追記 2015.05.18
追記というより補足、というか書き忘れただけなのですが、この関数はPashではいまのところSyntax errorになります。どうもパラメータのところの対応が完全ではなさそうです。もしかしたらすでに対処済みのバージョンが出ているかもしれません。
動機
先日はコメントベースのヘルプについて調べてが、パラメータがどうしても表示されなかったので深堀してみました。ついでに、パラメータについても指定の仕方を調べてみることにしました。
題材
タイトルの通りですが、むかしシーケンサー(YAMAHA QY300)で打ち込みしてた頃によくやってた「BPMと小節数からおおよその曲の長さを計算する」というのを関数にしてみたいと思います。いつもは電卓叩いて計算してたのですが、せっかくIT業界にいたのにExcelでするないとかありえへんと言われそうなので。
パラメータの指定
PowerShellでは関数の定義のときに、いろんな定義の仕方があるようです。たとえば、C#とかJavaScriptみたいに関数名に並べて記述する方法です。
function Get-Something($first, $second){ # something todo. }
よくあるやつですね。わたしはずっとこれで書いてました。。。 でも、ほかにも方法があります。まずは型を指定するパターン。
function Get-Something([int]$first, [string]$second){ # something todo. }
はいはい、ですね。このパターンは時々やってました。でも、Githubとかで見かけるやつはほかにもあります。たとえば、関数名に並べずに記述しているパターン。
function Get-Something { param($first, $second) # something todo. }
paramって記述してやるパターンですね。これもよくよく考えると使ったことがありますが、意図して書いたことなかったかもしれません…恥ずかしながら。 そして、さらにパラメータの必須を指定する方法もあります。
function Get-Something { param( [Parameter(Mandatory=$True)] $first, $second ) # something todo. }
この記述で、上記の例では$first変数は必須扱いです。指定がないとプロンプトからは値を要求されます。 さらに型を指定すると次のようになります。
function Get-Something { param( [Parameter(Mandatory=$True)] [int]$first, [string]$second ) # something todo. }
初期値も与えておくことのできるスクリプト言語はいろいろありますが、PowerShellでもいけるようです。
function Get-Something { param( [Parameter(Mandatory=$True)] [int]$first=12, [string]$second="hello" ) # something todo. }
ここまでくると、パラメータ自体に多少なりとも設定のようなことができたかと思います。これで先日のようにコメントベースのヘルプを書いてGet-Helpしてみますと、パラメータの説明が表示されるようになります。 なんだ、そういうことだったのかーと一人納得しました。
そういうことでまとめです。
まとめ
BPM(Beat Per Minutes)と小節数から計算するには、次のような計算をします。
60 / BPM × 4 × 小節数
これで4拍子の曲について長さが何秒なのか計算されます。60を分子に持ってきているのは、BPMの意味が「1分間に何拍なのか」なので、1分=60秒ということでそうしています。また、4をかけているのは60 / BPMで1拍あたりの秒数が計算され、4拍子で1小節だからです。ここまでで1小節あたりの長さが計算されます。
あとはこれを60で割った商が分、残りが秒数になります。
これを関数にしてGistに置いておきました。ご参考まで。
一応ここにも貼っておきます。finally句の中身が空なのは手抜きです…
<# .SYNOPSIS トラックの速さ(BPM)と小節数からトラックの長さを計算します。 .DESCRIPTION トラックの速さ(BPM)と小節数からトラックの長さを計算します。 速さ、小節数は正の整数で指定します。 .EXAMPLE Get-TrackLength -bpm 120 -bar 8 .INPUTS [System.UInt32] .OUTPUTS [System.String] #> function Get-TrackLength { param( [Parameter(Mandatory=$true)] [uint32]$bpm, [Parameter(Mandatory=$true)] [uint32]$bar ) begin { try { $sec = 60 / $bpm * 4 * $bar } catch [Exception] { "例外が発生しました。" throw } finally { } } process { $min = [math]::truncate($sec / 60) $psec = [math]::round($sec - ($min * 60), 0) } end { return "{0}min {1}sec" -f $min, $psec } }
使い方は以下のとおりです。
Get-TrackLength -bpm 120 -bar 8
ヘルプを見るには以下のとおりです。
Get-Help Get-TrackLength -full
今回はこのあたりで。














