Amplitude Modulation

Introduction

Amplitude Modulation (aka ring modulation) is one of the simplest synthesis techniques to implement, but one of the lesser used techniques. AM uses the multiplication of two signals to create new harmonics. The product will contain the sum and difference of all of the harmonics in the original waveforms. This comes from the combinations of the phase change in the original waveforms. If you take the difference of two trigonometric angle sum and difference identities you can see how the new frequencies are derived from the multiplied sines.

cos(\alpha - \beta) = cos(\alpha)cos(\beta) + sin(\alpha)sin(\beta) \\ cos(\alpha + \beta) = cos(\alpha)cos(\beta) - sin(\alpha)sin(\beta) \\ cos(\alpha - \beta) - cos(\alpha + \beta) = 2*sin(\alpha)sin(\beta) \\ sin(\alpha)sin(\beta) = \frac{1}{2}*(cos(\alpha - \beta) - cos(\alpha + \beta))

As the frequencies are being shifted with sum and difference, these new harmonics can easily lose any harmonic relation they had in the original signals. For example, if a waveform with related harmonics of 100Hz, 200Hz and 500Hz is modulated by a 96Hz sine, the new harmonics will be at 4Hz, 104Hz, 196Hz, 296Hz, 404Hz and 596Hz. There are no simple harmonic relations in the new tone.

96Hz sine * 100,200&500Hz sine
“Walk This Way” break * sine sweep from 1k to 0Hz

Amplitude Modulation Techniques

AM can be configured in several ways to get more consonant results. The C code below will show how to achieve the following three methods.

  • By restricting the frequencies used in AM, a more useful result is obtained. If simple harmonic relations are maintained between the two source waveforms, harmonic relations will be maintained in the product.
  • The original waveforms can be reintroduced into the output by adding two parameters. This can be very useful if one of the sources isn’t sinusoidal. y(t) = \alpha*(sin(\omega_1 t)*sin(\omega_2 t) + \beta*sin(\omega_1 t) + \gamma*sin(\omega_2 t))
  • A simple harmonic tone generator can be created using feedback and self modulation.

Implementation

AM is usually implemented with a simple multiply and two source signals. Our first C example will create an AM oscillator with internal sqaure and sine wave oscillators. It will also implement gain parameters for the original waveforms.

// the samplerate in Hz
float sampleRate = 44100;
// initial phase
float phaseSin, phaseSqu = 0.0;
long tableSize = 8192;
long tableMask = 8191;
float squareTab[8192];
float sineTab[8192];

void InitTables(void)
{
  // create sineTab from sin() and squareTab from 11 first harmonics of square wave
  for(i = 0; i < tableSize; i++)
  {
    sineTab[i] = sin((6.283185307179586 * i)/tableSize);
    squareTab[i] = sin((6.283185307179586 * i)/tableSize);
    squareTab[i] += sin((6.283185307179586 * i * 3.0)/tableSize)/3.0;
    squareTab[i] += sin((6.283185307179586 * i * 5.0)/tableSize)/5.0;
    squareTab[i] += sin((6.283185307179586 * i * 7.0)/tableSize)/7.0;
    squareTab[i] += sin((6.283185307179586 * i * 9.0)/tableSize)/9.0;
    squareTab[i] += sin((6.283185307179586 * i * 11.0)/tableSize)/11.0;
    squareTab[i] += sin((6.283185307179586 * i * 13.0)/tableSize)/13.0;
    squareTab[i] += sin((6.283185307179586 * i * 15.0)/tableSize)/15.0;
    squareTab[i] += sin((6.283185307179586 * i * 17.0)/tableSize)/17.0;
    squareTab[i] += sin((6.283185307179586 * i * 19.0)/tableSize)/19.0;
    squareTab[i] += sin((6.283185307179586 * i * 21.0)/tableSize)/21.0;
  }
}

void RingOsc(float *input, float *output, float frequency, float ratio, float ringGain, float sineGain, float squareGain, long samples)
{
    long sample;
    float phaseIncSin, phaseIncSqu;
    float sinSamp, squSamp;
    // calculate for each sample in a block
    for(sample = 0; sample < samples; sample++)
    {
        // get the phase increment for this sample
        phaseIncSqu = frequency/sampleRate;
        phaseIncSin = phaseIncSqu * ratio;
        // calculate the waveforms
        sinSamp = sineTab[(long)(phaseSin * tableSize)];
        squSamp = squareTab[(long)(phaseSqu * tableSize)];

        // mix the output from ring, sine and square
        *(output+sample) = sinSamp * squSamp * ringGain + squSamp * squareGain
          + sinSamp * sineGain; 

        // increment the phases
        phaseSin = phaseSin + phaseIncSin;
        if(phaseSin >= 1.0)
            phaseSin = phaseSin - 1.0;
        phaseSqu = phaseSqu + phaseIncSqu;
        if(phaseSqu >= 1.0)
            phaseSqu = phaseSqu - 1.0;
    }
}
square * sine ring oscillator with ratio of 3 and modulation of square and sine gain

As stated earlier, a simple harmonic oscillator can be made by using a single sinewave oscillator, AM and feedback. Feedback needs to be kept under 1.0 or the algorithm will become unstable. As the feedback gain increases, more and more harmonics will be added. A small offset needs to be added to the feedback to give the sound an initial gain. Not a very rich technique, but worth knowing….

// the samplerate in Hz
float sampleRate = 44100;
// initial phase
float phase = 0.0;
float fbSamp;
long tableSize = 8192;
long tableMask = 8191;
float sineTab[8192];

void InitTables(void)
{
  // create sineTab from sin()
  for(i = 0; i < tableSize; i++)
  {
    sineTab[i] = sin((6.283185307179586 * i)/tableSize);
  }
}

void RingFBOsc(float *input, float *output, float frequency, float feedback, long samples)
{
    long sample;
    float phaseInc;
    float sinSamp, squSamp;

    if(feedback > .95) feedback = .95;
    // calculate for each sample in a block
    for(sample = 0; sample < samples; sample++)
    {
        // get the phase increment for this sample
        phaseInc = frequency/sampleRate;
        // calculate the waveforms
        sinSamp = sineTab[(long)(phase * tableSize)];

        // ring modulate with last output * feedback
        fbSamp = sinSamp * ((fbSamp * feedback) + 0.1)
        *(output+sample) = fbSamp; 

        // increment the phase
        phase = phase + phaseInc;
        if(phase >= 1.0)
            phase = phase - 1.0;
    }
}
random bass line with single oscillator feedback AM modulation

Leave a Reply

Your email address will not be published.