-*- outline -*-

* Introduction

The C/XEN library `libsndins.so' provides the instrument FM-VIOLIN and
the reverberators JC-REVERB, NREV, and FREEVERB to use them in longer
notelists in Snd/Guile and Snd/Ruby.  They are not so fast as the
ffi-lisp versions, at least not on my machine, but they run much
faster than the Scheme or Ruby variants.  In addition I have added the
FCOMB example from sndscm.html which is used in freeverb.

The library is based on Bill Schottstaedt's `xen' and `sndlib'
libraries and the Snd editor itself.  Thank you for these great music
programs and libraries!

* XEN-Instruments

The following generator and instruments are accessible from Guile or
Ruby.

** make-fcomb, fcomb?, and fcomb

These are the examples from sndscm.html.

*** (make-fcomb (:scaler 0.0) (:size 1) (:a0 0.0) (:a1 0.0))
*** make_fcomb(:scaler, 0.0, :size, 1, :a0, 0.0, :a1, 0.0)

Returns a new fcomb generator.

*** (fcomb? gen)
*** fcomb?(gen)

Tests if gen is an fcomb generator.

*** (fcomb gen (input 0.0))
*** fcomb(gen[, input = 0.0])

Returns the next value of the fcomb generator gen.

*** (mus-describe gen)
*** gen.to_s

Shows the inspect string of the fcomb gen.

*** (mus-length gen)
*** gen.length

Shows length of delay line.

*** (mus-scaler gen) (set! (mus-scaler gen) val)
*** gen.scaler       set_mus_scaler(gen, val)

Shows the scaler value, settable.

** fm-violin

Keyword options for fm-violin (v.ins, v.scm, examp.rb).

