非公式チュートリアル02 repeat-n, omloop
今回はrepeat-nとomloopの2つの使い方について述べる。
まずは前回と同じようにchordを作成する。mキーで中身を表示し、クラスの大きさを見やすいように整えておく。
左下をorderにすると編集しやすい。新規に音を追加する場合はcommand+クリックで行う。
編集し終わったら自動的にブロックされるが、ブロックされていない場合はbキーでブロックしておく。
編集し終わったら自動的にブロックされるが、ブロックされていない場合はbキーでブロックしておく。
まずfirstというファンクションについて解説する。これはその名の通り括弧で囲まれたリストの中の1番目の値を抽出するものである。OpenMusicの母体であるLISPは常に0からものを数えるのであるが、このオブジェクト名の場合はfirst, secondというように1から数える。同様のオブジェクトはtenthまで有効である。
先ほどのchordの左から2番目のアウトプットをこのfirstに繋ぎevaluateすると、最初の値が表示される。先ほどのorderで左から順番にド、ミ、ソと入力していれば、最初のドの音の値である6000がLISPウィンドウに現れる。
先ほどのchordの左から2番目のアウトプットをこのfirstに繋ぎevaluateすると、最初の値が表示される。先ほどのorderで左から順番にド、ミ、ソと入力していれば、最初のドの音の値である6000がLISPウィンドウに現れる。
今度はファンクションrepeat-nを作成しよう。repeat-nの左側のインプットに先ほどのchordの左から2番目のアウトプットの値を繋ぎ、repeat-nの右側のインプットはshift+クリックしてボックスを表示し、5と入力する。
ここで一旦evaluateしてみると、((6000 6400 6700)(6000 6400 6700)(6000 6400 6700)(6000 6400 6700)(6000 6400 6700))という値がLISPウィンドウに表示される。つまりここでは括弧で囲まれた数値のリスト(和音)が5回繰り返されたということになる。
ここで一旦evaluateしてみると、((6000 6400 6700)(6000 6400 6700)(6000 6400 6700)(6000 6400 6700)(6000 6400 6700))という値がLISPウィンドウに表示される。つまりここでは括弧で囲まれた数値のリスト(和音)が5回繰り返されたということになる。
このrepeat-nの下にchord-seqを作り、repeat-nのアウトプットからchord-seqの左から2番目のインプットにコードを繋ぐ。mキーで中身を表示させ、evaluateする。
すると、ドミソの和音が5回繰り返して表示される。
すると、ドミソの和音が5回繰り返して表示される。
今度は、ファンクションomloopを作成する。
作成した直後はinputを持っていないが、以前と同じ方法の>キーでインプットを増やせる。ここでは1つに設定してchordの左から2番目のアウトプット(output 1)からコードを繋いでおこう。
作成した直後はinputを持っていないが、以前と同じ方法の>キーでインプットを増やせる。ここでは1つに設定してchordの左から2番目のアウトプット(output 1)からコードを繋いでおこう。
ここでomloopをダブルクリックすると、中にいくつかのオブジェクトが置かれたサブパッチが現れる。
まずomloopウィンドウ上部にあるアイコンのうち、右から2つ目のLISTと書いたアイコンをクリックすると、listloopというオブジェクトが現れる。
このlistloopは、受け取ったリストのうち最初から最後までの値をループのたびに一つずつの値を返す。今ここでは(6000 6400 6700)という値が入力されているので、合計3回ループし、1番目のループでは6000、2番目は6400、3番目は6700が出力される。
このlistloopは、受け取ったリストのうち最初から最後までの値をループのたびに一つずつの値を返す。今ここでは(6000 6400 6700)という値が入力されているので、合計3回ループし、1番目のループでは6000、2番目は6400、3番目は6700が出力される。
listloopの左側に先ほど扱ったfirstを作り、その下にlistを作ってinputを2つに増やし、firstとlistloopからそれぞれ繋いでおこう。(画像参照)
ここでもう一度omloopウィンドウ上部のアイコン群を見よう。右側のグループの右から2番目のアイコンをクリックすると、collectというオブジェクトが現れる。これを先ほどのlistの下に置き、左から1番目のアウトプット(output 0)を画面下にあるオブジェクトのeachTimeに、左から2番目のアウトプット(output 1)をfinallyに接続する。(画像参照)
これで一旦omloopのサブウィンドウを閉じる。
このomloopをevaluateしてみると、結果は((6000 6000) (6000 6400) (6000 6700))となる。これについて説明しよう。
omloopの中に置いたfirstは常に与えられたリスト、ここでは(6000 6400 6700)の最初の値を参照し、listloopはループのたびにリストの中の値を順番に参照する。つまり最初のループではfirstは6000を、listloopも6000を返す。これがlistで括弧にまとめられるので(6000 6000)となる。これがcollectに代入される。次のループではfirstは6000を、listloopは6400を返す。これがlistで(6000 6400)となる。次のループではfirstは6000を、listloopは6700を返す。これがlistで(6000 6700)となる。リストの値はこれで最後なので、最後にcollectによって集められていたそれぞれのループごとの結果がさらに括弧でまとめられ、((6000 6000) (6000 6400) (6000 6700))となる。
omloopの中に置いたfirstは常に与えられたリスト、ここでは(6000 6400 6700)の最初の値を参照し、listloopはループのたびにリストの中の値を順番に参照する。つまり最初のループではfirstは6000を、listloopも6000を返す。これがlistで括弧にまとめられるので(6000 6000)となる。これがcollectに代入される。次のループではfirstは6000を、listloopは6400を返す。これがlistで(6000 6400)となる。次のループではfirstは6000を、listloopは6700を返す。これがlistで(6000 6700)となる。リストの値はこれで最後なので、最後にcollectによって集められていたそれぞれのループごとの結果がさらに括弧でまとめられ、((6000 6000) (6000 6400) (6000 6700))となる。
omloopの下にchord-seqを作成してこの結果をevaluateしてみると、ドド、ドミ、ドソという2音ずつの和音3つが表示されるのである。
さて先ほどlistloopを使ったが、omloop内のループファンクションには他にもforloop, whileloop, onlistloopがある。
ここではもう一つのよく使われるforloopについて見てみよう。
ここではもう一つのよく使われるforloopについて見てみよう。
まずnoteを作る。デフォルトのC4(ド)のまま用いるので、そのままbキーでブロックする。
その下にomloopを作成し、>キーでインプットを2つにしておく。
input 0にはchordのoutput 1を繋ぎ、input 1はshift+クリックでボックスを出し12と入れておく。
その下にomloopを作成し、>キーでインプットを2つにしておく。
input 0にはchordのoutput 1を繋ぎ、input 1はshift+クリックでボックスを出し12と入れておく。
omloopの中身を開き、上のアイコンの左側の群の一番左にあるFORのアイコンをクリックし、forloopを作成する。
forloopの左側のインプット(input 0)をクリックしてボックスが出る。デフォルトで0が入っているのでその0のまま用いる。
右側のインプットには、omloopの中に現れたinput 1のアイコンのアウトプットをそのまま繋ぐ。omloopの外側ではボックスに12を入れていたから、ここでは12が入力される。
これでforloopは0から始まって12までのループのたびに1ずつ増える数値を出力する。
forloopの左側のインプット(input 0)をクリックしてボックスが出る。デフォルトで0が入っているのでその0のまま用いる。
右側のインプットには、omloopの中に現れたinput 1のアイコンのアウトプットをそのまま繋ぐ。omloopの外側ではボックスに12を入れていたから、ここでは12が入力される。
これでforloopは0から始まって12までのループのたびに1ずつ増える数値を出力する。
その下にファンクションom*を用意する。これは掛け算のオブジェクトである。左側のインプットにforloopのアウトプットを、右側のインプットはボックスを出して100を入力しておく。
これでforloopの出力する数値はそれぞれ100倍される。最初のループでは0だから0*100=0である。次のループでは1が来るので1*100=100になる。次は2*100=200、という具合である。
これでforloopの出力する数値はそれぞれ100倍される。最初のループでは0だから0*100=0である。次のループでは1が来るので1*100=100になる。次は2*100=200、という具合である。
その下にom+を用意し、左側のインプットにはオブジェクトinput 0のアウトプットを、右側にはom*のアウトプットを繋ぐ。
input 0にはnoteのC4(ド)の音、つまり数値6000が入っていたので、先ほどのom*からの出力を足すと、それぞれ6000+0=6000, 6000+100=6100, 6000+200=6200 ... となる。
input 0にはnoteのC4(ド)の音、つまり数値6000が入っていたので、先ほどのom*からの出力を足すと、それぞれ6000+0=6000, 6000+100=6100, 6000+200=6200 ... となる。
先ほどと同じようにcollectを用意する。om+のアウトプットをそれに繋ぐ。collectのoutput 0はeachTimeに、output 1はfinallyに繋ぐ。
ここまで出来たらomloopのサブウィンドウを閉じる。
ここまで出来たらomloopのサブウィンドウを閉じる。
パッチのメインウィンドウに戻り、omloopをevaluateしてみると、(6000 6100 6200 6300 6400 6500 6600 6700 6800 6900 7000 7100 7200)という結果が出力される。
今度はchord-seqを作成する。
omloopのアウトプットをchord-seqの左から2番目のinput 1に繋いでevaluateすると、ド、ド#、レ、レ#、ミ・・・と半音ずつ上がる単音がオクターブ上のドまで表示されるはずである。中身をクリックして鳴らして確認しよう。
omloopのアウトプットをchord-seqの左から2番目のinput 1に繋いでevaluateすると、ド、ド#、レ、レ#、ミ・・・と半音ずつ上がる単音がオクターブ上のドまで表示されるはずである。中身をクリックして鳴らして確認しよう。
待てよ、とここで気づいた人は勘が良い。ド、ド#、レ、レ#、ミ・・・オクターブ上のド、まで数えると、音符は合計で13個ある。
先ほど12という数値を与えたのに、なぜ13個あるのだろうか。
ここでLISPは0からものを数えるという原則が生きてくる。0-12でループすると、実はその数値は0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12の合計13個あるのである。
ここは初心者に取って混乱しやすい場面なので、ぜひとも注意してほしい。
先ほど12という数値を与えたのに、なぜ13個あるのだろうか。
ここでLISPは0からものを数えるという原則が生きてくる。0-12でループすると、実はその数値は0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12の合計13個あるのである。
ここは初心者に取って混乱しやすい場面なので、ぜひとも注意してほしい。