前回に引き続き、“The Psychophysics of Harmony Perception: Harmony is a Three-Tone Phenomenon” より和音の心理数理モデルのPython実装を行います。
今回は、和音の緊張度を分析する数理モデルを扱います。
用途としては、減3和音や増3和音のような緊張感のある和音・ヴォイシングを分析・検出したり、コード進行を分析するのに利用できる可能性があります。
和音の緊張度
参考文献では、和音の緊張度を音程の等しさに基づいて算出しています。
緊張度の高い和音としては、減3和音や増3和音などが知られています。
この3和音の低い音高(Low tone)と真ん中の音高 (Middle tone) の周波数差を第1音程、また、真ん中の音高と高い音高 (High tone) の周波数差を第2音程とすると、第1音程と第2音程が等しいという特徴があります。
この第1,2音程が等しいことが和音の緊張感を生み、和音進行で未解決的な響きとして知覚されると仮定されています。
このような特徴を利用し、参考文献では3つ音高の各周波数から第1,2音程を算出して緊張度を導出するモデルを提案しています。
3つの純音における緊張度の算出
不協和度と同様に、まずは倍音のない純音を考えます。
純音の場合、以下の数式から緊張度を求めることができます*1
x12, x23がそれぞれ第1,2音程であり、不協和度の時と同様に周波数比の対数を取ることで音程を線形な軸で扱います。
すなわち、x12=1であれば第1音程は半音(例えば、CとC#の音程)になります。
なお、γはt123の値の大きさを調整する係数であり、論文ではγ=0.6となっています。
以上をクラスとしてPythonで実装したのが以下になります。
注意点として、f1, f2, f3 は f1≦f2≦f3 であることが要求されます
class Tension(): def __init__( self, n_semitone=12, gamma=0.6, p=0.88 ): self.n_semitone = n_semitone self.gamma = gamma self.p = p def calc_velocity(self, v1, v2, v3): return v1 * v2 * v3 def calc_pitch_distance(self, f1, f2): return np.abs(self.n_semitone * np.log2(f2/f1)) def calc_puretones(self, f1, f2, f3, v1, v2, v3): x12 = self.calc_pitch_distance(f1, f2) x23 = self.calc_pitch_distance(f2, f3) v123 = self.calc_velocity(v1, v2, v3) np.set_printoptions(suppress=True, precision=4) t = v123 * np.exp( -( (x23-x12)/self.gamma )**2 ) return t
このコードを使い、3音の内の2音の音高を変えてプロットしました。
下図は音高がちょうど12平均律の各半音の時の値だけプロットしています。
f2とf3の入れ替えた結果は等しいため、対称的な形状となっています。
少し分かりにくいですが、第1,2音程に注目すると、目的としてた第1,2音程が等しい3和音では大きな値となっていることが確認できます。
倍音を考慮した緊張度の算出
次に、倍音を考慮した緊張度 T の算出を行います。
基本的には不協和度の算出と同じ、3つの音の周波数比をN倍音まで全パターン足すことで算出します。
注意点としては、各緊張度 t を算出する際に渡す3つの音高はソートしてから渡す必要があります
Python実装は、先ほどのTensionクラスにメソッドを追加しました。
# class Tension(): def calc(self, f1, f2, f3, v1=1.0, v2=1.0, v3=1.0, n_overtones=2): T = 0.0 f, v = np.zeros(3), np.zeros(3) for k in range(1, n_overtones+1): for m in range(1, n_overtones+1): for n in range(1, n_overtones+1): f[:] = f1 * k, f2 * m, f3 * n v[:] = v1*(self.p**(k-1)), v2*(self.p**(m-1)), v3*(self.p**(n-1)) args = np.argsort(f) f[:], v[:] = f[args], v[args] T += self.calc_puretones(f[0], f[1], f[2], v[0], v[1], v[2]) return T / n_overtones def surface(self, f_lower, f_centers, f_uppers, v1=1.0, v2=1.0, v3=1.0, n_overtones=2): # f_centers, f_uppers は複数の音高を格納したnumpy配列 T_mx = np.zeros((f_centers.shape[0], f_uppers.shape[0])) for k, fc in enumerate(f_centers): for m, fu in enumerate(f_uppers): T_mx[k,m] = self.calc(f_lower, fc, fu, v1, v2, v3) return T_mx
なお、このコードはナイーブな実装のため3重ループが出てきており計算速度は遅いです。
高速化のためには、例えば Numba などを使って実装するのがよいと思われます。
以下が計算する倍音数の上限値 n_orvertones
を変えたときの結果です。
先ほどの純音の場合(すなわちn_orvertones==1
)だと第1,2音程が等しい場合以外はほぼ値を持たない結果となっていましたが、計算する倍音数を大きくすると倍音の影響で第1,2音程が異なっていても緊張度の値が大きくなる3和音が出てきます。
また、傾向として増三和音で緊張度が大きな値を取るようです。
■2倍音まで計算
■3倍音まで計算
■4倍音まで計算
■6倍音まで計算
プロット用のコード
まとめ
和音の緊張度を算出する緊張度曲線 (Tension Curve) のPython実装を行いました。
和音の特性を音高や音程に対して連続的に算出できるので、よく知られた和音の分析だけでなく微分音の活用などを探るのによいかもしれません。
ただし、綺麗な数理モデルに基づいているとはいえ、あくまでも数理モデルであり実際に知覚される緊張度とは乖離があることに注意が必要です。
参考文献
- Fujisawa, Takashi. (2006). The Psychophysics of Harmony Perception: Harmony is a Three-Tone Phenomenon. Empirical Musicology Review. 1. 10.18061/1811/24080.
- 藤沢隆史, ノーマン D. クック, "和音性の計算法と曲線の描き方 : 不協和度・緊張 度・モダリティ",2006.