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'
出力例:
- shepardscale.wav(ループで再生してください)
参考: