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

  1. //SquareWave.c
  2. //gcc MKAiff.c SquareWave.c -o SquareWave
  3. #include "MKAiff.h"
  4. #define SAMPLE_RATE 44100
  5. #define NUM_CHANNELS 1
  6. #define BITS_PER_SAMPLE 16
  7. #define NUM_SECONDS 3
  8. const int numSamples = NUM_SECONDS * NUM_CHANNELS * SAMPLE_RATE;
  9. int main()
  10. {
  11. MKAiff* aiff = aiffWithDurationInSeconds(NUM_CHANNELS, SAMPLE_RATE, BITS_PER_SAMPLE, NUM_SECONDS);
  12. if(aiff == NULL) return 0;
  13. float audioBuffer[numSamples];
  14. double frequency = 440;
  15. int halfWavelength = SAMPLE_RATE / (2*frequency);
  16. float nextSample = -1;
  17. int i;
  18. for(i=0; i<numSamples; i+=NUM_CHANNELS)
  19. {
  20. if(!((i/NUM_CHANNELS) % halfWavelength))
  21. nextSample *= -1;
  22. audioBuffer[i] = nextSample;
  23. }
  24. aiffAppendFloatingPointSamples(aiff, audioBuffer, numSamples, aiffFloatSampleType);
  25. aiffSaveWithFilename(aiff, "SquareWave.aif");
  26. aiff = aiffDestroy(aiff);
  27. return 1;
  28. }

Output:

Builds On

AIFF Template

Explanation of the Concepts

A square wave jumps between its highest value and its lowest value with no intermediate values. Here these values are -1 and +1, but in some analog implementations (like on the Arp 2500) the values are 0 and +1 or -1 and 0. Here is a plot of a square wave's value as a function of time:

FFT

The frequency content of a square wave is rich in odd numbered partials, but deprived of even numbered partials. This is evident in the Fourier Spectrograph:

FFT

For this reason, many musicians describe the square-wave as sounding "hollow".

Explanation of the Code

The value of the wave must flip from -1 to 1 every half-period. The number of frames in the half-period is calculated on line 21. line 26 checks to see if the current frame is the beginning of a half-period. The term (i/NUM_CHANNELS) is the current frame, and the current frame modulo the half-period will be zero at the beginning of every half-period, and non-zero at all other times. The logical 'not' operator, represented by an exclamation point in the C language, turns the value 0 into 'true' and all other values into 'false'. Line 27, which flips the value of the wave between -1 and +1, therefore, only gets evaluated every half-period.