FREQUENCY MODULATION
From Vibrato to the Emergence of Sidebands
A vibrato is a periodical change of pitch, normally less than a halftone and with a slow changing-rate (around 5Hz). Frequency modulation is usually done with sine-wave oscillators.
Example 04D01.csd
<CsoundSynthesizer> <CsOptions> -o dac </CsOptions> <CsInstruments> sr = 48000 ksmps = 32 nchnls = 2 0dbfs = 1 instr 1 aMod poscil 10, 5 , 1 ; 5 Hz vibrato with 10 Hz modulation-width aCar poscil 0.3, 440+aMod, 1 ; -> vibrato between 430-450 Hz outs aCar, aCar endin </CsInstruments> <CsScore> f 1 0 1024 10 1 ;Sine wave for table 1 i 1 0 2 </CsScore> </CsoundSynthesizer> ; written by Alex Hofmann (Mar. 2011)
When the modulation-width becomes increased, it becomes harder to describe the base-frequency, but it is still a vibrato.
Example 04D02.csd
<CsoundSynthesizer> <CsOptions> -o dac </CsOptions> <CsInstruments> sr = 48000 ksmps = 32 nchnls = 2 0dbfs = 1 instr 1 aMod poscil 90, 5 , 1 ; modulate 90Hz ->vibrato from 350 to 530 hz aCar poscil 0.3, 440+aMod, 1 outs aCar, aCar endin </CsInstruments> <CsScore> f 1 0 1024 10 1 ;Sine wave for table 1 i 1 0 2 </CsScore> </CsoundSynthesizer> ; written by Alex Hofmann (Mar. 2011)
The Simple Modulator->Carrier Pairing
Increasing the modulation-rate leads to a different effect. Frequency-modulation with more than 20Hz is no longer recognized as vibrato. The main-oscillator frequency lays in the middle of the sound and sidebands appear above and below. The number of sidebands is related to the modulation amplitude, later this is controlled by the so called modulation-index.
Example 04D03.csd
<CsoundSynthesizer> <CsOptions> -o dac </CsOptions> <CsInstruments> sr = 48000 ksmps = 32 nchnls = 2 0dbfs = 1 instr 1 aRaise linseg 2, 10, 100 ;increase modulation from 2Hz to 100Hz aMod poscil 10, aRaise , 1 aCar poscil 0.3, 440+aMod, 1 outs aCar, aCar endin </CsInstruments> <CsScore> f 1 0 1024 10 1 ;Sine wave for table 1 i 1 0 12 </CsScore> </CsoundSynthesizer> ; written by Alex Hofmann (Mar. 2011
Hereby the main-oscillator is called carrier and the one changing the carriers frequency is the modulator. The modulation-index: I = mod-amp/mod-freq. Making changes to the modulation-index, changes the amount of overtones, but not the overall volume. That gives the possibility produce drastic timbre-changes without the risk of distortion.
When carrier and modulator frequency have integer ratios like 1:1, 2:1, 3:2, 5:4.. the sidebands build a harmonic series, which leads to a sound with clear fundamental pitch.
Example 04D04.csd
<CsoundSynthesizer> <CsOptions> -o dac </CsOptions> <CsInstruments> sr = 48000 ksmps = 32 nchnls = 2 0dbfs = 1 instr 1 kCarFreq = 660 ; 660:440 = 3:2 -> harmonic spectrum kModFreq = 440 kIndex = 15 ; high Index.. try lower values like 1, 2, 3.. kIndexM = 0 kMaxDev = kIndex*kModFreq kMinDev = kIndexM*kModFreq kVarDev = kMaxDev-kMinDev kModAmp = kMinDev+kVarDev aModulator poscil kModAmp, kModFreq, 1 aCarrier poscil 0.3, kCarFreq+aModulator, 1 outs aCarrier, aCarrier endin </CsInstruments> <CsScore> f 1 0 1024 10 1 ;Sine wave for table 1 i 1 0 15 </CsScore> </CsoundSynthesizer> ; written by Alex Hofmann (Mar. 2011)
Otherwise the spectrum of the sound is inharmonic, which makes it metallic or noisy.
Raising the modulation-index, shifts the energy into the side-bands. The side-bands distance is: Distance in Hz = (carrierFreq)-(k*modFreq) | k = {1, 2, 3, 4 ..}
This calculation can result in negative frequencies. Those become reflected at zero, but with inverted phase! So negative frequencies can erase existing ones. Frequencies over Nyquist-frequency (half of samplingrate) "fold over" (aliasing).
The John Chowning FM Model of a Trumpet
Composer and researcher Jown Chowning worked on the first digital implementation of FM in the 1970's.
Using envelopes to control the modulation index and the overall amplitude gives you the possibility to create evolving sounds with enormous spectral variations. Chowning showed these possibilities in his pieces, where he let the sounds transform. In the piece Sabelithe a drum sound morphes over the time into a trumpet tone.
Example 04D05.csd
<CsoundSynthesizer> <CsOptions> -o dac </CsOptions> <CsInstruments> sr = 48000 ksmps = 32 nchnls = 2 0dbfs = 1 instr 1 ; simple way to generate a trumpet-like sound kCarFreq = 440 kModFreq = 440 kIndex = 5 kIndexM = 0 kMaxDev = kIndex*kModFreq kMinDev = kIndexM * kModFreq kVarDev = kMaxDev-kMinDev aEnv expseg .001, 0.2, 1, p3-0.3, 1, 0.2, 0.001 aModAmp = kMinDev+kVarDev*aEnv aModulator poscil aModAmp, kModFreq, 1 aCarrier poscil 0.3*aEnv, kCarFreq+aModulator, 1 outs aCarrier, aCarrier endin </CsInstruments> <CsScore> f 1 0 1024 10 1 ;Sine wave for table 1 i 1 0 2 </CsScore> </CsoundSynthesizer> ; written by Alex Hofmann (Mar. 2011)
The following example uses the same instrument, with different settings to generate a bell-like sound:
Example 04D06.csd
<CsoundSynthesizer> <CsOptions> -o dac </CsOptions> <CsInstruments> sr = 48000 ksmps = 32 nchnls = 2 0dbfs = 1 instr 1 ; bell-like sound kCarFreq = 200 ; 200/280 = 5:7 -> inharmonic spectrum kModFreq = 280 kIndex = 12 kIndexM = 0 kMaxDev = kIndex*kModFreq kMinDev = kIndexM * kModFreq kVarDev = kMaxDev-kMinDev aEnv expseg .001, 0.001, 1, 0.3, 0.5, 8.5, .001 aModAmp = kMinDev+kVarDev*aEnv aModulator poscil aModAmp, kModFreq, 1 aCarrier poscil 0.3*aEnv, kCarFreq+aModulator, 1 outs aCarrier, aCarrier endin </CsInstruments> <CsScore> f 1 0 1024 10 1 ;Sine wave for table 1 i 1 0 9 </CsScore> </CsoundSynthesizer> ; written by Alex Hofmann (Mar. 2011)
More Complex FM Algorithms
Combining more than two oscillators (operators) is called complex FM synthesis. Operators can be connected in different combinations often 4-6 operators are used. The carrier is always the last operator in the row. Changing it's pitch, shifts the whole sound. All other operators are modulators, changing their pitch alters the sound-spectrum.
Two into One: M1+M2 -> C
The principle here is, that (M1:C) and (M2:C) will be separate modulations and later added together.
Example 04D07.csd
<CsoundSynthesizer> <CsOptions> -o dac </CsOptions> <CsInstruments> sr = 48000 ksmps = 32 nchnls = 2 0dbfs = 1 instr 1 aMod1 poscil 200, 700, 1 aMod2 poscil 1800, 290, 1 aSig poscil 0.3, 440+aMod1+aMod2, 1 outs aSig, aSig endin </CsInstruments> <CsScore> f 1 0 1024 10 1 ;Sine wave for table 1 i 1 0 3 </CsScore> </CsoundSynthesizer> ; written by Alex Hofmann (Mar. 2011)
In series: M1->M2->C
This is much more complicated to calculate and sound-timbre becomes harder to predict, because M1:M2 produces a complex spectrum (W), which then modulates the carrier (W:C).
Example 04D08.csd
<CsoundSynthesizer> <CsOptions> -o dac </CsOptions> <CsInstruments> sr = 48000 ksmps = 32 nchnls = 2 0dbfs = 1 instr 1 aMod1 poscil 200, 700, 1 aMod2 poscil 1800, 290+aMod1, 1 aSig poscil 0.3, 440+aMod2, 1 outs aSig, aSig endin </CsInstruments> <CsScore> f 1 0 1024 10 1 ;Sine wave for table 1 i 1 0 3 </CsScore> </CsoundSynthesizer> ; written by Alex Hofmann (Mar. 2011)
Phase Modulation - the Yamaha DX7 and Feedback FM
There is a strong relation between frequency modulation and phase modulation, as both techniques influence the oscillator's pitch, and the resulting timbre modifications are the same.
If you'd like to build a feedbacking FM system, it will happen that the self-modulation comes to a zero point, which stops the oscillator forever. To avoid this, it is more practical to modulate the carriers table-lookup phase, instead of its pitch.
Even the most famous FM-synthesizer Yamaha DX7 is based on the phase-modulation (PM) technique, because this allows feedback. The DX7 provides 7 operators, and offers 32 routing combinations of these. (http://yala.freeservers.com/t2synths.htm#DX7)
To build a PM-synth in Csound tablei opcode needs to be used as oscillator. In order to step through the f-table, a phasor will output the necessary steps.
Example 04D09.csd
<CsoundSynthesizer> <CsOptions> -o dac </CsOptions> <CsInstruments> sr = 48000 ksmps = 32 nchnls = 2 0dbfs = 1 instr 1 ; simple PM-Synth kCarFreq = 200 kModFreq = 280 kModFactor = kCarFreq/kModFreq kIndex = 12/6.28 ; 12/2pi to convert from radians to norm. table index aEnv expseg .001, 0.001, 1, 0.3, 0.5, 8.5, .001 aModulator poscil kIndex*aEnv, kModFreq, 1 aPhase phasor kCarFreq aCarrier tablei aPhase+aModulator, 1, 1, 0, 1 outs (aCarrier*aEnv), (aCarrier*aEnv) endin </CsInstruments> <CsScore> f 1 0 1024 10 1 ;Sine wave for table 1 i 1 0 9 </CsScore> </CsoundSynthesizer> ; written by Alex Hofmann (Mar. 2011)
Let's use the possibilities of self-modulation (feedback-modulation) of the oscillator. So in the following example, the oscillator is both modulator and carrier. To control the amount of modulation, an envelope scales the feedback.
Example 04D10.csd
<CsoundSynthesizer> <CsOptions> -o dac </CsOptions> <CsInstruments> sr = 48000 ksmps = 32 nchnls = 2 0dbfs = 1 instr 1 ; feedback PM kCarFreq = 200 kFeedbackAmountEnv linseg 0, 2, 0.2, 0.1, 0.3, 0.8, 0.2, 1.5, 0 aAmpEnv expseg .001, 0.001, 1, 0.3, 0.5, 8.5, .001 aPhase phasor kCarFreq aCarrier init 0 ; init for feedback aCarrier tablei aPhase+(aCarrier*kFeedbackAmountEnv), 1, 1, 0, 1 outs aCarrier*aAmpEnv, aCarrier*aAmpEnv endin </CsInstruments> <CsScore> f 1 0 1024 10 1 ;Sine wave for table 1 i 1 0 9 </CsScore> </CsoundSynthesizer> ; written by Alex Hofmann (Mar. 2011)
The last example features modulation of the buzz opcode. The buzz opcode can have a lot of harmonic overtones and frequency modulation of the buzz opcode gives even more overtones. Four different voices play at the same time, forming strange chords that use glissando/portamento to move from one chord to the next. This .csd file is regenerative, everytime you run it, it should show a different performance.
EXAMPLE 04D11.csd
<CsoundSynthesizer> <CsOptions> -odac </CsOptions> <CsInstruments> ; By Bjørn Houdorf, April 2012 sr = 44100 ksmps = 8 nchnls = 2 0dbfs = 1 ; Global initializations ("Instrument 0") seed 0; New pitches, gkfreq1 init 0; every time you gkfreq2 init 0; run this file gkfreq3 init 0 gkfreq4 init 0 gimidia1 init 60; The 4 voices start gimidib1 init 60; at different gimidia2 init 64; MIDI frequencies gimidib2 init 64 gimidia3 init 67 gimidib3 init 67 gimidia4 init 70 gimidib4 init 70 ; Function Table giFt1 ftgen 0, 0, 16384, 10, 1; Sine wave instr 1; Master control pitch for instrument 2 test: idurtest poisson 20; Duration of each test loop timout 0, idurtest, execute reinit test execute: gimidia1 = gimidib1 ital1 random -4, 4 gimidib1 = gimidib1 + ital1 gimidia2 = gimidib2 ital2 random -4, 4 gimidib2 = gimidib2 + ital2 gimidia3 = gimidib3 ital3 random -4, 4 gimidib3 = gimidib3 + ital3 gimidia4 = gimidib4 ital4 random -4, 4 gimidib4 = gimidib4 + ital4 idiv poisson 4 idurx = 0.01; Micro end segment to create ;a held final frequency value ifreq1a = cpsmidinn(gimidia1) ifreq1b = cpsmidinn(gimidib1) ; Portamento frequency ramp: gkfreq1 linseg ifreq1a, idurtest/idiv, ifreq1b, idurx, ifreq1b ifreq2a = cpsmidinn(gimidia2) ifreq2b = cpsmidinn(gimidib2) gkfreq2 linseg ifreq2a, idurtest/idiv, ifreq2b, idurx, ifreq2b ifreq3a = cpsmidinn(gimidia3) ifreq3b = cpsmidinn(gimidib3) gkfreq3 linseg ifreq3a, idurtest/idiv, ifreq3b, idurx, ifreq3b ifreq4a = cpsmidinn(gimidia4) ifreq4b = cpsmidinn(gimidib4) gkfreq4 linseg ifreq4a, idurtest/idiv, ifreq4b, idurx, ifreq4b endin instr 2 ; Oscillators iamp = p4 irise = p5 idur = p3 idec = p6 kamp = p7 imodfrq = p8 iharm = p9 ; Number of harmonics ky linen iamp, irise, idur, idec kampfreq = 2 kampa oscili kamp, kampfreq, giFt1 ; Different phase for the 4 voices klfo1 oscili kampa, imodfrq, giFt1, 0 klfo2 oscili kampa, imodfrq, giFt1, 0.25 klfo3 oscili kampa, imodfrq, giFt1, 0.50 klfo4 oscili kampa, imodfrq, giFt1, 0.75 kzfrq = 0.1; Velocity of amplitude oscillation kampvoice = 0.5; Amplitude of each voice ; Amplitude between -0.5 and 0.5 kx1 oscili 0.5, kzfrq, giFt1, 0 kx2 oscili 0.5, kzfrq, giFt1, 0.25 kx3 oscili 0.5, kzfrq, giFt1, 0.50 kx4 oscili 0.5, kzfrq, giFt1, 0.75 ; Add 0.5 so amplitude oscillates between 0 and 1 k1 = kx1+0.5 k2 = kx2+0.5 k3 = kx3+0.5 k4 = kx4+0.5 ; Minimize interference between chorus oscillators itilf random -5, 5 asig11 buzz ky*k1, (2.02*gkfreq1)+itilf+klfo1, iharm, giFt1 asig12 buzz ky*k1, gkfreq1 +klfo1, iharm, giFt1; Voice 1 asig13 buzz ky*k1, (1.51*gkfreq1)+itilf+klfo1, iharm, giFt1 aa1 = asig11+asig12+asig13 asig21 buzz ky*k2, (2.01*gkfreq2)+itilf+klfo2, iharm, giFt1 asig22 buzz ky*k2, gkfreq2 +klfo2, iharm, giFt1; Voice 2 asig23 buzz ky*k2, (1.51*gkfreq2)+itilf+klfo2, iharm, giFt1 aa2 = asig21+asig22+asig23 asig31 buzz ky*k3, (2.01*gkfreq3)+itilf+klfo3, iharm, giFt1 asig32 buzz ky*k3, gkfreq3 +klfo3, iharm, giFt1; Voice 3 asig33 buzz ky*k3, (1.51*gkfreq3)+itilf+klfo3, iharm, giFt1 aa3 = asig31+asig32+asig33 asig41 buzz ky*k4, (2.01*gkfreq4)+itilf+klfo4, iharm, giFt1 asig42 buzz ky*k4, gkfreq4 +klfo4, iharm, giFt1; Voice 4 asig43 buzz ky*k4, (1.51*gkfreq4)+itilf+klfo4, iharm, giFt1 aa4 = asig41+asig42+asig43 outs aa1+aa3, aa2+aa4 endin </CsInstruments> <CsScore> ; Master control instrument ; Inst start dur i1 0 3600 ; Oscillators ; inst start idur iamp irise idec kamp imodfrq iharm i2 0 3600 0.3 4 20 0.10 7 16 </CsScore> </CsoundSynthesizer>