Ableton Live で FizzBuzz

プログラミング言語で FizzBuzz を実装できるのは当たり前じゃないですか。ということで、音楽制作ソフトウェアである [Ableton Live](https://www.ableton.com/ja/live/) で FizzBuzz を実装してみました。

## デモ動画

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Ableton Live で FizzBuzz が実装できた <a href="https://t.co/jOVx4njgDg">pic.twitter.com/jOVx4njgDg</a></p>&mdash; Akinori Tomita (@__tmy) <a href="https://twitter.com/__tmy/status/937691644580700161?ref_src=twsrc%5Etfw">2017年12月4日</a></blockquote>

## Ableton Live について

Ableton Live は、DAW という音楽を制作するためのジャンルに属するソフトウェアです。

通常の DAW が曲を制作するために作られているのに対し、Ableton Live は名前の通りライブでの使用も想定されて作られているのが特徴です。このため、音楽の演奏を録音・記録された通りに再生するだけではなく、曲の展開をその場でコントロールできるように**セッションビュー**という画面を備えているのが最大の特徴です。

この特徴のため、Ableton Live は純粋な音楽制作だけでなく、MIDI 信号出力による照明のリアルタイム制御やインスタレーションのシステムの制御といった分野にも使われているそうです。

セッションビューには、即興的な操作をサポートするために、簡単な自動化の機能が備わっています。今回はこれを活用して FizzBuzz の挙動を再現します。

なお、Ableton Live には、MAX/MSP という本物のビジュアルプログラミング環境と連携する Max for Live というオプション機能がありますが、今回は使用しません。なぜならプログラミング環境で FizzBuzz を実装できるのは当たり前だからです。

## 要件

今更ですがおさらいしておきます。

  * 1 から 99 まで数え上げる
  * 3 で割り切れる時は「fizz」と数える
  * 5 で割り切れる時は「buzz」と数える
  * 15 で割り切れる時は「fizz buzz」と数える

オーディオを扱うソフトなので、出力は音声とします。
また、今回は日本語で出力するものとします。

## 動作環境

Ablenton Live 9 (Suite 推奨)

## 音ネタの準備

まずは音声が必要です。Mac の場合は `say` コマンドを使うと簡単に用意できます。

```
$ say 1 -o 1.aiff
```

こんな感じで、1〜9, 10〜90, fizz, buzz, fizzbuzz の音声ファイルを作成しておきます。

## プロジェクトの基本設定

1 小節で 1 つカウントすることにします。また、2 桁の数値を発音させるので、2 拍子に設定しておくと打ち込みが見やすくなります。

テンポは何でもいいんですが、`say` コマンドが出力する音声のスピード感だと、だいたい BPM=90 くらいが適当なようです。デモ動画では時間短縮のために BPM=180 に設定してありますが、この場合音声ファイルをタイムストレッチして早口に加工する必要があります(今回は説明しません)。

拍子とテンポを設定するとこうなります。

<img width="312" alt="スクリーンショット 2017-12-07 0.13.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/419692a4-7e7a-43d1-2dd1-40efcb289375.png">

また、前述の通り以下のすべての操作は[セッションビュー](https://www.ableton.com/ja/manual/session-view/)で行います。

## 1 から 99 までカウントする

初めに、fizzbuzz 抜きで数値を「1」から「99」まで順番にカウントすることを考えます。幸運なことにループ再生機能があるので、1 の桁と 10 の桁をそれぞれ別々の[トラック](https://www.ableton.com/ja/manual/live-concepts/#トラック)でループ再生させることにします。

全体設定で 2 拍子に設定したので、10 の桁を 1 拍目に再生し、続けて 1 の桁を 2 拍目に再生させれば、一応 2 桁の数値を読み上げているように聞こえるはずです。

### 1 の桁

「1 の桁」は MIDI トラックにして、「1」,「2」, ...,「9」,「0」の数え上げをループ再生させます。全部で 10 小節でループすることになります。
実際には「0」は発音しないので、最後の 1 小節は無音になります。

[トラックビュー](https://www.ableton.com/ja/manual/working-with-instruments-and-effects/)に [Drum Rack](https://www.ableton.com/ja/manual/instrument-drum-and-effect-racks/#drum-rack) デバイスを配置し、パッドに「1」から「9」の音声ファイルを設定します。

<img width="308" alt="スクリーンショット 2017-12-07 1.10.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/4b50cf61-0944-b393-95dd-676b7f1911cf.png">

そしてセッションビューで、各小節の 2 拍目で「1」から「9」まで順番に再生する [MIDI クリップ](https://www.ableton.com/ja/manual/editing-midi-notes-and-velocities/)を作れば良いわけです。前述の通り最後の 1 小節は無音になります。

<img width="1432" alt="スクリーンショット 2017-12-07 1.18.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/09664251-f4a0-91a2-63b3-1d770cc27876.png">

ただ、これだとカウントが 10 に満たない時、すなわち「1」から「9」をカウントする時も 2 拍目に発音し、1 拍目は無音になるため、実際に聞くと少々気持ち悪く感じます。聴感上は 1 拍目に発音した方が自然に聞こえます。
このため、10 未満をカウントする用にもう一つ MIDI クリップを作ります。

<img width="1435" alt="スクリーンショット 2017-12-07 1.17.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/6db8325d-b495-0346-e46b-14c623069c5d.png">

セッションビュー上で 2 つのクリップは以下のように配置します。一番上に 10 未満をカウントするためのクリップを置き、その下に 10 以上をカウントするためのクリップを置きます。

<img width="90" alt="スクリーンショット 2017-12-07 1.15.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/51b3bd8e-a2fd-bcde-c6df-d1e079b034eb.png">

こうして作った 2 つのクリップを再生途中で切り替えるために、[Follow Action](https://www.ableton.com/ja/manual/launching-clips/#フォローアクション) 機能を使います。10 未満用クリップは 10 小節再生したら次のクリップを再生する設定に、10 以上用クリップは 89 小節再生 (合計で 99 小節再生) したら停止する設定にします。

### 10 の桁

「10 の桁」も MIDI トラックにします。「1 の桁」と同様に、トラックビューに Drum Rack デバイスを配置し、パッドに「10」から「90」の音声ファイルを設定します。

<img width="311" alt="スクリーンショット 2017-12-08 1.22.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/240d2da9-ec6d-dca8-a21f-33fd328d2bf9.png">


「10 の桁」全体では、以下のシーケンスで再生をすることになります。

  * 最初の 9 小節は無音
  * 次の 10 小節は毎小節「10」を再生
  * 次の 10 小節は毎小節「20」を再生
  * (以下「90」まで繰り返し)

「1 の桁」と異なり、一つのクリップではひたすら同じ数字をループ再生させます。例えば「21」,「22」, ... を読み上げている間は毎小節ひたすら「20」を再生させます。よってクリップの長さは 1 小節です。

<img width="1433" alt="スクリーンショット 2017-12-08 1.18.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/f7fec4fa-3d0d-e945-41db-d713113b7c04.png">

セッションビューには先頭に無音のクリップを、あとは「10」から「90」のクリップを順に並べます。

<img width="89" alt="スクリーンショット 2017-12-08 1.19.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/e5a5a1d3-f71b-305a-81bf-a332b9453e11.png">

これらクリップも Follow Action 機能で連結します。先頭の無音クリップは 9 小節で次のクリップを再生する設定に、中間のクリップは 10 小節で次のクリップを再生する設定に、最後の「90」のクリップは 10 小節で停止する設定にします。

ここまで出来た状態で先頭の[シーン](https://www.ableton.com/ja/manual/session-view/#トラックとシーン)を再生開始すると、「1」から「99」まで読み上げてくれるはずです。

## Fizz, Buzz, FizzBuzz を再生する

次に、Fizz, Buzz, FizzBuzz をそれぞれ適切なタイミングで再生することを考えます。

まず「Fizz」はカウントが 3 の倍数の時に再生させるのですが、これは単純に長さ 3 小節で 3 小節目に「Fizz」を再生する MIDI クリップを作ってループ再生させれば良いです。

「Fizz」用に新たに MIDI トラックを作成し、カウント用トラックと同様に Drum Rack 内に「Fizz」の音声ファイルを配置します。

<img width="314" alt="スクリーンショット 2017-12-10 0.38.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/ba12581b-a49c-f45a-dc29-a0ad760617f6.png">

MIDI クリップは Follow Action で 99 小節再生したら止まるようにしておきます。

<img width="1434" alt="スクリーンショット 2017-12-10 0.33.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/61007019-859a-de07-c72a-e1b84ea6e808.png">

同様にして、「Buzz」は 5 小節目だけ再生するように、「FizzBuzz」は 15 小節目だけ再生するようにします。

<img width="1440" alt="スクリーンショット 2017-12-10 0.39.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/84615147-1470-5971-a589-3572a46d78b1.png">

<img width="1440" alt="スクリーンショット 2017-12-10 0.39.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/54ff2d4a-74e8-2d6e-3c9e-e94afb53b29f.png">

## 不要な音をミュートする

ここまでで必要な音を全て鳴らすことができますが、このままでは複数の音が重なって再生されてしまうので余分な音が鳴らないようミュートする必要があります。

  * 「Fizz」か「Buzz」が鳴っている間はカウントをミュート
  * 「FizzBuzz」が鳴っている間は「Fizz」「Buzz」をミュート

### サイドチェインコンプ

ミュートを実現するために、[サイドチェインコンプ](https://www.ableton.com/ja/manual/live-audio-effect-reference/#サイドチェーンのパラメーター)というエフェクターを利用します。サイドチェインコンプの働きを雑にいうと、別のトラックで鳴っている音量分だけ音を小さくするというものです。

Ableton Live では、[Compressor](https://www.ableton.com/ja/manual/live-audio-effect-reference/#compressor) デバイスのオプションでサイドチェインの指定が行えます。

ただしサイドチェインコンプで音量が下がるのは、サイドチェインで音が鳴っている瞬間だけであることに注意が必要です。カウントに適用するサイドチェインの入力を「Fizz」に指定するだけだと、「Fizz」を再生し終わった瞬間に音量が元に戻ってしまいます。なので例えば「12」など「Fizz」より長い音については、後半の「2」の音が残ってしまいます。

これを防ぐために、該当する小節の間ずっとサイドチェインが反応するよう持続音が鳴り続けるトラックを用意し、それをサイドチェインの入力に指定します。かなり富豪的な方法ではありますが。

### サイドチェインの入力を作る

「Fizz」「Buzz」「FizzBuzz」の各 MIDI クリップは既に 1 小節丸々持続して発音するパターンになっています。この MIDI クリップが出力する MIDI 信号は直接 Drum Rack に接続されていますが、これを分岐して元々ある Drum Rack と新たに追加する持続音のトラックの両方に分配します。

まず、MIDI クリップと Drum Rack は同じトラックに配置されていますが、これを別のトラックに分離しておきます。そして持続音のトラックを追加します。

持続音トラックには、ソフトウェア音源の [Operator](https://www.ableton.com/ja/manual/live-instrument-reference/#operator) を配置します。[^1]

[^1]: Ableton Live Standard 版には付属していないので、代わりに何か無料ので良いのでソフトウェアシンセを使ってください。

サイドチェインの入力に使うだけなので、音色はなんでも良く、一定の音量で鳴るのが重要なので、[エンベロープ](https://www.ableton.com/ja/manual/live-instrument-reference/#エンベロープ)を以下のように設定します。

| パラメーター | 値 |
| ---- | ---- |
| Attack | 0 ms |
| Sustain | 0 dB |
| Release | 1 ms (最短) |

<img width="758" alt="スクリーンショット 2017-12-10 1.52.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/10f19753-f4bd-8afa-57e1-91668af2ad64.png">

これで分配元となる MIDI クリップのあるトラックと、分配先となる Drum Rack のあるトラック、Operator のあるトラックの 3 トラックが用意できたので、これらを接続します。1 つの MIDI 信号を複数のトラックに分配するには、トラックの[入力/出力セクション](https://www.ableton.com/ja/manual/routing-and-i-o/)で設定します。

<img width="78" alt="スクリーンショット 2017-12-10 1.39.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/4aefb92c-f915-c516-7102-11bccf508f0f.png">

| | 分配元トラック<br>(MIDI クリップを配置) | 分配先トラック<br>(音源を配置) |
| ---- | ---- | ---- | ---- |
| **MIDI From** | All Ins | 分配元トラック |
| **Monitor** | Auto | In |
| **MIDI To** | No Output | - |

これを Fizz, Buzz, FizzBuzz それぞれ 3 トラック作ります。また、Fizz と Buzz トラックの出力は[グループトラック](https://www.ableton.com/ja/manual/mixing/#グループトラック)で一つにまとめます。

<img width="295" alt="スクリーンショット 2017-12-10 1.50.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/cc8e2f61-79e4-a545-94d7-19c6a088b231.png">

各トラックの出力セクションは以下のように設定して、マスター出力に音が流れないようにします。

| | Fizz,Buzz のグループ | Fizz | Buzz | FizzBuzz |
| ---- | ---- | ---- | ---- | ---- |
| **Audio To** | Sends Only | Group | Group | Sends Only |

### サイドチェインコンプの設定

>   * 「Fizz」か「Buzz」が鳴っている間はカウントをミュート

を設定します。まずカウントの 1 の桁と 10 の桁のトラックをグループトラックで一つにまとめます。

<img width="251" alt="スクリーンショット 2017-12-10 2.10.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/2c6d9979-bda7-bc84-66fb-f1c65c9fbc2c.png">

このトラックのトラックビューに Compressor デバイスを置き、以下のようにパラメーターを設定します。

| パラメーター | 値 |
| ---- | ---- |
| Sidechain | ON |
| Audio From | Fizz,Buzz のミュート用トラック<br>(グループトラック) |
| Ratio | inf : 1 |
| Attack | 0.01 ms |
| Release | 1.00 ms |
| Thresh | -inf dB |
| Knee | 0.0 dB |

これでミュート用トラックからオーディオ信号が来ている間、音量が最低に抑えられます。が、音量が完全にゼロになるわけではなく、微かに聞こえてしまいます。

微かに聞こえる音を完全に削るため、[Gate](https://www.ableton.com/ja/manual/live-audio-effect-reference/#gate) デバイスを利用します。Gate デバイスは、一定以下の音量のオーディオ信号をカットするオーディオフィルターです。普通はノイズのカットなどの用途で使用します。

Compressor デバイスの後ろに Gate デバイスを置き、以下のようにパラメーターを設定します。

| パラメーター | 値 |
| ---- | ---- |
| Threshold | 実際に音を聞いて余計な音だけ消えるポイントを探す |
| Return | 0.00 dB |
| Lookahead | 0 ms |
| Attack | 0.02ms (最短) |
| Floor | -inf dB |

<img width="712" alt="スクリーンショット 2017-12-10 2.16.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/7337479d-6e88-ca91-3ec7-03cb8dda3433.png">


>  * 「FizzBuzz」が鳴っている間は「Fizz」「Buzz」をミュート

も同様に「Fizz」「Buzz」のグループトラックを作り、

<img width="249" alt="スクリーンショット 2017-12-10 2.13.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/b58386a9-664e-cff4-a6d5-3902551b4e8b.png">

作成したトラックのトラックビューに Compressor と Gate を配置します。サイドチェインの Audio From パラメーターには FizzBuzz のミュート用トラックを指定します。

これで完成です！

## トラック全体のルーティング

<img width="1411" alt="スクリーンショット 2017-12-10 2.29.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/57c8e8ae-a260-811a-ea4b-4736c3e9ed1b.png">

このプロジェクト内のルーティングを図示すると、以下のようになります。

<img width="884" alt="fizzbuzz.png" src="https://qiita-image-store.s3.amazonaws.com/0/20615/f876db99-2ba4-e22d-b37d-541b105ae790.png">


## プロジェクトファイルダウンロード

https://www.dropbox.com/s/yc0624mxht4crva/FizzBuzz.zip