wrapperコードをコンパイル
swigの生成してくれたruby_interface_wrap.cc, ruby_interface_wrap.hをコンパイルしてオブジェクトを作成する。これもsconsして出てきたコンパイルオプションで実施。これも山ほどwarningが出る。
g++ -o interfaces/ruby_interface_wrap.os -c -fexceptions -Wall -O3 -march=pentium3 \ -fomit-frame-pointer -ffast-math -ftree-vectorize -DLINUX -DPIPES -fPIC \ -DHAVE_LIBSNDFILE=1016 -DHAVE_FLTK -DUSE_DOUBLE -DHAVE_SOCKETS -DHAVE_FCNTL_H \ -DHAVE_UNISTD_H -DHAVE_STDINT_H -DHAVE_SYS_TIME_H -DHAVE_SYS_TYPES_H -DHAVE_TERMIOS_H \ -DHAVE_SOCKETS -DHAVE_DIRENT_H -D__BUILDING_LIBCSOUND -D_CSOUND_RELEASE_ \ -DCS_DEFAULT_PLUGINDIR=\"/usr/local/lib/csound/plugins64\" -I. -IH \ -I/usr/java/jdk1.6.0_02/include -I/usr/local/include -I/usr/include -I/usr/X11R6/include \ -Iinterfaces -I/usr/lib/ruby/1.8/i386-linux/ interfaces/ruby_interface_wrap.cc
ruby_interface_wrap.ccで「dereferencing type-punned pointer will break strict-aliasing rules」という警告が出まくるがとりあえず無視。
ライブラリを作成
これもsconsの結果をほとんど持ってこようと思ったが-o _csdとなっていたものは明らかにpython用のライブラリと名前が被るのでrcsoundにした*1
g++ -o rcsound.so -Wl,-Bdynamic -Wl,-rpath-link,. -shared interfaces/ruby_interface_wrap.os \ -L/usr/local/lib -L/usr/lib -L/usr/lib/ruby/1.8/i386-linux/ -L. -L. -L/usr/local/lib -L. \ -L. -lruby -lstdc++ -lutil -lsndfile -ldl -lm -lpthread -csnd
テストコード
リアルタイム動作をさせることを念頭に、interface/test.pyやinterface/test.luaを斜めに見て作成。サンプルでは-oとdacを分けて引数として与えていたがひとつにしても動く。hw:0,0等の値は各環境に依存する。
#!/bin/env /usr/bin/ruby require 'rcsound' # automatically Init_rcsoundが動く csound=Rcsound::Csound.new() csound.Compile('-d','-m0','-+rtaudio=alsa','-odac:hw:0,0', 'rt.csd') puts "compile END" while csound.PerformBuffer()==0 next end csound.Reset() #Rcsound::csoundDestroy(csound)
- テストコードのファイルを作るのは、interfaces配下ではなく、先ほどのrcsound.soと同じディレクトリに作成(特にrcsound.soをLD_LIBRARY_PATHのどこかにコピーしたのではない限り。つまりこの例だとソースを展開したディレクトリの最上位でした)。
- requireを行うとinit_XXXXXという関数が動くのが分かるXXXXXというのは作成したライブラリの名称でこれはruby_interface.iで定義したモジュール名と同一になるべき。例えば以下のようなエラーが出る。
./XXXXX.so: ./XXXXX.so: undefined symbol: Init_XXXXX - ./XXXXX.so (LoadError)
- 最終行でDestroyを行おうとしたらこの引数の中身はポインタが入るべきなので動かないけどOKだなーとか思っていたら、csoundDestoryというのはCの関数でC++のAPIではデストラクタから直接呼び出されていることがソースから判明。rubyでは呼ばなくていいのかな?ガベージコレクションの関係があるのみたいなので、それから悩むのかな?
csoundファイル
どこから持ってきたか忘れてしまいましたが、シンプルで結構好きな音だったのでとっといてあったもの(最初のファイル名はfilteredSawとあったような)。オプションが書かれているけどこれはどこまで有効なんだろうか後から考えると不明。
; ; generated by shell function ; <CsoundSynthesizer> <CsOptions> -d -m0 -+rtaudio=alsa -odac:hw:0,0 </CsOptions> <CsInstruments> sr = 44100 kr = 44100 ksmps = 1 nchnls = 2 instr 1 ilen = p3 ifrq = cpspch(p4) iamp = p5 i_filt_frq_start = p6 i_filt_frq_end = p7 kenv linen iamp,ilen/5,ilen,ilen/5 kpan phasor 1/ilen a1 oscil kenv,ifrq ,9 a2 oscil kenv,ifrq*0.999 ,9 a3 oscil kenv,ifrq*1.001 ,9 k_flt_freq line i_filt_frq_start,ilen,i_filt_frq_end a4=(a1+a2+a3)/3 aout reson a4,k_flt_freq,100, 2 outs aout*kpan , aout*(1-kpan) endin </CsInstruments> <CsScore> f9 0 4096 10 1 .5 .333 .25 .2 .167 .1428 .125 .111 .1 .0909 .0833 .0769 .0714 .0667 .0625 ; SAW i1 0 10 8.04 14000 5000 500 i1 0 10 8.07 14000 5000 500 i1 0 10 8.11 14000 5000 500 i1 0 10 9.02 14000 5000 500 </CsScore> </CsoundSynthesizer>