/examples/polysynth.scm

http://github.com/digego/extempore · Scheme · 127 lines · 75 code · 16 blank · 36 comment · 0 complexity · b83ae0d7eef582958223215049a0d862 MD5 · raw file

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;
  3. ;; This example shows how to define your own polyphonic synths
  4. ;;
  5. ;; You will first need to load and compile dsp_library.scm
  6. ;;
  7. ;; Then you're OK to go
  8. ;;
  9. ;; NOTE [at the moment compiling in a secondary thread is a little
  10. ;; [flakey. I'm working on this so in the mean time you'll
  11. ;; [just have to put up with the audio delays while compiling
  12. ;;
  13. ;; first let's play with the default synth defined in dsp_library
  14. ;; the default synth is called .... synth
  15. (define loop
  16. (lambda (beat offset dur)
  17. (play-note (*metro* beat) synth (+ offset (random '(60 62 63 65 67))) 80 2000)
  18. (callback (*metro* (+ beat (* dur .5))) 'loop
  19. (+ beat dur)
  20. offset
  21. dur)))
  22. (loop (*metro* 'get-beat 4) 0 1/2) ;; start one playing quavers
  23. (loop (*metro* 'get-beat 4) 12 1/3) ;; another playing triplets
  24. ;; to create our own instrument
  25. ;; we first need to compile a kernel function
  26. ;; this is the dsp code that gets rendered for each note
  27. ;; it must be a closure that returns a closure
  28. ;;
  29. ;; lets try a simple sawwave synth
  30. (definec my-saw-synth
  31. (lambda ()
  32. (let ((sawl (make-saw))
  33. (sawr (make-saw)))
  34. (lambda (time:double chan:double freq:double amp:double)
  35. (cond ((< chan 1.0)
  36. (sawl amp freq))
  37. ((< chan 2.0)
  38. (sawr amp freq))
  39. (else 0.0)))))))
  40. ;; now define an instrument to use my-additive-synth note kernel
  41. ;; with a default (i.e. pass through) default-effect
  42. (define-instrument my-synth my-saw-synth default-effect)
  43. ;; finally we need to add the new synth to the dsp routine
  44. ;; this is only slightly modified from the on in dsp_library
  45. ;; we just sum my-synth with synth and add some delay
  46. ;;
  47. ;; NOTE: then 100000 is extra memory for our
  48. ;; comb filters
  49. (definec dsp 1000000
  50. (let ((combl (make-comb (dtoi64 (* 0.25 *samplerate*))))
  51. (combr (make-comb (dtoi64 (* 0.33333333 *samplerate*)))))
  52. (lambda (in:double time:double chan:double dat:double*)
  53. (cond ((< chan 1.0)
  54. (combl (+ (* 1.0 (synth in time chan dat))
  55. (my-synth in time chan dat))))
  56. ((< chan 2.0)
  57. (combr (+ (* 1.0 (synth in time chan dat))
  58. (my-synth in time chan dat))))
  59. (else 0.0)))))
  60. ;;make my-synth active
  61. (my-synth.active 1)
  62. ;; now start a temporal recursion to play the new synth
  63. (define loop2
  64. (lambda (beat dur)
  65. (let ((pitch (random '(55 36 63 70 72))))
  66. (play-note (*metro* beat) my-synth pitch
  67. (if (= pitch 36) 105 95) 3000)
  68. (callback (*metro* (+ beat (* dur .5))) 'loop2
  69. (+ beat dur)
  70. dur))))
  71. (loop2 (*metro* 'get-beat 4) 1/3) ;; play our new synth
  72. ;; we can recompile my-saw-synth into something
  73. ;; else whenever we like
  74. ;; here's something more complex
  75. (definec my-saw-synth
  76. (let ((res 15.0)
  77. (cof 8000.0))
  78. (lambda ()
  79. (let ((sawl (make-saw))
  80. (sawl2 (make-saw))
  81. (modl (make-oscil 0.0))
  82. (lpfl (make-lpf))
  83. (lpflmod (make-oscil 0.0))
  84. (sawr (make-saw))
  85. (sawr2 (make-saw))
  86. (modr (make-oscil 0.0))
  87. (lpfr (make-lpf))
  88. (lpfrmod (make-oscil 0.0)))
  89. (lpfl.res res)
  90. (lpfr.res res)
  91. (lambda (time:double chan:double freq:double amp:double)
  92. (cond ((< chan 1.0)
  93. (lpfl (* amp (+ (sawl (* 1.0 amp) freq)
  94. (sawl2 amp (+ freq (modl 10.0 0.2)))))
  95. (+ cof (lpflmod freq 1.0))))
  96. ((< chan 2.0)
  97. (lpfr (* amp (+ (sawr (* 1.0 amp) freq)
  98. (sawr2 amp (+ freq (modr 50.0 0.5)))))
  99. (+ cof (lpfrmod 1400.0 2.0))))
  100. (else 0.0)))))))
  101. ;; some event level modification to my-synth
  102. ;; adjust res cof of my-additive-synth (dsp kernel)
  103. ;; adjust release of my-synth (instrument)
  104. (define res-sweep
  105. (lambda (beat dur)
  106. (my-synth.release (cosr 12000.0 11000.0 1/29))
  107. (my-saw-synth.res (cosr 40.0 30.0 1/37))
  108. (my-saw-synth.cof (cosr 5000.0 3500.0 1/19))
  109. (callback (*metro* (+ beat (* dur .5))) 'res-sweep
  110. (+ beat dur) dur)))
  111. (res-sweep (*metro* 'get-beat 4.0) 1/8)