竹内関数で音楽生成を Squeak Smalltalk で


自動でアルペジオとか付かないので、リンク先の演奏よりは間延びしますがそれでもついつい聴き入ってしまいます。

tarai でブロックの再帰を使っていますので、Squeak4.1 以降でお試しください(例えば Squeak4.2-ja-all-in-one.zip をダウンロードして展開。各OS用起動スクリプトで起動後、ツール→ワークスペースにペースト→貼り付けたテキストを全選択してから alt/cmd + d すると演奏が始まります)。

このコードで出力される音だけ聴ければいいやという人はこちらを。→tarai.aiff

| pitches sound noteSeq tarai |
pitches := (FMSound majorPitchesFrom: #c4) first: 7.
pitches := pitches, (pitches * 2).
pitches := pitches flipRotated: 3*2.

sound := [:n |
   FMSound default
      soundForPitch: (pitches atWrap: n) dur: 1.84 loudness: 0.3].

noteSeq := SequentialSound new.
tarai := nil.
tarai := [:x :y :z |
   noteSeq add: (sound value: x)+(sound value: y)+(sound value: z).
   noteSeq sounds size >= 60 ifTrue: [
      noteSeq play.
      [noteSeq isPlaying] whileTrue.
      ^noteSeq storeAIFFOnFileNamed: 'tarai.aiff'].
   x <= y ifTrue: [y] ifFalse: [
      tarai
         value: (tarai value: x-1 value: y value: z)
         value: (tarai value: y-1 value: z value: x)
         value: (tarai value: z-1 value: x value: y)]].
tarai value: 10 value: 5 value: 0
▼簡単な解説

FMSound majorPitchesFrom: #c4 で指定したキーからドレミファ…の周波数列を生成。2オクターブ分をつくり結合(#,)し、最初(つまり低音の方の)のドレミだけ flipRotated: 3*2 で末尾に移動させています(#atWrap: を使用して -1 のときのレ、0 のときのミにアクセスできるように)。あとは taiai 関数(ブロック)内で sound ブロックをコールし、そのときの x y z おのおのの値からサウンドデータを生成させています。ちなみにサウンドは加算(#+)で和音にすることが可能です。60小節(?)たまったところでとりあえず再帰から抜けて演奏を開始。その後、演奏終了を待って tarai.aiff を出力します。全343073小節の出力が可能かどうかは試していません。w