*** (:startime 0.0)			    :startime, 0.0,
*** (:duration 1.0)			    :duration, 1.0,
*** (:frequency 440.0)			    :frequency, 440.0,
*** (:amplitude 0.5)			    :amplitude, 0.5,
*** (:fm-index 1.0)			    :fm_index, 1.0,
*** (:amp-env '(0 0 25 1 75 1 100 0))	    :amp_env, [0, 0, 25, 1, 75, 1, 100, 0],
*** (:periodic-vibrato-rate 5.0)	    :periodic_vibrato_rate, 5.0,
*** (:periodic-vibrato-amplitude 0.0025)    :periodic_vibrato_amplitude, 0.0025,
*** (:random-vibrato-rate 16.0)		    :random_vibrato_rate, 16.0,
*** (:random-vibrato-amplitude 0.005)	    :random_vibrato_amplitude, 0.005,
*** (:noise-freq 1000.0)		    :noise_freq, 1000.0,
*** (:noise-amount 0.0)			    :noise_amount, 0.0,
*** (:ind-noise-freq 10.0)		    :ind_noise_freq, 10.0,
*** (:ind-noise-amount 0.0)		    :ind_noise_amount, 0.0,
*** (:amp-noise-freq 20.0)		    :amp_noise_freq, 20.0,
*** (:amp-noise-amount 0.0)		    :amp_noise_amount, 0.0,
*** (:gliss-env '(0 0 100 0))		    :gliss_env, [0, 0, 100, 0],
*** (:glissando-amount 0.0)		    :glissando_amount, 0.0,
*** (:fm1-env '(0 1 25 0.4 75 0.6 100 0))   :fm1_env, [0, 1, 25, 0.4, 75, 0.6, 100, 0],
*** (:fm2-env '(0 1 25 0.4 75 0.6 100 0))   :fm2_env, [0, 1, 25, 0.4, 75, 0.6, 100, 0],
*** (:fm3-env '(0 1 25 0.4 75 0.6 100 0))   :fm3_env, [0, 1, 25, 0.4, 75, 0.6, 100, 0],
*** (:fm1-rat 1.0)			    :fm1_rat 1.0,
*** (:fm2-rat 3.0)			    :fm2_rat 3.0,
*** (:fm3-rat 4.0)			    :fm3_rat 4.0,
*** (:fm1-index 0.0)			    :fm1_index, 0.0,
*** (:fm2-index 0.0)			    :fm2_index, 0.0,
*** (:fm3-index 0.0)			    :fm3_index, 0.0,
*** (:base 1.0)				    :base, 1.0,
*** (:degree 0.0)			    :degree, 0.0,
*** (:distance 1.0)			    :distance, 1.0,
*** (:reverb-amount 0.01)		    :reverb_amount, 0.01,
*** (:index-type 1 [0 = cello, 1 = violin]) :index_type, 1, [0 = cello, 1 = violin]
*** (:no-waveshaping #f)                    :no_waveshaping, false

** jc-reverb

Keyword options for jc-reverb (jcrev.ins, jcrev.scm, examp.rb).

*** (:startime 0.0)           		    :startime, 0.0,
*** (:duration #f)	      		    :duration, nil,
*** (:low-pass #f)	      		    :low_pass, false,
*** (:volume 1.0) 	      		    :volume, 1.0,
*** (:double #f)  	      		    :double, false,
*** (:delay1 0.013)	      		    :delay1, 0.013,
*** (:delay2 0.011)	      		    :delay2, 0.011,
*** (:delay3 0.015)	      		    :delay3, 0.015,
*** (:delay4 0.017)	      		    :delay4, 0.017,
*** (:amp-env #f) 	      		    :amp_env, nil,

If more than one reverb channel exists, the values from them are
collected together before computing the result.

** nrev

Keyword options for nrev (nrev.ins, clm-ins.scm, clm-ins.rb).

*** (:startime 0.0)           		    :startime, 0.0,
*** (:duration #f)	      		    :duration, nil,
*** (:reverb-factor 1.09)     		    :reverb_factor, 1.09,
*** (:lp-coeff 0.7)	      		    :lp_coeff, 0.7,
*** (:lp-out-coeff 0.85)      		    :lp_out_coeff, 0.85,
*** (:output-scale 1.0)	      		    :output_scale, 1.0,
*** (:amp-env '(0 1 1 1))     		    :amp-env, [0, 1, 1, 1],
*** (:volume 1.0)	      		    :volume, 1.0,

If more than one reverb channel exists, the values from them are
collected together before computing the result.

** freeverb

Keyword options for freeverb (freeverb.ins, freeverb.scm, freeverb.rb).

*** (:startime 0.0)	      		    :startime, 0.0,
*** (:duration #f)	      		    :duration, nil,
*** (:room-decay 0.5)	      		    :room_decay, 0.5,
*** (:damping 0.5)	      		    :damping, 0.5,
*** (:global 0.3)	      		    :global, 0.3,
*** (:predelay 0.03)	      		    :predelay, 0.03,
*** (:output-gain 1.0)	      		    :output_gain, 1.0,
*** (:output-mixer #f)	      		    :output_mixer, nil,
*** (:scale-room-decay 0.28)  		    :scale_room_decay, 0.28,
*** (:offset-room-decay 0.7)  		    :offset_room_decay, 0.7,
*** (:combtuning                            :combtuning,
***  '(1116 1188 1277 1356 1422 1491 1557 1617))
***                                          [1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617],
*** (:allpasstuning '(556 441 341 225))     :allpasstuning, [556, 441, 341, 225]
*** (:scale-damping 0.4)      		    :scale_damping, 0.4,
*** (:stereo-spread 23.0)     		    :stereo_spread, 23.0,

Works with one reverb channel or the same number of reverb channels
like output channels.

* C-Instruments

The following generator and instruments are accessible from C (or
Gforth).

** mus_any *mus_make_fcomb(Float scaler, int size, Float a0, Float a1);

** int mus_fcomb_p(mus_any *ptr);

** Float mus_fcomb(mus_any *ptr, Float input, Float ignored);

** Float mus_fcomb_1(mus_any *ptr, Float input);

** off_t ins_fm_violin(Float start, Float dur, Float freq, Float amp, Float fm_index,
	    Float *amp_env, int amp_len,
	    Float periodic_vibrato_rate, Float periodic_vibrato_amp,
	    Float random_vibrato_rate, Float random_vibrato_amp,
	    Float noise_freq, Float noise_amount,
	    Float ind_noise_freq, Float ind_noise_amount,
	    Float amp_noise_freq, Float amp_noise_amount,
	    Float *gliss_env, int gliss_len, Float gliss_amount,
	    Float *fm1_env, int fm1_len,
	    Float *fm2_env, int fm2_len,
	    Float *fm3_env, int fm3_len,
	    Float fm1_rat, Float fm2_rat, Float fm3_rat,
	    Float fm1_index, Float fm2_index, Float fm3_index,
	    Float base, Float degree, Float distance,
	    Float reverb_amount, int index_type, bool no_waveshaping,
	    mus_any *out, mus_any *rev, mus_interp_t mode);

** off_t ins_jc_reverb(Float start, Float dur, Float volume, bool low_pass, bool doubled,
	    Float delay1, Float delay2, Float delay3, Float delay4,
	    Float *amp_env, int amp_len, mus_any *out, mus_any *rev);

** off_t ins_nrev(Float start, Float dur, Float reverb_factor, Float lp_coeff,
	    Float lp_out_coeff, Float output_scale, Float volume,
	    Float *amp_env, int amp_len, mus_any *out, mus_any *rev);

** off_t ins_freeverb(Float start, Float dur, Float room_decay, Float damping, Float global,
	    Float predelay, Float output_gain, Float scale_room_decay,
	    Float offset_room_decay, Float scale_damping, Float stereo_spread,
	    int *combtuning, int comb_len, int *allpasstuning, int all_len,
	    mus_any *output_mixer, mus_any *out, mus_any *rev);

* Installation

After running `configure' and `make' in the normal sndlib directory
you can cd to sndins and run

    make
    make install (as root)

The library path should be in your LD_LIBRARY_PATH, e.g. if you have
installed the library in /usr/gnu/lib.:

	(csh) setenv LD_LIBRARY_PATH /usr/gnu/lib:$LD_LIBRARY_PATH

	(sh)  LD_LIBRARY_PATH=/usr/gnu/lib:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH

In Snd/Guile you can add the line

	(load-extension "libsndins" "init_sndins")

in your ~/.snd init file or wherever you need it if the library is
installed in a proper directory.

I set symlinks from libsndlib.so and libsndins.so to the ruby library
path, i.e.

ln -s $(prefix)/lib/libsndlib.so $(prefix)/lib/ruby/site_ruby/1.9/i686-freebsd5.1/sndlib.so
ln -s $(prefix)/lib/libsndins.so $(prefix)/lib/ruby/site_ruby/1.9/i686-freebsd5.1/sndins.so

So in Snd/Ruby one can add the line

      	require "sndlib"
	require "sndins"

in ~/.snd init.

* Samples

The four scripts in sndins/samples may run outside in a shell and
inside Snd too.  If you have compiled and installed the Guile sndlib
and sndins libraries, you can type

	./agn.scm [ outfile.clm ]
	./fmviolin.scm [ -s ]

The default outfile is agn.clm (or agn.rbm in Ruby).  A different
outfile name should end in *.clm (or in *.rbm). The option -s can be
everything, its only meaning is to choose the (short-example), without
an option (long-example) is chosen.

If you have compiled and installed the Ruby sndlib and sndins
libraries, you can type

        ./agn.rb [ outfile.rbm ]
        ./fmviolin.rb [ -s ]

The options are like above.

You can set some variables in fmviolin.* to change the channels,
srate, reverb function etc.

** agn.scm, agn.rb

Translation of clm-2/clm-example.clm into Guile and Ruby as a test
case.

** fmviolin.scm, fmviolin.rb

Translation of clm-2/fmviolin.clm into Guile and Ruby as a test case.

** ws_s.scm

Simple with-sound for running the Guile examples outside Snd.

* Emacs Fontifying for C-, Scheme-, SND-Guile-, and Lisp-Mode

The following font variables and functions are set in my .emacs file.

(setq c-font-lock-extra-types
      (append '("Float" "XEN" "mus_any" "mus_xen") c-font-lock-extra-types))

(font-lock-add-keywords
 'scheme-mode
 '(("(\\(definstrument\\|run\\)\\>\\s-*(?\\(\\sw+\\)?"
    (1 font-lock-keyword-face)
    (2 (cond ((match-beginning 1) font-lock-function-name-face)
	     ((match-beginning 2) font-lock-variable-name-face)
	     (t font-lock-type-face))
       nil t))))

(font-lock-add-keywords
 'snd-guile-mode
 '(("(\\(definstrument\\|run\\)\\>\\s-*(?\\(\\sw+\\)?"
    (1 font-lock-keyword-face)
    (2 (cond ((match-beginning 1) font-lock-function-name-face)
	     ((match-beginning 2) font-lock-variable-name-face)
	     (t font-lock-type-face))
       nil t))))

(font-lock-add-keywords
 'lisp-mode
 '(("(\\(def[p]?instrument\\|def-optkey-fun\\|run\\|let\\*?\\)\\>\\s-*(?\\(\\sw+\\)?"
    (1 font-lock-keyword-face)
    (2 (cond ((match-beginning 1) font-lock-function-name-face)
	     ((match-beginning 2) font-lock-variable-name-face)
	     (t font-lock-type-face))
       nil t))))

* README ends here
