- //ModIndexSweep.c
- //gcc MKAiff.c ModIndexSweep.c -o ModIndexSweep
- #include "MKAiff.h"
- #include <math.h>
- #define SAMPLE_RATE 44100
- #define NUM_CHANNELS 1
- #define BITS_PER_SAMPLE 16
- #define NUM_SECONDS 3
- const int numSamples = NUM_SECONDS * NUM_CHANNELS * SAMPLE_RATE;
- #define PI 3.141592653589793
- const double TWO_PI_OVER_SAMPLE_RATE = 2*PI/SAMPLE_RATE;
- int main()
- {
- MKAiff* aiff = aiffWithDurationInSeconds(NUM_CHANNELS, SAMPLE_RATE, BITS_PER_SAMPLE, NUM_SECONDS);
- if(aiff == NULL) return 0;
- float audioBuffer[numSamples];
- double initialModIndex = 0, finalModIndex = 15;
- double modIndexIncrement = (finalModIndex-initialModIndex) / numSamples;
- double modulatorFrequency = 440, modulatorAngle = 0;
- double carrierFrequency = modulatorFrequency, carrierAngle = 0, modulationIndex = initialModIndex;
- double carrierAmplitude;
- int i;
- for(i=0; i<numSamples; i+=NUM_CHANNELS)
- {
- audioBuffer[i] = sin(modulatorAngle);
- modulatorAngle += (modulatorFrequency + sin(carrierAngle) * carrierAmplitude) * TWO_PI_OVER_SAMPLE_RATE;
- carrierAngle += carrierFrequency * TWO_PI_OVER_SAMPLE_RATE;
- modulationIndex += modIndexIncrement;
- carrierAmplitude = modulatorFrequency * modulationIndex;
- }
- aiffAppendFloatingPointSamples(aiff, audioBuffer, numSamples, aiffFloatSampleType);
- aiffSaveWithFilename(aiff, "ModIndexSweep.aif");
- aiffDestroy(aiff);
- return 0;
- }
Output:
Explanation of the Concepts
This example applies a linear envelope to the index of modulation of a frequency modulated timbre. Remember that the index of modulation is analogous to the depth of vibrato. In other words, it is the ratio of the amplitude of the modulator to the frequency of the carrier. So this example, conceptually, creates a deeper and deeper vibrato, except that the vibrato is audio-rate.
As was previously stated, the index of modulation has a profound impact on the timbre of the resultant sound. In the previous chapter we saw that the timbre of a frequency-modulated signal comprises several sideband pairs whose frequencys are determined by the ratio of the carrier frequency to the modulator frequency. It turns out that the amplitude of each sideband pair is controlled by the index of modulation. Specifically, the amplitudes can be described by a Bessel function of the first kind. We will not concern ourselves with the mathematics of such a function, but we can learn much by inspecting its plot. Here, the amplitude of each sideband pair is plotted as a function of the index of modulation, where the red line plots the amplitude of the carrier, the orange lone plots the amplitude of the first sideband pair, and soforth, according to the corresponding table:
Carrier (C) 1st Sideband Pair (C+M, C-M) 2nd Sideband Pair (C+2M, C-2M) 3rd Sideband Pair (C+3M, C-3M) 4th Sideband Pair (C+4M, C-4M) 5th Sideband Pair (C+5M, C-5M) |
6th Sideband Pair (C+6M, C-6M) 7th Sideband Pair (C+7M, C-7M) 8th Sideband Pair (C+8M, C-8M) 9th Sideband Pair (C+9M, C-9M) 10th Sideband Pair (C+10M, C-10M) |
If the index of modulation (the depth of vibrato) is 0, then one might expect that the only audible signal would be the carrier wave, which is confirmed in the above diagram where, at x=0, the value of the carrier (the red line) is 1, and the values of the other sideband pairs are all 0. Continuing farther to th right, at x=2, the first sideband pair (orange) is the most prominent, the second sideband pair (yellow) is only slightly less prominent, and the carrier is even less prominent. This is confirmed by the spectrum analysis of a sound whose index of modulation is 2:
Examining the Bessel function, it may be predicted that if the modulation index is 3.25, the second sideband pair will be most prominent in the timbre. This is confirmed in the spectrograph where the position of the red line indicates that such is true:
The same may be said of an index of modulation of 5.5 and the 4th sideband pair:
or an index of modulation of 12.5 and the 10th sideband pair.
Explanation of the Code
There is not much new in the code here. Please refer to the 'Builds On' section above for more information.