数式での翻訳 |
---|
幹音と変化記号の文字列としての結合で与えられる文字列を、幹音と変化記号の組と同一視します。幹音と変化記号の組全体の集合 \[ \textrm{OnMei} = \textrm{KanOn} \times \textrm{HenKaKiGou} \] に属する文字列を音名と呼びます。特に変化記号成分が空文字列\(\textrm{□}\)である音名は文字列として幹音と一致しますので、文字列の結合と組の同一視の下で任意の幹音は音名です。数学ではよく同一視という言葉が多義的に用いられますが、ここでの文脈における同一視をより厳密に表現すると、単射な写像 \[ \begin{align} \textrm{KanOnToOnMei} \colon \textrm{KanOn} & \hookrightarrow \textrm{OnMei} \\
N & \mapsto (N,\textrm{□}) \end{align} \] を略して表記する、ということです。具体的には、「文字列の結合と組の同一視の下で任意の幹音は音名である」という主張は「任意の幹音\(N\)に対し『\(\textrm{KanOnToOnMei}\)による\(N\)の像を\(N\)と略記すると』\(N\)は音名である」ということで、命題における略記のメタな明示である『』部分を解消するとこの主張は「任意の幹音\(N\)に対し\(\textrm{KanOnToOnMei}\)による\(N\)の像は音名である」という主張になります。このように命題の略記のメタな明示やそれに基づく同一視は数学において曖昧さが致命的でない範囲で断りなく多用されるものですので、今後も断りなく使っていきます。また\(\textrm{KanOnToOnMei}\)は再帰的かつ像が\(\textrm{OnMei}\)の再帰的部分集合となるので、このような同一視は何らかの意味で実装をすることも可能です。実際、今回は\(\textrm{KanOnToOnMei}\)に対応するコンストラクタを適切に定義することで幹音から音名への暗黙なキャストを可能にし、また音名が幹音か否か(つまり変化記号成分が空文字列か否か)の判定も変化記号に対応するメンバ変数への参照返しを行うメンバ関数を実装することで可能にします。
第\(1\)射影と第\(2\)射影 \[ \begin{align} \textrm{OnMei} & \to \textrm{KanOn} \\
\textrm{OnMei} & \to \textrm{HenKaKiGou} \end{align} \] をそれぞれ\(\textrm{GetKanOn}\)と\(\textrm{GetHenKaKiGou}\)と置きます。
\(\textrm{PitchClass} = \mathbb{Z}/12 \mathbb{Z}\)と置き、\(\textrm{PitchClass}\)の元をピッチクラスと呼びます。また写像 \[ \begin{align} \textrm{GetPitchClass} \colon \textrm{OnMei} & \to \textrm{PitchClass} \\
N & \mapsto \textrm{GetPitchClass}(N) \end{align} \] を以下のように定めます:
- \(N_0 = \textrm{GetKanOn}(N)\)と置き、\(S_0 = \textrm{GetHenKaKiGou}(N)\)と置く。
- \(N_0 = \textrm{Do}\)ならば、\(\textrm{GetPitchClass}(N) = 0 + \textrm{GetNum}(S_0)\)である。
- \(N_0 = \textrm{Re}\)ならば、\(\textrm{GetPitchClass}(N) = 2 + \textrm{GetNum}(S_0)\)である。
- \(N_0 = \textrm{Mi}\)ならば、\(\textrm{GetPitchClass}(N) = 4 + \textrm{GetNum}(S_0)\)である。
- \(N_0 = \textrm{Fa}\)ならば、\(\textrm{GetPitchClass}(N) = 5 + \textrm{GetNum}(S_0)\)である。
- \(N_0 = \textrm{So}\)ならば、\(\textrm{GetPitchClass}(N) = 7 + \textrm{GetNum}(S_0)\)である。
- \(N_0 = \textrm{La}\)ならば、\(\textrm{GetPitchClass}(N) = 9 + \textrm{GetNum}(S_0)\)である。
- \(N_0 = \textrm{Ti}\)ならば、\(\textrm{GetPitchClass}(N) = 11 + \textrm{GetNum}(S_0)\)である。
ただし定義中の\(\textrm{GetNum}(S_0)\)は変化記号の記事においてオーバーロードした写像\(\textrm{HenKaKiGou} \to \mathbb{Z}\)に\(S_0\)を代入したものであることに注意しましょう。この写像\(\textrm{GetPitchClass} \colon \textrm{OnMei} \to \textrm{PitchClass}\)は全射ですが、単射ではありません。\(\textrm{GetPitchClass}\)での像が等しい相異なる音名を(平均律における)異名同音と呼びます。
また\(\textrm{KanOnToOnMei}\)と\(\textrm{GetPitchClass}\)の合成写像 \[ \begin{align} \textrm{KanOn} & \to \textrm{PitchClass} \\
N & \mapsto \textrm{GetPitchClass}(\textrm{KanOnToOnMei}(N)) \end{align} \] を\(\textrm{KanOnToPitchClass}\)と呼びます。
C++での宣言 |
---|
音名のクラスおよび関係する関数たちを以下のように宣言します。
using PitchClass = Mod<12>;
class OnMei
{
private:
KanOn m_N;
HenKaKiGou m_S;
PitchClass m_pc;
public:
inline OnMei( const KanOn& N ) noexcept;
inline OnMei( const KanOn& N , const HenKaKiGou& S ) noexcept;
OnMei& operator++() noexcept;
OnMei& operator--() noexcept;
inline string Display() const noexcept;
inline const KanOn& GetKanOn() const noexcept;
inline const HenKaKiGou& GetHenKaKiGou() const noexcept;
inline const PitchClass& GetPitchClass() const noexcept;
static PitchClass KanOnToPitchClass( const KanOn& N ) noexcept;
};
inline bool operator==( const OnMei& N1 , const OnMei& N2 ) noexcept;
inline bool operator!=( const OnMei& N1 , const OnMei& N2 ) noexcept;
C++での定義 |
---|
実際の実装例についてはこちらをご覧下さい。実装においては以下の仕様を要請します。
inline OnMei::OnMei( const KanOn& N ) noexcept
は移譲コンストラクタOnMei( N , HenKaKiGou( 0 ) )
で定める。inline OnMei::OnMei( const KanOn& N , const HenKaKiGou& S ) noexcept
はメンバ初期化子リストm_N( N )
,m_S( S )
,m_num( KanOnToInt( N ) + S.GetNum() )
で定める。OnMei& OnMei::operator++() noexcept
とOnMei& OnMei::operator--() noexcept
はそれぞれ++m_S
と--m_S
を実行し、return *this
と定める。inline string OnMei::Display() const noexcept
はreturn m_N.Display() + m_S.Display()
と定める。inline const KanOn& OnMei::GetKanOn() const noexcept
はreturn m_N
と定める。inline const HenKaKiGou& OnMei::GetHenKaKiGou() const noexcept
はreturn m_S
と定める。inline const OnMei::PitchClass& GetPitchClass() const noexcept
はreturn m_pc
と定める。static PitchClass OnMei::KanOnToPitchClass( const KanOn& N ) noexcept
は引数Do()
~Ti()
に対してそれぞれconst int n
を0
,2
,4
,5
,7
,11
と定め、return PitchClass( n )
と定める。- クラス
OnMei
に対する等号演算子は自然なものである。