Main Page       Index


dulcimer.lsp


 dulcimer.lsp
 Version 1.00   01 February 2005
 Author  Steven Jones

 Contact jones57@swbell.net include the word "nyquist" in subject line  

 The contents of this file are released under the terms of the GNU General
 Public License. See the file LICENSE.txt

 Defines dulcimer instrument with "Aeolian harp reverb". By default the
 instrument uses a 12 note just scale in C. The sound is composed of three
 components; FM pluck sound, Karplus-Strong pluck sound and Aeolian reverb.


function

dulcimer:pluck

 (dulcimer:pluck pindex dur [:vel][:rc][:rm][:i][:mix])
 The primary sound is composed of two "pluck" components; FM and
 Karplus-Strong.
 
 pindex - integer. MIDI key number.

 dur    - flonum. Pluck decay time

 :vel   - integer. MIDI velocity controls modulation index and relative mix 
          of FM and Karplus-Strong components. At velocities above 63 the 
          two components have approximately equal amplitude. With lower 
          velocities the Karplus-Strong component drops out and the FM 
          component becomes less bright. Default 64

 :rc    - flonum. Relative FM carrier frequency, default 1.000

 :rm    - flonum. Relative FM modulation frequency, default 1.001

 :i     - flonum. FM modulation index. The actual index is modified by 
          velocity, default 4.00.

 :mix   - flonum. Relative mix between FM and Karplus-Strong components.
          0 <= mix <= 1. If specified mix overrides the velocity derived
          mix, default nil.

 return - sound.


function

dulcimer:aeolian

 (dulcimer:aeolian pindex dur [:vel][:rc][:rm][:i][:attack][:decay])
 The Aeolian reverb component of Dulcimer. See aeolus.lsp

 pindex  - integer.
 dur     - flonum.
 :vel    - integer.
 :rc     - flonum.
 :rm     - flonum.
 :i      - flonum.
 :attack - flonum.
 :decay  - flonum.
 return  - sound.


function

dulcimer:voice

 (dulcimer:voice pindex dur [keywords...])
 
 pindex   - integer.
 dur      - flonum.
 :vel     - integer. 
 :mix     - flonum. Relative mix of FM and Karplus-Strong components.
 :rc      - flonum.
 :rm      - flonum.
 :i       - flonum.
 :attack  - flonum.
 :decay   - flonum.
 :aeo     - integer. MIDI Amplitude of Aeolian reverb  0<= aeo < 128
 return   - sound


wrapper

dulcimer

 (dulcimer plist dur [keywords...])
 A dulcimer instrument with just intonation and Aeolian Harp reverb.  The
 intonation is a 12 note just scale in C. The sound is composed of three
 components; FM pluck, Karplus-Strong pluck and Aeolian reverb

 plist   - list or integer. MIDI key-number(s) to be played. Be aware the 
           dulcimer is demanding computation wise, long list of notes
           require long rendering times.

 dur     - flonum. Duration in seconds. The harp continues for decay 
           seconds after dur.

 :vel    - integer. MIDI velocity controls amplitude, brightness and relative 
           mix of FM and Karplus-Strong components, default 64.

 :pos    - flonum or sound. Pan position, default 0.5

 :arpeg  - flonum. Arpeggio time, default 0

 :rc     - flonum. Relative FM carrier frequency. The rc argument applies to 
           both the FM pluck and Aeolian components. Default 1.000

 :rm     - flonum. Relative FM modulator frequency. The rm argument applies 
           to both the FM pluck and Aeolian components. Default 1.001

 :i      - flonum. FM modulation index applies to both FM pluck and Aeolian 
           components. Default ?

 :mix    - flonum. Relative mix of FM and Karplus-Strong components.
           0 <= mix <= 1. If specified mix overrides velocity derived mix.

 :attack - flonum. Base line attack time of Aeolian reverb, default 0.050
 
 :decay  - flonum. Base line decay time of Aeolian reverb, default 1.50

 :aeo    - integer. MIDI controller of Aeolian reverb. Default 64

 :fc     - flonum. Filter resonance in Hertz, default 750.

 :q      - flonum. Filter q, 0<= q <= 1, default 0.75.

 return  - sound vector.


