音の鳴るエディタことVim

音の鳴るエディタ - ✘╹◡╹✘の技術的解説。

おさらい

音の鳴るエディタ 眼を閉じた状態で"Hello"と入力して、画面を見ずに正しく"Hello"と入力されていることを確認したい。 そこで、キーを叩く度にそれぞれ固有の音が鳴るようにした。 プログラミングしながら演奏できる。 開発者集めてジャムセッションとかできると思う。 人月の神話っぽくならないように注意したい。

仕組み

Vimはキーイベントが取れるので、キーを押したときにカーソルの下にある文字を取得して、それを非同期でRubyのプログラムに渡す。objective-c調べて書くの面倒だからRuby使った。Rubyの方は、文字列の文字コードと見て適当に半音階ずつの周波数を決める。a, b, c, d, ...と半音ずつ上がっていく。キーイベントでキーが取得できて非同期でシステムコマンド呼び出せるエディタだったら何でも使えると思うけど、5分ぐらい探した限りVimぐらいしかなかった。非同期にするのにvim-proc使ってるけど、いま使ってるMacbookAirだと1秒に3〜4文字ぐらいのタイプ速度なら支障ないけど、環境によって遅くなったりするっぽい。

.vimrc

autocmd CursorMovedI \* :call vimproc#system\_bg($HOME . "/bin/vim-key-sound.rb '" . getline('.')[col('.') - 2] . "'")

~/bin/vim-key-sound.rb

#!/usr/bin/env ruby require "coreaudio" class SinWaveSounder LONG = 44000 scale = 2.0 \*\* (1 / 12.0) FREQUENCIES = 28.times.map do |i| 220 \* (scale \*\* i) end def initialize dev = CoreAudio.default\_output\_device @buf = dev.output\_loop(LONG) end def sound(frequency, sec) phase = Math::PI \* 2.0 \* frequency / LONG LONG.times do |i| @buf[i] = ((0.4 \* Math.sin(phase\*i)) \* 0x7FFF).round end @buf.start sleep(sec) @buf.stop end def random\_sound(seed, sec) i = seed.ord % FREQUENCIES.size sound(FREQUENCIES[i], sec) end end sounder = SinWaveSounder.new sounder.random\_sound(ARGV[0], 0.1)

音質

エディタから音が鳴るようになったら当然7.1chで聴きたいと思うだろうし、併せてこちらもお読みください。

7.1ch - ✘╹◡╹✘
http://r7kamura.hatenablog.com/entry/2012/08/10/135239