Yes, there will be a slight click each time the “full-cycle” repeats. To avoid that you would need to slide from one frequency to the next rather than jumping from one frequency to the next. It doesn’t matter for square waves because the waveform is at a constant level each time it switches.
;type generate
;control dur "Duration" float "seconds" 10 0 100
;control gain "Amplitude" float "" 0.8 0 1
;; Generate a square wave that alternates between
;; 5 cycles of 600hz, and 4 cycles of 435 hz.
;;
;; a. Duration of 5 cycles of 600 Hz = 5/600 seconds.
;; b. Duration of 4 cycles of 435 Hz = 4/435 seconds.
;; Hard coded values below could be assigned by ;control lines.
(setf hz-a 600)
(setf cycles-a 5.0)
(setf hz-b 435)
(setf cycles-b 4.0)
(setf step-a (/ cycles-a hz-a))
(setf step-b (/ cycles-b hz-b))
(setf step (+ step-a step-b))
; Calculate closest number of complete cycles
(setf cycles (round (/ dur step)))
(defun control-sig ()
;; Required breakpoints:
;; hz-a, step-a, hz-a, 0, hz-b, step-b, hz-b, 0 ...
(let ((breakpoints ())
(cycle (list hz-a step-a hz-a 0 hz-b step-b hz-b 0)))
(dotimes (i cycles)
(dolist (c cycle)
;; 'push' prepends a value to a list, so we will
;; need to reverse the list before we use it.
;; Alternatively it could be build it reverse-wise but
;;that makes my head hurt ;-)
(push c breakpoints)))
;(print (reverse breakpoints))
(pwlvr-list (reverse breakpoints))))
(mult gain (hzosc (control-sig)))
It avoids clicks because the PWL (piecewise linear approximations) functions create a control signal at 1/20th of the sample rate, so there is a short ramp up / down in the frequency rather than an abrupt jump.
I’m not sure what you are trying to show me.
Are you sure that you are not being mislead by the spectrograms? Note that the spectrograms are calculated in blocks of samples (according to the “window size”. In effect, the “FFT window” is being laid over a periodically changing spectrum, which will create patterns that aren’t really present in the audio (like looking through two net curtains).
With These settings:
Low sampling rates vs high sampling rates audibly sound different.
The spectrograms are the same sampling rates, they look different because the code was run at a higher sampling rate for the first track(480,000hz), resampled back to 48000hz, and clipped.
The issue is that a cycle of (5 x 651 Hz) + (4 x 465 Hz) cannot be represented exactly at a sample rate of 48000 samples per second, or at the “control rate” of 2400 Hz. The code is rounding all the lengths to exact samples, so there is a repeating pattern of rounding errors on each frequency switch and each cycle. The audible result is that the generated sound is modulated by the sample rates, resulting in lower “beat frequencies”.
Probably the easiest solution is to generate the sounds in a very high sample rate track, then down-sample to the rate you require.