シェパード音階を Squeak の Smalltalk で


rubyco(るびこ)の日記 - Rubyで作る無限音階 経由で、PB memo - [Ruby][音楽]Shepard Tone に、触発されて。マルチメディアなら Squeak!ということでもないのですが(むしろ、マルチメディアはおろか、サウンド関係すらほとんど遊んだことがない…汗)、まあ、勉強だと思って無限音階にチャレンジしてみました。


まず、準備段階として、釣り鐘状に強さが変化する(低音、高音では弱い)7オクターブの音階をこしらえて鳴らしてみます。

| scales |

scales := (1 to: 7) collect: [:octv |
   #(c d e f g a b) collectWithIndex: [:note :idx |
      | dur loud |
      dur := 0.5.
      loud := 500 * (octv - 1 * 8 + idx / 56 - 1 raisedTo: 2).
      {AbstractSound pitchForName: note, octv asString. dur. loud}]].

(AbstractSound noteSequenceOn: FMSound default from: scales concatenation) play


loud の計算は適当です。すでに低い音は小さいので、高い音の強さを押さえる適当な関数を当てはめました。あとは、オクターブ違いの音をそれぞれ和音にして順番に鳴らせば、無限音階…になるはず(自信なし)。

| seq |

seq := SequentialSound new.

#(c d e f g a b) doWithIndex: [:note :idx |
   | mix |
   mix := MixedSound new.
   (1 to: 7) do: [:octv |
      | pitch dur loud |
      pitch := AbstractSound pitchForName: note, octv printString.
      dur := 0.5.
      loud := 0.5 * (octv - 1 * 8 + idx / 56 - 1 raisedTo: 2).
      mix add: (FMSound default soundForPitch: pitch dur: dur loudness: loud)].
   seq add: mix; add: (RestSound dur: 0.5)].

(RepeatingSound repeat: seq count: 5) play


うーむ。微妙…。なめらかに昇ってゆかせるには、もう少し個々の音の強さの調整が必要かもしれません。あと、使用するマシンによってきちんと鳴らすことができる音の範囲や、聞こえ方が異なりますので環境に合わせてオクターブの範囲を狭めるなどの修正(同時に loud のパラメータか算出方法の変更)が必要です。あしからず。


なお、お手元のマシンや音声出力環境が、その高さの音階を、途中で極端に音を外さずに(あるいは、急に音の強さを弱めたりせずに)、ある程度、期待通り鳴らすことができるかどうかは、次のようなスクリプトで確認できます(#c の後の数字が音の高さです)。

(FMSound majorScaleOn: FMSound default from: #c6) play


ファイルに出力したい場合は、最後の行を出力用の式に変更します。

| seq |

seq := SequentialSound new.

#(c d e f g a b) doWithIndex: [:note :idx |
   | mix |
   mix := MixedSound new.
   (1 to: 7) do: [:octv |
      | pitch dur loud |
      pitch := AbstractSound pitchForName: note, octv printString.
      dur := 0.5.
      loud := 0.5 * (octv - 1 * 8 + idx / 56 - 1 raisedTo: 2).
      mix add: (FMSound brass2 soundForPitch: pitch dur: dur loudness: loud)].
   seq add: mix; add: (RestSound dur: 0.5)].

seq storeWAVOnFileNamed: 'shepardscale.wav'

出力例:


参考: