簡易な水平スペーシングの実装 前編

この記事は 楽譜組版 Advent Calendar 2023 の13日目の記事です。

概要

自動的な楽譜組版を実現する中で主要となるテーマには様々なものがあります。最低限の情報を含む楽曲ファイル(例えば MIDI ファイルなど)が入力として与えられた際に、例えば

  • 音符や休符の水平方向のレイアウト
  • 連桁(複数の音符の符尾を太い線で結合したもの)の傾き
  • 臨時記号のレイアウト
  • スラーの形状、レイアウト

などを自動的に決定するにはどのように実装すればよいかについては、一定の興味の対象となるでしょう。

今回は、これらの中から水平スペーシングについて取り上げます。この記事で水平音符スペーシングについて軽く述べ、次回の記事で実際に静的サイト上で表示できる簡易的な自動水平音符スペーシングの実装手法を紹介しようと思います。

水平音符スペーシング

同じ組段の同じ声部において、臨時記号などを含まない純粋な音符を水平方向にレイアウトすることを考えます。この際、最低限守られるべきルールは次の2つです。

  • 等しい音価をもつ音符が占めるスペースは、互いに等しい。
  • 長い音価をもつ音符が占めるスペースは、短い音価をもつ音符の占めるスペースより長い。

1つ目のルールは分かりやすいですが、2つ目のルールは曖昧です。一体どのくらいスペースが長いのでしょう?ここで何となく、スペースの長さは音価に比例しているのでは?と思われるかもしれませんが、それは次のような譜例を考えると正しくなさそうです。

同じ組段内の音価で大きな差が見られる譜例

もしスペースの長さと音価が比例していれば、2分音符は16分音符の8倍の音価を持つのでスペースも8倍になっているはずですが、明らかにそうはなっていません。この譜例に限らず、大抵の楽譜においてもこのようになっているはずです。

実際には、このようなレイアウトは対数を用いたスペーシングに概ね従っています。具体的に高校数学レベルで記述を行うとすると、音価 a\,(> 0) の音符が占めるスペースの長さ s_a と音価 b\,(> 0) の音符が占めるスペースの長さ s_b の比は、スペーシング比率 r\;(1\leq r\leq 2) を用いて次のように表されます*1

\dfrac{\,s_a\,}{\,s_b\,} = r^{\log_2\frac{a}{b}} {\left(= \dfrac{\,r^{\log_2a}\,}{\,r^{\log_2b}\,}\right)}

特に r = 1 のときは s_a = s_b、すなわち音価の違いに関わらずすべての音符のスペースが等しくなります。r = 2 のときは \dfrac{\,s_a\,}{\,s_b\,} = \dfrac{\,a\,}{\,b\,} となって、先程述べたような比例関係になります。このスペーシング比率 r12 の真ん中辺りによしなに設定することで、適切に水平音符スペーシングを決定することができます。

実際に MuseScore という楽譜組版ソフトウェアでは大体同じような処理が実装されていそうなことが、コードを見ると何となくわかります。

ユーザーは、次のウィンドウに示すように、この比率を自由に設定することができます*2。デフォルトでは r = 1.5 に設定されているようです。

Format > Style > Measure > Spacing ratio

これら2つのルールさえあれば、純粋な音符だけの水平スペーシングのアルゴリズムはすぐに実装できそうです。でも例えば、多声部だったり、音符に臨時記号がついていたりした場合であればどうでしょうか?次回はこの辺りに切り込みつつ実装を書いていこうと思います。

なお、水平音符スペーシングの考え方については HashibosoP さんによる2021年のブログシリーズ「水平スペーシングの考え方の全て」が詳しいですので是非読んでみてください。

最後に

いかがでしたか?次回(未定)はもう少し濃厚な感じの実装記事を書く予定です。短い記事ですみません!

*1:ここで音価は、全音符の音価は 1 で、2^{n}\,(n=1,\,2,\,\dots) 分音符の音価は \dfrac{\,1\,}{\,2^{n}\,} で、付点 2^{n} 分音符の音価は \dfrac{\,1\,}{\,2^{n}\,}+\dfrac{\,1\,}{\,2^{n+1}\,} で、…といったふうに記述されるものとします。

*2:古いバージョンだと 1.6 でハードコードされていたような気がします。気のせいかも。