Additive Synthesis on SND

Signal theory tells us that by means of the Fourier Transform, any periodic waveform can be represented as a sum of harmonically related sinusoids, each one with its own particular amplitude and phase. The timbre or the spectra of a sound can be viewed from two different perspectives known as the “time domain” and the “frequency domain”. Depending on conditions and how a sound is being analyzed one view might be more useful than the other. For example in the case of additive synthesis, the frequency domain is more useful while if we were to edit a complete chunk of sound the time domain will certainly be more useful.

In theory the Fourier Transform (FFT) generates most of the information necessary to reconstruct a signal from a complex sound. Additive synthesis can be used for reconstructing a signal by synthesizing each partial as given on the FFT of the original signal but more generally speaking additive synthesis is used to sum and mix sinusoids to produce more complex sounds. This allows for control over the individual simple components by means of individual envelopes for amplitude and frequency.

Therefore one should be able to add up a bunch of sine waves and get any complex arbitrary signal. The simplest case is when all overtones are integer multiples of the fundamental frequency. In this simple case the waveform is periodic. As the periodic waveform repeats over time we can implement additive synthesis by using a table to store the values of one cycle instead of adding the output of all the equivalent sine oscillators (it is a lot more efficient). Here's a simple Snd instrument inspired on Fernando Lopez-Lezcano's (circa 1996) that implements additive synthesis by using the table-lookup unit generator. This is called harmonic synthesis by means of wave-table synthesis.

(define (dowave start-time dur frequency amplitude harmonics)
  (let* ((start (seconds->samples start-time))
	 (len (seconds->samples (+ start-time dur)))		
           ;; create a table called "waveform" with the harmonics
           (waveform (partials->wave harmonics ))
           ;; create the table lookup unit generator
           (s (make-table-lookup :frequency frequency :wave waveform))
           ;; add a simple amplitude envelope...
           (amp-env (make-env :envelope '(0 0 0.5 1 1 0)
                              :duration dur
                              :scaler amplitude))
      (do ((i start (1+ i)))
          ((= i len))
        (outa i  (* (env amp-env) (table-lookup s)) ))
You can try the following function calls to listen to the tones.

In Partial Synthesis the overtones are not integer multiples of a fundamental frequency and thus we do not resort to the previous shortcut of a table. Therefore, in this case each component (partial) needs to be implemented independently and separately and furthermore sum each signal component to get the more complex sound. This means a lot of computing resources which translate in more computations and time.

Here is a very simple instrument that implements additive synthesis with three partials.

(define* (doadd start-time duration frequency amplitude  
		(partial1 1.0)(amp1 0.3)
		(partial2 2.0)(amp2 0.2)
		(partial3 3.0)(amp3 0.1)
		(ampenv '(0 0 0.5 1 1 0)))
  (let* ((start (seconds->samples start-time))
	 (len (seconds->samples (+ start-time duration)))		
         (sine1 (make-oscil :frequency (* partial1 frequency)))
         (sine2 (make-oscil :frequency (* partial2 frequency)))
         (sine3 (make-oscil :frequency (* partial3 frequency)))
         (amp-env (make-env :envelope ampenv 
                            :scaler amplitude
                            :end len)) )
    (do ((i start (1+ i)))
        ((= i len))
      (outa i (* (env amp-env)
                 (+ (* amp1 (oscil sine1))
                    (* amp2 (oscil sine2))
                    (* amp3 (oscil sine3))))))
The function calls for this instruments are as follows:


Jean Claude Risset, among the pioneers of computer music, experimented exhaustively on the synthesis of natural sounds by means of a computer. He researched instrumental sounds such like a trumpet, by employing spectrum analysis tools at the time (circa 1964), revealing amplitudes and frequencies of partials of these instruments but most importantly, how each partial will differ depending on its frequency, duration and amplitude (i.e. the basis for additive synthesis). Later he joined John Chowning on persuit for complex spectra on FM Synthesis techniques. More about J.C. Risset.Amid his work, there were synthesis of Inharmonic tones. For this he found that the higher the frequency of a partial component of a sound, the faster its decay, calling this a principle because a much more natural decay. In most natural sounds, evidence shows that higher frequency components tend to decay more rapidly than the lower frequency ones. But from a creative compositional perspective he mentioned:

“ Because with additive synthesis one has complete control of decay rates, one can add interest to the computer timbres by occasionally violating the principle.”

Inharmonic tones evoke music played on gongs and bells. For a natural rendition of these sounds some envelopes are changed to non percussive envelopes, hence producing bell-like tones transformed into fluid textures while retaining same underlying pattern. In the first part of a synthesized sound as described above, the listener tends to perceive individual “sound objects” such as bells whereas in a second part of the sound, the fusion of partials into individual sound objects is hindered by asynchronous envelopes, helping hear each partial in successive patterns. Next is our take on the subject of synthesizing Inharmonic tones on Snd's s7.

;;; Bell Spectra
(define bell-ratios '(.56 .563 .92 .923 1.19 1.7 2 2.74 3 3.74 4.07))
(define bell-amps   '(1 2/3 1 1.8 8/3 1.46 4/3 4/3 1 4/3 1))
;;;  Inharmonic Spectra
(define in-ratios '(.56 .92 1.19 1.71 2.0 2.74 3. 3.76 4.07 4.125))
(define in-amps '(2/3 1 .75 .5 .45 .4 .43 .15 .1 .07))

(define* (inharmonic beg dur freq att partials coeffs
		     (envl '(0 0 .05 1  .85 0.07  1 0)))
  (let* ((start (seconds->samples beg))
	 (len (length partials))
	 (arr (make-vector len))
	 (ratios (make-vector len))
	 (amps (make-vector len))
	 (envelopes (make-vector len))
	 (end (seconds->samples (+ beg dur))) ) 
    (set! ratios (list->vector partials))   
    (set! amps (list->vector coeffs))
    (do ((i 0 (1+ i)))                                 ;; oscillator bank 
	((= i len))
      (set! (arr i) (make-oscil :frequency (* freq (ratios i))) ))
    (do ((k 0 (1+ k)))                                 ;; amplitude for each partial
	((= k len))
      (set! (amps k) (/ 1 (1+ k))) )
    (do ((k 0 (1+ k)))                                 ;; envelope for each partial
	((= k len))                                    ;; duration shorter on higher partials
      (set! (envelopes k) (make-env :envelope envl
				   :base 28  
				   :duration (* dur (/ (- len k) len))
				   :scaler (amps k))))
    (do ((i start (1+ i)))                             ;; Output signal
        ((= i end))
      (let ((sum 0.0))
	(do ((j 0 (1+ j)))
	    ((= j len))
	  (set! sum (+ sum
		       (* (env (envelopes j)) (oscil (arr j)))))
	(if *reverb*
	    (outa i (* (*  0.8 att  sum ) rev-amt) *reverb*)
	    (outa i (*  0.8 att  sum )))
	)) ))

Copy-and-paste -all-of-the-above- code into a new file and save it as “inharmonic.cms”.

© Copyright 2001-2022 CCRMA, Stanford University. All rights reserved.
Created and Mantained by Juan Reyes