Play SoundFonts with FluidSynth |
In the contrib/cl-fluidsynth
directory, there is a wrapper for
FluidSynth SoundFont synthesizer.
The following example shows how to use it with Incudine:
(in-package :scratch)
SCRATCH> (require :incudine-fluidsynth)
(defvar *fluid-settings* (fluidsynth:new-settings
`(("synth.polyphony" 128)
("synth.sample-rate" ,*sample-rate*)
("audio.sample-format" "float"))))
(defvar *synth* (fluidsynth:new *fluid-settings*))
(dsp! fluid-test ((synth fluidsynth:synth))
(with ((len (block-size))
(left (make-f32-array len))
(right (make-f32-array len)))
(fluidsynth:write-float synth len left 0 1 right 0 1)
(foreach-frame
(out (f32-ref left current-frame)
(f32-ref right current-frame)))))
SCRATCH> (fluidsynth:sfload *synth* "/usr/share/sounds/sf2/FluidR3_GM.sf2" 1)
SCRATCH> (setf (fluidsynth:setting *fluid-settings* "synth.gain") 0.5)
SCRATCH> (defvar *midiin* (pm:open (pm:get-default-input-device-id)))
SCRATCH> (recv-start *midiin*)
(defvar *fluid-resp*
(make-responder *midiin*
(lambda (st d1 d2)
(let ((ch (logand st #xF)))
(cond ((midi-note-on-p st)
(fluidsynth:noteon *synth* ch d1 d2))
((midi-note-off-p st)
(fluidsynth:noteoff *synth* ch d1))
((midi-program-p st)
(fluidsynth:program-change *synth* ch d1)))))))
SCRATCH> (set-rt-block-size 64)
SCRATCH> (rt-start)
SCRATCH> (fluid-test *synth*)
(defvar *tun*
(make-tuning
:notes '(2187/2048 9/8 32/27 81/64 4/3 729/512 3/2 6561/4096 27/16 16/9
243/128 2/1)
:description "12-tone Pythagorean scale"))
;; The first argument is a INCUDINE:TUNING, a list of notes
;; or a scl file.
SCRATCH> (set-fluidsynth-tuning *tun* *synth* 0 0)
SCRATCH> (fluidsynth:activate-tuning *synth* 0 0 0 t)
;;; Play with the new tuning...
SCRATCH> (set-fluidsynth-tuning
'(16/15 9/8 6/5 5/4 4/3 7/5 3/2 8/5 5/3 9/5 15/8 2/1) *synth* 0 0
:description "Basic JI with 7-limit tritone. Robert Rich: Geometry")
;; Vice versa, the frequencies of a INCUDINE:TUNING structure are
;; obtained from the FluidSynth tuning with BANK and PROG preset.
SCRATCH> (set-tuning-from-fluidsynth *tun* *synth* 0 0)
#<TUNING "Basic JI with 7-limit tritone. Robert Rich: Geometry">
;; Remember to update the intervals.
SCRATCH> (tuning-notes-from-data *tun* 60 72)
SCRATCH> (tuning-ratios *tun*)
#(1 16/15 9/8 6/5 5/4 4/3 7/5 3/2 8/5 5/3 9/5 15/8 2)
;; Another test with a scl file and...
SCRATCH> (set-fluidsynth-tuning "/tmp/carlos_beta.scl" *synth* 0 0)
;; ... it is the end
SCRATCH> (remove-all-responders)
SCRATCH> (recv-stop *midiin*)
SCRATCH> (free 0)
SCRATCH> (free *tun*)
SCRATCH> (fluidsynth:delete *synth*)
SCRATCH> (set-rt-block-size 1)
SCRATCH> (pm:terminate)