やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

ScaleKeyクラスを作った

音階の調を表すクラス。

成果物

GitHubPython.MusicTheory.ScaleKey.201709230939

前回まで

今回

音階と音度から音名を得たい。しかし、やってみると厄介なことになってきた。ポイントは以下2点。

  • C#Dbの区別はピッチクラスではつけられない(音名を得たいなら区別が必要)
  • 異なるクラス間の通知ができない(Observerパターンが必要)

作りながら気づいた経緯を列挙する。

  • 音階と音度から音名を得たい
    • 調の指定はピッチクラスだと不足。音名で指定すべき
      • 第一音の音名が特定できないから
        • C#Dbの場合、それぞれCDの音名を使いたい
          • C#,Dbは両者ともピッチクラス1になる。1ではC,Dどちらを使うべきか判断できない
      • ScaleKeyクラス作成が必要
        • 調はピッチクラスでなく、音名で指定するようにする
    • ScaleクラスからScaleKeyを参照する
      • ScaleKeyから調を設定する
        • Scale側でScaleKeyの変更を検知できない
          • Scaleの構成音再計算ができない
            • Observerパターンの実装が必要

肝心なことは以下。上記に気づく過程でクラスを作ったり壊したりしていたので一向に実装までたどりつけなかった。

音階と音度から音名を取得する

C#Dbかを選出するアルゴリズム

  • できるだけ各音度ごとにC,D,E,F,G,A,B個別の音名を割り振る
    • その音に変化記号#bどちらを割り振れば構成音になるか判断する
  • 調が幹音でない(C#など変化記号がある)場合、変化記号をとった音名を基準として上記のように処理する(どこかで必ず音名が被る)
s = Scale(9, ScaleIntervals.Minor)
self.assertEqual(9, s.Key)
self.assertEqual(ScaleIntervals.Minor, s.Intervals)
self.assertEqual([(9,0),(11,0),(0,1),(2,1),(4,1),(5,1),(7,1)], s.PitchClasses)

戻り値は(ピッチクラス, 相対オクターブ)である。

テストコード 項目数
TestScale.py 9

テスト計160項目。

所感

ピッチクラスと絶対オクターブが決まれば、周波数が算出できる。今回、相対オクターブを付与したおかげで、どの音からオクターブ上げる必要があるか算出する必要がなくなる。後々楽になるはず。

ピッチクラスなら問題なく一意に特定できる。しかし、音名は違う。C#Dbのどちらにすべきかの処理が面倒。次回、やってみる。