Hello to somebody that would read this, and scuse me in advance for my english mistake.
I tried to make this plugin wich Switch on/off cadenced with the tempo, quite simple, but it can give some idea or help with the comment (i tried to comment as much as possible). There are some rise/fall time on switching.
I also add a wha effect (resonant filter sweeping on freq wich is controled by oscillator), but i guess that other guys have already made this better than me. But finally it works not so bad, for both mono and stereo.
PS: it’s important to put Wha effect stage before Switching and not after, because if not, you hear “pouic-pouic”, i guess it is because off the thing called the “side-effect”… maybe im not sure.
;nyquist plug-in
;version 3
;type process
;name "Switch on Tempo with Wha"
;action "Processing Switch on Tempo with Wha"
;info " Gate-like switched on tempo with Wha (Wha can be removed) \n"
;control bpm "Switch bpm (tempo)" real "bpm" 160 10 350
;control sterex "Stereo alternance (disabled for mono track)" real "" 0.5 0 1
;control pwmswtch "Sitch PWM (time on/off per periode)" real "" 0.7 0.5 0.9
;control widthwha "Width of sweep" real "" 3.5 2 4
;control bandfact "Resonant bandwidth factor" real "" 0.8 0.5 1
;control centerfreq "Center frequency of sweep" real "Hz" 632 200 3000
;control sweepspeed "Speed of sweep" real "Hz" 0.4 0.05 2
;control compgain "Attenuation/compensation gain" real "dB" -10 -30 7
;control whafact "Remove Wha effect (dry/wet)" real "" 1 0 1
; this function return duration of selection (stereo signal)
(defun timeselec (sign)
(setq lefts (aref sign 0)) ; aref function to get only one channel (here left=0)
(setq stoplist (snd-extent lefts 10000000 ) ) ; snd-extent to return duration in a list
(setq stopt (nth 1 stoplist ) ) ; extract duration from previous list
)
; this function return duration of selection (mono signal)
(defun timeselecmono (sign)
(setq stoplist (snd-extent sign 10000000 ) ) ; snd-extent to return duration in a list
(setq stopt (nth 1 stoplist ) ) ; extract duration from previous list
)
; this function generate a square wave in mono signal
; wich have duration of selection, and have freq and pwm set by user
(defun mksqare-mono (stoptime bpmset pwmset)
(setq demi-per (/ (/ 1 (/ bpmset 60)) 4)) ; half period
(setq nbpoint (/ stopt demi-per)) ; finally i didn't use it (number of pair in list)
(setq logidur (/ demi-per (/ stopt 20))) ; i had some problem with logic and real time
(setq logidur (/ logidur 20)) ; i don't have more explanation but it work
(setq time-per (/ stopt (* demi-per 2))) ; number of period
(setq rifa (/ logidur 10) ) ; rise and fall times are 1/10 period (rifa=risefall)
(setq pwmset (* (- pwmset 0.5) 2) ) ; convert pwm user value in an addition term
(setq count 0) ; set counter of while wich is below
(setq point1 (* logidur (float count)) )
(setq point2 (* logidur (+ (float count) (+ (float 1) pwmset)) ) ) ; setting x values (time axis)
(setq point3 (* logidur (+ count 2)) ) ; point2 is modulated according
; to pwm value
(setq point4 (+ point2 rifa )) ; rifa follow point2 modulation
(setq point5 (- point3 rifa ))
(setq pair1 (list point1 1)) ; set pair in some lists
(setq pair2 (list point2 1)) ; with x value, y is 0 or 1
(setq pair3 (list point4 0)) ; 4 pairs= 4 points a period
(setq pair4 (list point5 0))
(setq list3 (nconc pair1 pair2 pair3 pair4)) ; using nconc funtion to concatenate in single list
(while (< count (* (- time-per 1) 2)) ; while repeat the same as previously
; for the number of period (one loop is already done)
(setq count (+ count 2))
(setq point1 (* logidur (float count)) )
(setq point2 (* logidur (+ (float count) (+ (float 1) pwmset)) ) ) ; setting x values (time axis)
(setq point3 (* logidur (+ count 2)) ) ; point2 is modulated according
(setq point6 (+ point2 rifa) ) ; to pwm value
(setq point7 (- point3 rifa) ) ; rifa follow point2 modulation
(setq pair1 (list point1 1)) ; set pair in some lists
(setq pair2 (list point2 1)) ; with x value, y is 0 or 1
(setq pair3 (list point6 0)) ; 4 pairs= 4 points a period
(setq pair4 (list point7 0))
(setq list3 (nconc list3 pair1 pair2 pair3 pair4)) ; using nconc funtion to concatenate
; in a single list
)
(setq pwm1 (pwl-list list3)) ; pwl-list function generate
; the square wave with all points
) ; that are in the previous list
; this function generate a "half square" wave for left stereo signal
; wich have duration of selection, and have freq and pwm set by user
; the period is 2 time more long than mono version
; because one empty period is added for stereo a alternance
(defun mksqareleft (stoptime bpmset pwmset)
(setq demi-per (/ (/ 1 (/ bpmset 60)) 4)) ; half period
(setq nbpoint (/ stopt demi-per)) ; finally i didn't use it (number of pair in list)
(setq logidur (/ demi-per (/ stopt 20))) ; i had some problem with logic and real time
(setq logidur (/ logidur 20)) ; i don't have more explanation but it work
(setq time-per (/ stopt (* demi-per 2))) ; number of period
(setq rifa (/ logidur 10) ) ; rise and fall times are 1/10 period (rifa=risefall)
(setq pwmset (* (- pwmset 0.5) 2) ) ; convert pwm user value in an addition term
(setq count 0) ; set counter of while wich is below
(setq point1 (* logidur (float count)) )
(setq point2 (* logidur (+ (float count) (+ (float 1) pwmset)) ) ) ; setting x values (time axis)
(setq point3 (* logidur (+ count 2)) ) ; point2 is modulated according
(setq point8 (* logidur (+ count 3)) ) ; to pwm value
(setq point9 (* logidur (+ count 4)) ) ; rifa follow point2 modulation
(setq point4 (+ point2 rifa ))
(setq point5 (- point9 rifa ))
(setq pair1 (list point1 1)) ; set pair in some lists
(setq pair2 (list point2 1)) ; with x value, y is 0 or 1
(setq pair3 (list point4 0)) ; 6 pairs= 6 points a period
(setq pair4 (list point3 0)) ; here one period is 2 time more
(setq pair5 (list point8 0)) ; long than mono version
(setq pair6 (list point5 0))
(setq list3 (nconc pair1 pair2 pair3 pair4 pair5 pair6)) ; using nconc funtion to concatenate
; in a single list
(while (< count (* (- time-per 1) 2)) ; while repeat the same as previously
; for the number of period
(setq count (+ count 4)) ; (one loop is already done)
(setq point1 (* logidur (float count)) )
(setq point2 (* logidur (+ (float count) (+ (float 1) pwmset)) ) ) ; setting x values (time axis)
(setq point3 (* logidur (+ count 2)) ) ; point2 is modulated according
(setq point8 (* logidur (+ count 3)) ) ; to pwm value
(setq point9 (* logidur (+ count 4)) ) ; rifa follow point2 modulation
(setq point4 (+ point2 rifa ))
(setq point5 (- point9 rifa ))
(setq pair1 (list point1 1)) ; set pair in some lists
(setq pair2 (list point2 1)) ; with x value, y is 0 or 1
(setq pair3 (list point4 0)) ; 6 pairs= 6 points a period
(setq pair4 (list point3 0)) ; here a period is 2 time more
(setq pair5 (list point8 0)) ; long than mono version
(setq pair6 (list point5 0))
(setq list3 (nconc list3 pair1 pair2 pair3 pair4 pair5 pair6)) ; using nconc funtion to concatenate
; in a single list
)
(setq pwm1 (pwl-list list3)) ; pwl-list function generate
; the square wave with all points
; that are in the previous list
)
; this function generate a "half square" wave for left stereo signal
; wich have duration of selection, and have freq and pwm set by user
; the period is 2 time more long than mono version
; because one empty period is added for stereo a alternance
(defun mksqareright (stoptime bpmset pwmset)
(setq demi-per (/ (/ 1 (/ bpmset 60)) 4)) ; half period
(setq nbpoint (/ stopt demi-per)) ; finally i didn't use it (number of pair in list)
(setq logidur (/ demi-per (/ stopt 20))) ; i had some problem with logic and real time
(setq logidur (/ logidur 20)) ; i don't have more explanation but it work
(setq time-per (/ stopt (* demi-per 2))) ; number of period
(setq rifa (/ logidur 10) ) ; rise and fall times are 1/10 period (rifa=risefall)
(setq pwmset (* (- pwmset 0.5) 2) ) ; convert pwm user value in an addition term
(setq count 0) ; set counter of while wich is below
(setq point1 (* logidur (float count)) )
(setq point2 (* logidur (+ (float count) (float 1)) ) ) ; setting x values (time axis)
(setq point3 (* logidur (+ count 2)) )
(setq point8 (* logidur (+ count (+ (float 3) pwmset))) ) ; point8 (=5th) is modulated according
; to pwm value
(setq point4 (- point3 rifa )) ; rifa follow point8 modulation
(setq point5 (+ point8 rifa ))
(setq pair1 (list point1 0)) ; set pair in some lists
(setq pair2 (list point2 0)) ; with x value, y is 0 or 1
(setq pair3 (list point4 0)) ; 6 pairs= 6 points a period
(setq pair4 (list point3 1)) ; the period is 2 time more
(setq pair5 (list point8 1)) ; long than mono version
(setq pair6 (list point5 0)) ; and the pulse is on 2nd period
; for right channel, for stereo alternance
(setq list3 (nconc pair1 pair2 pair3 pair4 pair5 pair6)) ; using nconc funtion to concatenate
; in a single list
(while (< count (* (- time-per 1) 2)) ; while repeat the same as previously
; for the number of period
(setq count (+ count 4)) ; (one loop is already done)
(setq point1 (* logidur (float count)) ) ; setting x values (time axis)
(setq point2 (* logidur (+ (float count) (float 1)) ) )
(setq point3 (* logidur (+ count 2)) )
(setq point8 (* logidur (+ count (+ (float 3) pwmset))) ) ; point8 (=5th) is modulated according
; to pwm value
(setq point4 (- point3 rifa )) ; rifa follow point8 modulation
(setq point5 (+ point8 rifa ))
(setq pair1 (list point1 0)) ; set pair in some lists
(setq pair2 (list point2 0)) ; with x value, y is 0 or 1
(setq pair3 (list point4 0)) ; 6 pairs= 6 points a period
(setq pair4 (list point3 1)) ; the period is 2 time more
(setq pair5 (list point8 1)) ; long than mono version
(setq pair6 (list point5 0)) ; and the pulse is on 2nd period
; for right channel, for stereo alternance
(setq list3 (nconc list3 pair1 pair2 pair3 pair4 pair5 pair6)) ; using nconc funtion to concatenate
; in a single list
)
(setq pwm1 (pwl-list list3)) ; pwl-list function generate
; the square wave with all points
) ; that are in the previous list
; this function use the 3 function previously defined
; It make 2 stereo square signals, using square wave generated by previous function
; (one alterning, one without alterning). Then it multiplies these 2 signals with input,
; to make them switched by square wave. Then it mix alterning & non-alterning according to user set
(defun gatestereo (sign timestp bpmtm stereo pwmsett)
(setq squarelft (mksqareleft timestp bpmtm pwmsett)) ; use previous function
(setq squarerght (mksqareright timestp bpmtm pwmsett)) ; generate 3 square signals
(setq squaremono (mksqare-mono timestp bpmtm pwmsett))
(setq sqrgain (vector ; make stereo signal square
squarelft ; with one alterned on each channel
squarerght ) )
(setq dualmono (vector ; make "pseudo mono" square wave in stereo signal
squaremono ; (2 channels have the same signal)
squaremono ) )
(setq gatemono (mult dualmono sign)) ; multiplies it with input signal to switch it
(setq gatestereo (mult sqrgain sign))
(setq gatestereo (mult gatestereo stereo)) ; apply gain on alterned and non-alterned signal
(setq gatemono (mult gatemono (- 1 stereo))) ; according to the user parameter
(setq globalgate (sum gatemono gatestereo)) ) ; mix alterned and non-alterned
; this function generate a mono square wave using the previously defined function mksqare-mono
; then it multiplies square signal with input to switch it
(defun gatemono (sign timestp bpmtm pwmsett)
(setq squaremono (mksqare-mono timestp bpmtm pwmsett))
(setq gatemonout (mult squaremono sign))
)
; *************** Main program ******************
(if (arrayp s) ; is it mono or stereo? (is it an array)
(setq durt (timeselec s)) ; get duration selection using previous function
(setq durt (timeselecmono s)) )
; generate a sinus wave with snd-sine function, duration si the same as selection, frequency is
; the frequency of wha sweep, between 1=max and 0=mini
(setq modulsine (snd-offset (mult (snd-sine 0 sweepspeed 44100 durt) 0.5) 0.5) )
; constant function --> multiplies amplitude by 0
(setq offsin (snd-offset (mult (snd-sine 0 0.1 44100 durt) 0) 1) )
; here i try to convert everything in geometric scale (not arithmetic)
; so it began to be a little more complicated
(setq minimodulsine (/ 1 (* widthwha widthwha)) ) ; the minimum frequency center of sweep will be
(setq geocentmodulsine (/ 1 widthwha) ) ; given by dividing the maximum 2 times by
(setq modulsinamp (- 1 minimodulsine) ) ; width factor; whereas the ge0metrical center
; is given by dividing only one time
; The amplitude of modulation sinus is between
; 1 and minimodulsine, amplitude= modulsinamp
; the amplitude of sinus is below decreased by minimodulsine value, so offset need to be increased
; with the same value to keep maximum=1, using snd-offset function
(setq modulsine2 (snd-offset (mult modulsine modulsinamp) minimodulsine) )
; sometime the resonance become very loud, so attenuating factor is added
; Convert the logarithmic user value in linear : 10^(x/10)
; but the compensation gain also vary with frequency because i noticed that low frequency where
; louder than high frequency, but then i notice the inverse and began to hack the formula
(setq compgain (power 10 (/ compgain 10)))
; at geometrical center of the amplitude of the control sinus, the frequency is the one set by user,
; so the amplitude variation is geometrical, but not the speed of this variation. The bandwith also
; vary with frequency to make it larger on high frequency and smaller on low frequency, according
; to geometrical scale. Compensation gain is added and is hacked inside out (multiplied by itself but
; i think it was to get exponentially increase that foot with geometrical scale) but it works and
; modulate at the same time with compensationgain and with frequency
(setq resonate (mult (reson s (mult modulsine2 (/ centerfreq geocentmodulsine)) (mult (mult modulsine2 (/ centerfreq geocentmodulsine)) bandfact)) (snd-offset (mult (mult modulsine modulsine) compgain) (/ compgain (* (/ 20 compgain) (* 3 compgain)) )) ) )
(setq resonate (mult resonate whafact)) ; apply gain to each dry/wet wha
(setq sin (mult s (- 1 whafact)))
(setq resonate2 (sum resonate sin)) ; mix dry and wet by adding these signals
(if (arrayp s) ; is it stereo or mono? (is it an array)
(gatestereo resonate2 durt bpm sterex pwmswtch) ; apply switch function previously defined
(gatemono resonate2 durt bpm pwmswtch) )