SVX日記
2025-02-17(Mon) シン・チープなDTMアプリ
Linuxのサウンド機能についておさらいしたところで、だーいぶ以前に作った自作のDTMスイート「CUIck DTM suite」を引っ張り出してみることにした。当時はまだWindozeを使ってたので、Cygwin環境に向けて書いたものだ。何度か何度か何度かお色直しして使い続けているが、いまでも使えるものだろうか?
「CUIck DTM suite」には「melod」という発声デーモンがあって「konk」というアプリを組み合わせることで「PCのキーボード」が「楽器のキーボード」と化す。過去にはソレ用にこんな風に塗り分けたりしてた頃もあった。
OSSアプリ → OSSエミュ(PulseAudioの) → PulseAudioエミュ(PipeWireの) → PipeWire → ALSA
$ padsp ./melod
通常の環境には/dev/dspは存在しないのだが、padspを噛ませた中の環境には/dev/dspが出現するので、それを経由してPulseAudio……ではなく、PipeWireを経てALSAから鳴るわけだ。実際、アッサリと鳴った。よく考えてみれば、エラく回りクドいことをやってたんだな。
# modprobe snd_pcm_oss
これにより/dev/dspではないが、/dev/dsp1, /dev/dsp2が出現する。/dev/dsp1がノートPC本体のデバイス、/dev/dsp2はドックのデバイスを指すものだ。これを使えば、以下の経路を使うことになる。
OSSアプリ → OSSエミュ(ALSAの) → ALSA
$ ./melod
fragmentのサイズを調べようと思って、ioctlでSNDCTL_DSP_GETBLKSIZEを発行してみる。どうでもいいけど、ioctlってどこかに仕様がまとめられていたりしないの? カーネルのコード読むほかないのかしらん。
x = [0].pack('i*')
p dsp.ioctl(0xc0045004, x) # SNDCTL_DSP_GETBLKSIZE
printf("%04x\n", x.unpack('i*')[0])
x = [0, 0, 0, 0].pack('i*')
p dsp.ioctl(0x8010500c, x) # SNDCTL_DSP_GETOSPACE
printf("%04x %04x %04x %04x\n", *(x.unpack('i*')))
0020 0020 0080 1000
↓
0020 0020 0300 6000
事前にSNDCTL_DSP_GETBLKSIZEを実行すると、fragmentサイズとして55hが返ってくるのだが、なぜかその後のfragmentサイズは6倍(80h->300h)になっている……ワケワカラン。まぁ、鳴ったからいいけど。当然ながら、この経路でALSAを使う場合、デバイスは専有されるので複数起動することはできない。
$ ./melod
./melod:26:in `initialize': Device or resource busy @ rb_sysopen - /dev/dsp1 (Errno::EBUSY)
しかし、なにより驚いたのは、padspの実体がシェルスクリプトになっていたことだ。以前はバイナリだったんだがな。