🎼

Rubyの並列/非同期処理を"音"で表現する

2022/05/12に公開

まえおき: 非同期処理のサンプルコードは退屈である

concurrent-rubysocketry/asyncなど、Rubyには幾つかの非同期処理むけのライブラリがある。

そうしたライブラリのサンプルコードというのは、たいてい「sleep」とか「puts」で構成されている。ようするに、「ちょっとまってからコンソールにHelloと出る」みたいなそういうやつだ。
ただ、社内勉強会や社外勉強会でそういうのを紹介したとすると、聴衆は熱心に聞きつつも眠くなりがちだ。

そこで、"音"

みんな小学校でピアニカくらいは弾いたことがあるだろう。和音とか伴奏とかいう概念は、どんなに音楽に疎いエンジニアであっても間違いなくみんな知っている。

両手で音楽を弾くというのは、並列処理の為せる技だ。

つまり、2つの旋律をそれぞれメソッド定義して、それらを非同期に実行して音を鳴らすことができれば、きれいな和音で構成された音楽がその場を包む。

きれいな音楽が流れたら、勉強会の場はわりと和む。

Rubyで音を鳴らすには?

これには幾つかの前例がある。

有名どころだと、RubyConf 2015のこれ。
https://www.youtube.com/watch?v=exZTxhH06tw

Sonic Piというソフトを使っていろいろやっている。

あとは、rukawaワークフローエンジンで音を鳴らしていたこれ。
https://speakerdeck.com/5t111111/rubytoxi-reruoss-dtm

手っ取り早くは、osc-ruby(https://github.com/aberant/osc-ruby) と Sonic Piとを準備すれば、

require 'osc-ruby'

def play(sound)
  client = OSC::Client.new('localhost', 51235)
  client.send(OSC::Message.new('/run-code', 'DEMO', "play #{sound}"))
end

これだけで音は鳴らせる。Sonic Piを立ち上げた状態で play(60) すれば「ドー♪」と鳴る。
適度にsleepを入れてやれば、単旋律は簡単に作ることができる。

# かーえーるーのーうーたーがーー
play(60)
sleep 0.4
play(62)
sleep 0.4
play(64)
sleep 0.4
play(65)
sleep 0.4
play(64)
sleep 0.4
play(62)
sleep 0.4
play(60)
sleep 0.8

# きーこーえーてーくーるーよーー
play(64)
sleep 0.4
play(65)
sleep 0.4
play(67)
sleep 0.4
play(69)
sleep 0.4
play(67)
sleep 0.4
play(65)
sleep 0.4
play(64)
sleep 0.8

# ぐわーx4
4.times {
  play(60)
  sleep 0.8
}

# げげげげげげげげぐわぐわぐわ
play(60)
sleep 0.2
play(60)
sleep 0.2
play(62)
sleep 0.2
play(62)
sleep 0.2
play(64)
sleep 0.2
play(64)
sleep 0.2
play(65)
sleep 0.2
play(65)
sleep 0.2
play(64)
sleep 0.4
play(62)
sleep 0.4
play(60)
sleep 0.8

並列処理で輪唱

単旋律を用意するだけで、輪唱は簡単に実現できる。数秒ずらして2つの同一旋律を流すだけだからだ。

たとえば前述のかえるのうたであれば、旋律を kaeru というメソッドで定義したとして

require 'concurrent'

Concurrent::Promises.zip(
  Concurrent::Promises.future { kaeru },
  Concurrent::Promises.future { sleep 3.2 ; kaeru },
  Concurrent::Promises.future { sleep 6.4 ; kaeru },
).value!

こんなかんじで3並列の輪唱ができあがる。

勉強会としては Concurrent::Promises.zip がPromise.all的なやつよー、 .value! が awaitに相当するものよー、などなど学ぶコンテンツになる。

オンライン開催の勉強会で音を鳴らす

自分のPCから音がなってテンションが上がる。しかし勉強会がオンライン開催だったらどうやってそれをみんなに届けるか?という問題がある。

ZOOMであれば、実は簡単だ。画面共有のメニューで音声を共有するためのチェックボックスがある。それにチェックをいれてから画面共有するだけだ。

音声テストは発表開始時に必ずやろう!

これで音声が無事に届く・・・とは限らない。

なぜかわからないが、Sonic Piの音がZOOM会議で届かないことがある。

音声テストは、Rubyのコードを動かして音を鳴らす必要はない。(そんなことしたらネタバレしてしまう)
単純に、Sonic Piで play 60 と打って再生するだけでいい。


これを実施して「ドー♪」という音がみんなに届いているかだけ確認ができればOKだ。
(勘のいいエンジニアは、Sonic Piを使用しているという事実にも気づいてしまうし、音で何かをやるということ自体はネタバレしてしまう。

ただ、実際にデモをやろうとしたときに音が出ずトラブるよりは、事前に音声テストをしたほうが遥かにマシだ。かならずオンライン会議の開催直後に音声テストをしよう。

音が届いていない場合には、Sonic Piを再起動する!

音が会議を聞いているメンバーに聞こえていない場合には、Sonic Piがなんらかのオーディオ設定の変更により音声出力できない状態になっている可能性が高い。

こういうときは、Sonic Piを必殺再起動すると、だいたい直る。

あとは、音をみんなで感じながら非同期処理のお勉強を楽しむのみ!

まとめ

  • osc-rubyとSonic Piで、Rubyから簡単に音を鳴らすことができる。
  • ZOOMの画面共有で「音声を共有」チェックボックスにチェックを入れれば、オンライン勉強会でも音を伝えることができる
  • 音声を共有しているのに向こうに届いていない場合には、あせらずSonic Piを必殺再起動するとだいたい直る。

Discussion