Attached.

     - Tommi

--
Kotisivu / Homepage: http://www.iki.fi/tohoyn/
Sähköposti / E-Mail: [email protected]
GPG-sormenjälki / GPG fingerprint:
55F4 2477 7155 3528 5CB2 2B7A BB86 1FDE 4046 0F83
FT, Debian-ylläpitäjä / PhD, Debian Maintainer
;; test-render-envelope.scm
;;
;; Integration test for guile-fluidsynth:
;; - loads a SoundFont
;; - renders audio offline
;; - verifies note attack produces signal
;; - verifies note-off causes decay
;; - verifies polyphony accounting
;;
;; This is intentionally not a trivial smoke test.

(use-modules
  (srfi srfi-64)
  (ice-9 binary-ports)
  (nyacc foreign cdata)
  (f-synth)
  (f-synth ffi settings)
  (f-synth ffi synth))

(test-begin "fluidsynth-render-envelope")

(define SAMPLE-RATE 44100)
(define BLOCK-SIZE  64)

;; Utility ------------------------------------------------------------

(define (buffer-rms buffer)
  (let* ((n (f32vector-length buffer))
         (sum 0.0))
    (do ((i 0 (+ i 1)))
        ((>= i n) (/ sum n))
      (let ((x (f32vector-ref buffer i)))
        (set! sum (+ sum (* x x)))))
    (sqrt (/ sum n))))

(define ctype-float (cbase 'float))

(define (render-block synth frames)
  (let ((left  (make-cdata (carray ctype-float frames)))
        (right (make-cdata (carray ctype-float frames))))
    ;; Offline rendering into buffers
    (fluid_synth_write_float synth
                             frames
                             left 0 1
                             right 0 1)
    (values left right)))

(define (render-rms synth frames)
  (call-with-values
      (lambda () (render-block synth frames))
    (lambda (l r)
      (/ (+ (buffer-rms (cdata-ref l))
            (buffer-rms (cdata-ref r)))
         2.0))))

;; Setup --------------------------------------------------------------

(define synth (make <synth>))

(define settings (!settings synth))

(fluid_settings_setnum settings "synth.sample-rate" SAMPLE-RATE)
(fluid_settings_setint settings "synth.polyphony" 16)

;; Disable realtime drivers for deterministic CI behavior
(fluid_settings_setstr settings "audio.driver" "file")

;; You should replace this path with a test fixture.
(define sfid
  (sfload synth
          "example.sf2"
          1))

(test-assert "soundfont loaded"
  (>= sfid 0))

(program-select synth
                0       ; channel
                0       ; bank
                0       ; preset
                sfid)

;; Attack test --------------------------------------------------------

(noteon synth 0 60 100)

(define attack-rms
  (render-rms (!synth synth) 4096))

(test-assert "note-on produces audible signal"
  (> attack-rms 0.001))

;; Polyphony test -----------------------------------------------------

(noteon synth 0 61 100)
(noteon synth 0 62 100)

(test-assert "polyphony increases after multiple notes"
  (>= (fluid_synth_get_active_voice_count (!synth synth)) 3))

;; Release test -------------------------------------------------------

(noteoff synth 0 60)
(noteoff synth 0 61)
(noteoff synth 0 62)

;; Render enough frames for release envelope to decay
(define release-rms
  (begin
    (render-rms (!synth synth) (* SAMPLE-RATE 2))))

(test-assert "signal decays after note-off"
  (< release-rms (* attack-rms 0.2)))

(test-end "fluidsynth-render-envelope")

Reply via email to