wrapper

pdulcimer

 (pdulcimer plist dur [keywords...])
 Version of duclimer without Aeolian reverb. 


View the Sourcecode :



;; dulcimer.lsp
;; Version 1.00   01 February 2005
;; Author  Steven Jones
;;
;; Contact jones57@swbell.net include the word "nyquist" in subject line  
;;
;; The contents of this file are released under the terms of the GNU General
;; Public License. See the file LICENSE.txt
;;
;; Defines dulcimer instrument with "Aeolian harp reverb". By default the
;; instrument uses a 12 note just scale in C. The sound is composed of three
;; components; FM pluck sound, Karplus-Strong pluck sound and Aeolian reverb.

(require 'aeolus)
(require 'map)
(require 'map-vel6)
(require 'definst)
(provide 'dulcimer)
(current-file "dulcimer")


;; Maps pluck FM index as function of velocity
;;

(setf dulcimer:*vel-fmindex-map* (map:linear 0.75 4.00))


;; Maps pluck component mix (FM vs Karplus-Strong) as function of velocity
;; For velocities above 63 the relative mix is constant
;; For velocities less then 63 Karplus-Strong component is reduced
;;

(setf dulcimer:*vel-mix-map* (send map:discrete :new 128 :fillfn #'(lambda (n) 0.5)))
(do ((i 0 (+ i 1))(val 0 (+ val (/ 1.0 128))))
    ((>= i 64))
  (send dulcimer:*vel-mix-map* :set i val))


;; Instrument amplitude in db as function of velocity
;;

(setf dulcimer:*vel-db-map* map:*vel6*)


;; Amplitude of aeolian component in db as function of MIDI controller.
;;

(setf dulcimer:*aeolian-db-map* (map:quad -48 +6))


;; Defines the primary scale
;;

(setf dulcimer:*scale* (vector 1.000  ;unison
			       1.067  ;min 2nd
			       1.125  ;2nd
			       1.200  ;min 3rd
			       1.250  ;maj 3rd
			       1.333  ;4th
			       1.400  ;aug 4th/dim 5th
			       1.500  ;5th
			       1.600  ;aug 5th
			       1.667  ;6th
			       1.800  ;min 7th
			       1.875  ;7th
			       ))


;; Defines the Aeolian scale. 
;;

(setf dulcimer:*aeolian-scale* (vector 
				1.000  ;unison
				1.067  ;min 2nd
				1.125  ;2nd
				1.200  ;min 3rd
				1.250  ;maj 3rd
				1.333  ;4th
				1.400  ;aug 4th/dim 5th
				1.500  ;5th
				1.600  ;aug 5th
				1.667  ;6th
				1.800  ;min 7th
				1.875  ;7th
				))


;; Aeolian harmonics list
;;

(setf dulcimer:*aeolian-plist* '((0.500  0.800)
				 (0.750  0.600)
				 (1.000  1.000)
				 (1.200  0.300)
				 (1.250  0.400)
				 (1.333  0.700)
				 (1.500  0.800)
				 (1.667  0.400)
				 (1.875  0.100)
				 (2.000  0.500)
				 (3.000  0.500)))


;; Build the primary pitch map
;;

(setf dulcimer:*pitch-map* (send map:discrete :new 128))
(setf dulcimer:*ref-frq* (/ (step-to-hz C0) 2.0))
(let ((rindex 0)
      (frq dulcimer:*ref-frq*))
  (do ((pindex 0 (+ pindex 1)))
      ((> pindex 127))
    (send dulcimer:*pitch-map* :set pindex (hz-to-step (* frq (aref dulcimer:*scale* rindex))))
    (if (< rindex (- (length dulcimer:*scale*) 1))
	(setq rindex (+ 1 rindex))
      (setq rindex 0
	    frq (* 2 frq)))))


;; Build the Aeolian harp
;;       

(setf dulcimer:*aeolian-ref-pitch* C4)
(setf dulcimer:*aeolian-octaves* 2)
(setf dulcimer:*aeolian* (send aeolus:class :new))
(let (frq)
  (dotimes (oindex dulcimer:*aeolian-octaves*)
    (setf frq (* (step-to-hz dulcimer:*aeolian-ref-pitch*)(expt 2.0 oindex)))
    (dotimes (rindex (length dulcimer:*aeolian-scale*))
      (send dulcimer:*aeolian* :string (* frq (aref dulcimer:*aeolian-scale* rindex)) :plist dulcimer:*aeolian-plist*))))
(send dulcimer:*aeolian* :key ':i       3.000 (map:linear 0.10 1.00 0 1))
(send dulcimer:*aeolian* :key ':attack  0.050 (map:linear 25.0 1.00 0 1))
(send dulcimer:*aeolian* :key ':decay   1.500 (map:linear 0.25 1.00 0 1))
(send dulcimer:*aeolian* :key ':rc      1.000 (map:constant 1))
(send dulcimer:*aeolian* :key ':rm      1.010 (map:constant 1))


;; @doc function dulcimer:pluck
;; (dulcimer:pluck pindex dur [:vel][:rc][:rm][:i][:mix])
;; The primary sound is composed of two "pluck" components; FM and
;; Karplus-Strong.
;; 
;; pindex - integer. MIDI key number.
;;
;; dur    - flonum. Pluck decay time
;;
;; :vel   - integer. MIDI velocity controls modulation index and relative mix 
;;          of FM and Karplus-Strong components. At velocities above 63 the 
;;          two components have approximately equal amplitude. With lower 
;;          velocities the Karplus-Strong component drops out and the FM 
;;          component becomes less bright. Default 64
;;
;; :rc    - flonum. Relative FM carrier frequency, default 1.000
;;
;; :rm    - flonum. Relative FM modulation frequency, default 1.001
;;
;; :i     - flonum. FM modulation index. The actual index is modified by 
;;          velocity, default 4.00.
;;
;; :mix   - flonum. Relative mix between FM and Karplus-Strong components.
;;          0 <= mix <= 1. If specified mix overrides the velocity derived
;;          mix, default nil.
;;
;; return - sound.
;;

(defun dulcimer:pluck (pindex dur &key vel rc rm i mix)
  (let* ((hz (step-to-hz (send dulcimer:*pitch-map* :get (truncate pindex))))
	 (vel (or vel 74))
	 (chz (* hz (or rc 1.000)))
	 (mhz (* hz (or rm 1.010)))
	 (mamp (* chz (send dulcimer:*vel-fmindex-map* :get vel)(or i 4.00)))
	 (mix (min (max (or mix (send dulcimer:*vel-mix-map* :get vel)) 0.00) 1.00))
	 (envsig (percussion dur))
	 )
    (sum
     (scale mix (pluck (hz-to-step hz) dur))
     (scale (- 1 mix) (mult (fmosc (hz-to-step chz)
			     (mult (osc (hz-to-step mhz) dur)
				   (scale mamp envsig)))
		      envsig)))))


;; @doc function dulcimer:aeolian
;; (dulcimer:aeolian pindex dur [:vel][:rc][:rm][:i][:attack][:decay])
;; The Aeolian reverb component of Dulcimer. See aeolus.lsp
;;
;; pindex  - integer.
;; dur     - flonum.
;; :vel    - integer.
;; :rc     - flonum.
;; :rm     - flonum.
;; :i      - flonum.
;; :attack - flonum.
;; :decay  - flonum.
;; return  - sound.
;;

(defun dulcimer:aeolian (pindex dur &rest args)
  (send dulcimer:*aeolian* :render (step-to-hz (send dulcimer:*pitch-map* :get pindex)) dur (append (->list args)(list ':rc 2))))


;; @doc function dulcimer:voice
;; (dulcimer:voice pindex dur [keywords...])
;; 
;; pindex   - integer.
;; dur      - flonum.
;; :vel     - integer. 
;; :mix     - flonum. Relative mix of FM and Karplus-Strong components.
;; :rc      - flonum.
;; :rm      - flonum.
;; :i       - flonum.
;; :attack  - flonum.
;; :decay   - flonum.
;; :aeo     - integer. MIDI Amplitude of Aeolian reverb  0<= aeo < 128
;; return   - sound
;;

(defun dulcimer:voice (pindex dur &rest args)
  (let ((amix (send dulcimer:*aeolian-db-map* :get (get-keyword-value ':aeo args 64)))
	(arglist (append (list pindex dur) args)))
    (sum (apply #'dulcimer:pluck arglist)
	 (scale-db amix (apply #'dulcimer:aeolian arglist))
	 )))
    


;; Provides global filter for dulcimer.
;;

(defun  dulcimer:eq (sig frq q)
  (multichan-expand #'bandpass2 sig frq q))


;; @doc wrapper dulcimer
;; (dulcimer plist dur [keywords...])
;; A dulcimer instrument with just intonation and Aeolian Harp reverb.  The
;; intonation is a 12 note just scale in C. The sound is composed of three
;; components; FM pluck, Karplus-Strong pluck and Aeolian reverb
;;
;; plist   - list or integer. MIDI key-number(s) to be played. Be aware the 
;;           dulcimer is demanding computation wise, long list of notes
;;           require long rendering times.
;;
;; dur     - flonum. Duration in seconds. The harp continues for decay 
;;           seconds after dur.
;;
;; :vel    - integer. MIDI velocity controls amplitude, brightness and relative 
;;           mix of FM and Karplus-Strong components, default 64.
;;
;; :pos    - flonum or sound. Pan position, default 0.5
;;
;; :arpeg  - flonum. Arpeggio time, default 0
;;
;; :rc     - flonum. Relative FM carrier frequency. The rc argument applies to 
;;           both the FM pluck and Aeolian components. Default 1.000
;;
;; :rm     - flonum. Relative FM modulator frequency. The rm argument applies 
;;           to both the FM pluck and Aeolian components. Default 1.001
;;
;; :i      - flonum. FM modulation index applies to both FM pluck and Aeolian 
;;           components. Default ?
;;
;; :mix    - flonum. Relative mix of FM and Karplus-Strong components.
;;           0 <= mix <= 1. If specified mix overrides velocity derived mix.
;;
;; :attack - flonum. Base line attack time of Aeolian reverb, default 0.050
;; 
;; :decay  - flonum. Base line decay time of Aeolian reverb, default 1.50
;;
;; :aeo    - integer. MIDI controller of Aeolian reverb. Default 64
;;
;; :fc     - flonum. Filter resonance in Hertz, default 750.
;;
;; :q      - flonum. Filter q, 0<= q <= 1, default 0.75.
;;
;; return  - sound vector.
;;

(defwrapper dulcimer
  #'dulcimer:voice
  #'(lambda (sig args)
      (scale-db (send dulcimer:*vel-db-map* :get (get-keyword-value ':vel args 64))
		(dulcimer:eq sig
			     (get-keyword-value ':fc args 750)
			     (get-keyword-value ':q args 0.75)
			     ))))


;; @doc wrapper pdulcimer
;; (pdulcimer plist dur [keywords...])
;; Version of duclimer without Aeolian reverb. 
;; 

(defwrapper pdulcimer
  #'dulcimer:pluck
  #'(lambda (sig args)
      (scale-db (send dulcimer:*vel-db-map* :get (get-keyword-value ':vel args 64))
		sig)))


Main Page       Index