音の鳴るエディタが便利だけど使うと Vim が死ぬほど重くなる。適当に軽量化した。
#!/usr/bin/env ruby
open("#{ENV["HOME"]}/vim_audio_list",'a'){|x| x.puts ARGV[0]}
#!/usr/bin/env ruby
require "coreaudio"
require 'kconv'
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
while true
f = open("#{ENV["HOME"]}/vim_audio_list")
list = f.read.toutf8.split("\n")
f.close
list.delete_if{|x| x == ''}
if list.count > 0
f = open("#{ENV["HOME"]}/vim_audio_list", "w")
f.puts ''
f.close
list.each{|x|
next if x.nil? or x.empty?
sounder.random_sound(x, 0.1)
}
end
sleep 0.1
end
Vim から呼ぶプロセスは入力されたものをキュー(と呼ぶのもおこがましい酷いもの)に溜め込むだけ。音は別のプロセスが鳴らす。まあ酷いもんだがこれでも実用的に動く。
実際に音を出すやつをターミナルとかで実行しておくと、音が出る。 vimproc で非同期にプロセス読んでも結局どこかでブロックしてるっぽい。呼び出すプロセスを軽くしたら軽くなった。もしかしたら中村さんが非同期にプロセス呼べてないだけかもしれないけど、僕も Vim 詳しくないのでよく分からない。
いずれにせよ上記のアプローチで実用的に音が出るようになった。非常にいいと思う。