Orcaによるオーディオプログラミング例

Orca
===

[オーディオプログラミング言語 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/audiolang)

# 概要

https://github.com/hundredrabbits/Orca
https://100r.co/site/orca.html
https://wiki.xxiivv.com/site/orca.html

二次元平面に文字を置いてプログラミングするライブコーディング用難解プログラミング言語。

Rekka & Devineが開発。初出は2019年。

Orca自身は音源を内蔵しておらず、MIDIやUDP通信で楽器を制御して音を鳴らす。音源としては同じ作者のPilotシンセサイザー( https://github.com/hundredrabbits/pilot )がよく使われる。

# 注

Orcaは自前音源を持っておらず、信号処理的には特筆すべき機能もない言語なので、本来オーディオプログラミング言語Advent Calendarに含めるべきではないかもしれません。しかしながら、一度見たら忘れられないほど独特な言語設計で、ライブコーディングパフォーマンスでも視覚的聴覚的に孤高の存在感がある、この言語を紹介しないわけにはいきません。Advent Calendarを完走した自分へのご褒美に、この魅力いっぱいの難解言語を扱ってもいいことにします。

# 解説

Orca言語はあまりにもユニークで、今回調べた他のテキスト言語やビジュアル言語のいずれにも似ていません。あえて似ているものを探すならライフゲーム（Conway's Game of Life）かもしれません。そのため、実装例の前にイメージしやすいように少し解説をしておきます。

## metro

![img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/599bb556-d67f-1a23-7b13-d3f51b996e42.png)

すべての基本となる、定期的にBangを発生するメトロノームです。Maxのmetroに相当します（DはDelayの意味）。正確には、フレーム数をカウントアップして右側の引数（この例の場合8）の倍数になったときに水色の位置のセルにBangを発火する、という挙動になります。Dの左側のセルはレートで、カウントアップの速度を調整します。省略時は1で大きい値ほど遅くなります。

Orcaのコマンドは基本的にこのようなT型をしています。コマンドの左右に引数があり、コマンドの下側に計算結果をアウトプットします。この計算結果を別のコマンドの引数になるように組み合わせて配置していくのがOrcaのプログラミングです。
※正しくはコマンドではなくオペレーターと呼ぶようですが、ここではわかりやすさを優先してコマンドと呼んでいます。

## Bang

![img2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/55544005-581c-5960-1cd1-479ec302e157.png)

Bangの発火は*の文字で表現されます。発火した場合、上下左右のセルに影響を与えます。多くの場合上のセルにはBangの生成コマンドがあるので、Bangの右や下に連結することが多いです。

## カウントアップ

![img3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/b7b0e944-502d-c55b-06d1-5e6707ef367a.png)

Dコマンドに似たようなものにCコマンド（Clock）があります。フレーム数をカウントアップして水色の位置のセルに数値を出力します。右側のセルは最大値で、4とした場合は0,1,2,3,0,1,2,3,0,…のように順番に出力されます。

## Bangの複製

![img4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/0b73854e-7938-1666-54d8-058013f57e78.png)

プログラムが大きくなってくるとBangが届かなくなることもあります。その場合、JやYをつかってBangを複製することができます。Jは下方向に、Yは右方向にセルの内容を複製します。Bang以外でもCの出力なども複製できます。ただしコマンドを複製しても複製されたものはコマンドとして機能はしません。コマンドの複製には後述のXコマンドを使います。

## Bangの伝達

![img5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/14ed2e23-1ef2-5c34-8df0-d497d296301a.png)

Eコマンドは1フレーム毎に右側に移動して何かにぶつかったらBangを発火します。遠い位置のコマンドにドミノ倒しのトリックのようにBangを伝えるときによく使用されます。同様のコマンドにN、S、Wがあります。それぞれ移動方向が異なりコマンド名は方角の東西南北に由来します。

## グライダーガン

![img6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/00cbc7ff-7519-1ba1-ca80-67331e0c3538.png)

定期的にEコマンドを発射します。
Xコマンドは右側のセルのコマンドを下のセルにコピーします。小文字でxと書くとBangに触れたタイミングでコピーするようになります。コピー元であるxの右側のEは、そのままだと移動してしまうので上にH(Halt)コマンドを置いて機能を無効化しています。

## LFO

![img7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/4b2d0df4-e13c-815a-e95e-7a0c44077535.png)

Xの左側の引数は生成位置なので、Cコマンドで連続的な数値を与えてやると位置をずらしながらEコマンドを連続生成するようになります。結果的にEによるノコギリ波のような波形を生成します。2は波長、4は振幅のパラメータになります。大文字でXと書いた場合は常時活性化して右側のEの機能を無効化し続けるのでHを配置する必要はありません。

![lfo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/7fa654c0-400e-6e8e-d24b-7fe44c796195.png)

## コメント

![img8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/84fd158c-9f4c-2323-8a0d-27826a9e10e1.png)

1行コメント。#を置くとその右側に書いたものはコメントとして無効化されます。

![img9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/be667297-ba82-bf3a-b0a5-5dd3bece8cac.png)

範囲コメント。#～#で挟んだ部分がコメントになります。

## プレイヤー

![img10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/0c1f62f1-3f7c-c7aa-ae8e-58119a6485af.png)

セミコロンコマンドはBangに触れると連携するシンセサイザーへメッセージを送信します。この場合黄色の位置のセルが音程を表しCの音をBangのたびに鳴らします。

## ランダムプレイヤー

![img11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/96d33803-2cfa-d2ae-439e-4d22e2d479eb.png)

太枠部分は前項のプレイヤーと共通です。乱数発生のRコマンドを使って、音程部分をA～Gのランダムな文字列にして鳴らす例です。

## メロディープレイヤー

![img12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/3229bb54-b1a1-7d50-4223-7a9a290c0b9c.png)

これも太枠部分のプレイヤーは共通です。Tコマンドは、全長何文字の文字列から指定位置の文字を取り出すというコマンドです。この例の場合「CAFE」4文字からCコマンドで指定する位置の文字を取り出します。結果的にC、A、F、Eの文字が順番にプレイヤーに渡されメロディーとして演奏されます。

# 実装例

## サイン波生成

プログラミングはOrcaというよりPilotの制御がほとんどです。まずデフォルトでかかっているエフェクトを切るために「BIT00」「CHO00」などのコマンドをPilotに送ります。続いて波形をサイン波にするために「0OSCsisi」コマンドを送り、エンベロープも調整します。Pilotの場合完全なサイン波にはならず、倍音のような音が混ざるのは仕方ないのかもしれません。最後に「04A8f」コマンドを送ってAの音を音量8、長さfで鳴らします。

これらのコマンドを順番に送るためのOrcaプログラムを考えてみます。中央のBang Launcherは前述したLFOです。少しずつずらして生成されたEは右方向へ移動をして;（セミコロン）にぶつかるとPilotにUDPでメッセージを送信します。

しかしながら、Pilotへ送信するメッセージはそれぞれ1回ずつで十分なのでLFOによる繰り返しは不要です。これを阻止するのが上部のLauncher Disable Timerです。CコマンドのカウントアップをFコマンドで常時チェックします。FはIFの意味で左右の値が同じになったらBangを出力します。今回の場合カウントアップの値が8になったらBangが発火します。このBangを受けて、下にあるxコマンドがxの右側の空セルの内容をxの下のCの位置にコピーします。結果的にCが消去されてコピー先座標の数値が変化しなくなり2回目以降のメッセージは送信されなくなります。

```
.......................................................................
.......................................................................
...........6C9..#.Launcher.Disable.Timer.#.............................
............0F8........................................................
.......................................................................
.............x.........................................................
............6C7.#.Bang.Launcher.#......................................
.............0XE.....................#.Commands.#......................
.....................................;BIT00.....#.Bit.Crusher.Off.#....
.....................................;CHO00.....#.Chorus.Off......#....
.....................................;TRE00.....#.Tremolo.Off.....#....
.....................................;VIB00.....#.Vibrato.Off.....#....
.....................................;0OSCsisi..#.Set.Sine.Wave...#....
.....................................;0ENV00f0..#.Set.Envelope....#....
.....................................;04A8f.....#.Play.Note.......#....
.......................................................................
......################################.................................
......#.Sine.Wave.Generate.Program...#.................................
......#......for.Pilot.synthesizer...#.................................
......################################.................................
.......................................................................
```

## Delayエフェクト

OrcaもPilotもwavファイルを再生する機能はありません。今回はcassetter( https://person0b.itch.io/cassetter )を使うことにします。cassetterは、作者は異なりますがOrcaと連動することを意識して作られたプレイバックサンプラーで、デザインも通信もOrcaと大変相性が良いです。ディレイエフェクトを内蔵しているのでこれを利用します。

プログラムはサイン波生成とほとんど同じです。cassetterへはMIDIでコマンドを送るので;ではなく!コマンドを使います。アプリ間でMIDI通信できるように、macOS付属のIAC DriverやWindowsのLoopBe1のようなツールで仮想MIDIを用意しておきます。cassetterはあらかじめ起動してchannel 0にvoice.wavを読み込んでおきます。読み込みファイル指定まではOrcaから送ることができません。Orcaプログラムでは、ディレイタイム等の設定コマンドを送った後に「00o」コマンドでchannel 0の音を1回鳴らしています。

```
.......................................................................
.......................................................................
...........6C6..#.Launcher.Disable.Timer.#.............................
............0F5........................................................
.......................................................................
.............x.........................................................
............6C4.#.Bang.Launcher.#......................................
.............0XE.....................#.Commands.#......................
.....................................!02z....#.Grain.Size.#............
.....................................!09e....#.Delay.Time.#............
.....................................!0ae....#.Feedback...#............
.....................................!00o....#.Play.Voice.#............
.......................................................................
.......................................................................
.......................................................................
.......................................................................
......################################.................................
......#.Playback.and.Delay.Program...#.................................
......#......for.cassetter.sampler...#.................................
......################################.................................
.......................................................................
```

![delay.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/432b6e3d-356c-7cd2-0eb3-9d9b88d9eb54.png)

# 感想

二次元平面のプログラミング言語という発想は非常にユニークであるだけでなく、ソースコードの見た目がシーケンサーやリズムマシンに近くなるという点でも面白いです。

作者は漫画家兼ライターとプログラマー兼ミュージシャンで、世界中を航海しながらソフトウェア作品を作っているそうです( https://100r.co/site/about_us.html )。そういったライフスタイルやアート志向が、ユニークでミニマルな言語設計に反映されているようにも思います。

なお、以前のバージョンではBコマンドがsubtract(減算)ではなく、最小値と最大値の間でインクリメントとデクリメントを繰り返すbounceとなっていました。ネット上の解説やサンプルプログラムには両方の記述が混在しているので注意してください。

オーディオプログラミング分野でOrca言語が意味を持つのかどうかはわかりませんが、ライブコーディングパフォーマンス、テクノロジーアート、難解プログラミング言語の分野では大きな功績として今後さらに評価が高まるのではないかと思います。

[オーディオプログラミング言語 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/audiolang)