An Audio Synthesis Textbook For Musicians, Digital Artists and Programmers by Mike Krzyzaniak

  1. //RingModulation.c
  2. //gcc MKAiff.c RingModulation.c -o RingModulation
  3. #include "MKAiff.h"
  4. #include <math.h>
  5. #define SAMPLE_RATE 44100
  6. #define NUM_CHANNELS 1
  7. #define BITS_PER_SAMPLE 16
  8. #define NUM_SECONDS 3
  9. const int numSamples = NUM_SECONDS * NUM_CHANNELS * SAMPLE_RATE;
  10. #define PI 3.141592653589793
  11. const double TWO_PI_OVER_SAMPLE_RATE = 2*PI/SAMPLE_RATE;
  12. int main()
  13. {
  14. MKAiff* aiff = aiffWithDurationInSeconds(NUM_CHANNELS, SAMPLE_RATE, BITS_PER_SAMPLE, NUM_SECONDS);
  15. if(aiff == NULL) return 0;
  16. float audioBuffer[numSamples];
  17. double modulatorFrequency = 440, modulatorAngle = 0;
  18. double carrierFrequency = 550, carrierAngle = 0;
  19. int i;
  20. for(i=0; i<numSamples; i+=NUM_CHANNELS)
  21. {
  22. audioBuffer[i] = sin(modulatorAngle) * sin(carrierAngle);
  23. modulatorAngle += modulatorFrequency * TWO_PI_OVER_SAMPLE_RATE;
  24. carrierAngle += carrierFrequency * TWO_PI_OVER_SAMPLE_RATE;
  25. }
  26. aiffAppendFloatingPointSamples(aiff, audioBuffer, numSamples, aiffFloatSampleType);
  27. aiffSaveWithFilename(aiff, "RingModulation.aif");
  28. aiffDestroy(aiff);
  29. return 0;
  30. }

Output:

Explanation of the Concepts

Ring modulation is the process of modulating the amplitude of and audio signal by another audio signal. In the Stereo Panning chapter we saw how to modulate the amplitude of an audio signal by a sub-audio (1 Hz) sine wave. Ring modulation is similar to one channel of Stereo Panning, but with the following differences:

  1. the volume-controlling wave is now called the "carrier wave", and the audio signal is now called the "modulator wave". Amplitude modulation is used, amongst other things, to broadcast radio signals. In this context, the modulator wave is the sound of Rush's Voice, and the carrier wave is where you tune your radio, i.e. 1020AM. Notice, however, that as applied to audio synthesis, since the waves are being multiplied, it does not matter which wave is called the 'modulator' and which is the 'carrier'.
  2. The frequency of the carrier wave has been raised from sub-audio(1 Hz) to audio (550hz).
  3. The carrier wave is now allowed to swing negative. In the Stereo Panning chapter, it was scaled to a value between 0 and 1, but here it is left unscaled so that it is between -1 and +1.

If the modulator wave is a sine wave, like this one:

Modulator

and the carrier is another sine wave, like this one:

Carrier

the result of ring-modulating (i.e. multiplying) them will be the yellow wave in the image below, which has been superimposed on the modulator and carrier for demonstration:

All

Notice that the resultant wave (yellow) is just the carrier (white) whose amplitude is being adjusted by the modulator (red).

In the above program, the modulator is a 440 Hz sine wave, and the carrier is a 550 Hz sine wave. Interestingly, when they are ring-modulated, the original frequencies are no longer present in the resultant sound. Instead, the carrier frequency (550Hz) is replaced by two different frequencies, one above and the other below the original carrier frequency. These frequencies are called 'sideband' frequencies, because there is one on either 'side' of the original carrier. How far above and below the carrier are the sidebands? They are the distance of the modulator-frequency above and below. Since here the modulator is 440 Hz, one sideband will be 440 Hz above the carrier, and the other will be 440 Hz below. In the recording above, the lower sideband can be difficult to hear if you are listening through your laptop's built-in speakers (which have poor low-frequency response). The spectrograph of this sound, however, clearly shows the two sidebands at the expected frequencies:

FFT

Explanation of the Code

The code here is very straightforward. The audio buffer is just being filled with two sine-waves that are multiplied together on line 28.