- //QuadrophonicPanning.c
- //gcc MKAiff.c QuadrophonicPanning.c -o QuadrophonicPanning
- #include "MKAiff.h"
- #include <math.h>
- #define SAMPLE_RATE 44100
- #define NUM_CHANNELS 4
- #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 frequency = 440, angle = 0;
- double volumeFrequency = 1, volumeAngle = 0;
- float nextSample;
- int i;
- for(i=0; i<numSamples; i+=NUM_CHANNELS)
- {
- nextSample = sin(angle);
- audioBuffer[i] = nextSample * ((sin(volumeAngle) + 1) / 2);
- audioBuffer[i+1] = nextSample * ((cos(volumeAngle) + 1) / 2);
- audioBuffer[i+2] = nextSample * ((sin(volumeAngle+PI) + 1) / 2);
- audioBuffer[i+3] = nextSample * ((cos(volumeAngle+PI) + 1) / 2);
- angle += frequency * TWO_PI_OVER_SAMPLE_RATE;
- volumeAngle += volumeFrequency * TWO_PI_OVER_SAMPLE_RATE;
- }
- aiffAppendFloatingPointSamples(aiff, audioBuffer, numSamples, aiffFloatSampleType);
- aiffSaveWithFilename(aiff, "QuadrophonicPanning.aif");
- aiffDestroy(aiff);
- return 0;
- }
Output:
Explanation of the Concepts
In the previous chapter we saw how to move a sound back and forth in a stereo field. Here, we will move a sound in an orbit around a quadrophonic field. The process is the same, except that the volume of each channel will be only 90 degrees (PI/2 radians) behind the next. The mathematical function cosine is the same as sine, except that it is advanced 90 degrees, so we can save a couple of additions by using it. Note that the above audio will not play properly unless you happen to have 4 speakers connected to your laptop!
Explanation of the Code
Line 9 sets the number of audio channels to 4. From there, this is identical to the previous chapter on stereo panning, except that here we have 2 extra intermediate channels whose volume will be 90 degrees (PI/2) out of phase with the other channels. This is accomplished using cosine. Notice that
cos(volumeAngle)
is identical to
sin(volumeAngle+PI/2)
and
cos(volumeAngle+PI)
is identical to
sin(volumeAngle+3*PI/2)
It is therefore better to use cosine, because it saves many multiplications and divisions.