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

  1. //Scrubbing.c
  2. //gcc /usr/include/MKAudio/MKAiff.c Layering.c -o Layering
  3. #include <MKAudio/MKAiff.h>
  4. #include <math.h>
  5. #define PRERECORDED_AUDIO_PATH "/Users/michaelkrzyzaniak/Desktop/demo.aif"
  6. #define NUM_CHANNELS 2
  7. #define SAMPLE_RATE 44100
  8. #define BITS_PER_SAMPLE 16
  9. #define NUM_SECONDS 5
  10. #define PI 3.141592653589793
  11. #define GRAIN_DURATION 0.05
  12. #define GRAIN_OVERLAP 0.05
  13. const int framesPerGrain = GRAIN_DURATION * SAMPLE_RATE;
  14. const int numGrains = NUM_SECONDS / (GRAIN_DURATION * GRAIN_OVERLAP);
  15. #define GAIN 0.4
  16. int main()
  17. {
  18. MKAiff* preRecordedAudio = aiffWithContentsOfFile(PRERECORDED_AUDIO_PATH);
  19. if(preRecordedAudio == NULL) return 1;
  20. MKAiff* aiff = aiffWithDurationInSeconds(NUM_CHANNELS, SAMPLE_RATE, BITS_PER_SAMPLE, NUM_SECONDS);
  21. if(aiff == NULL) return 1;
  22. const int samplesPerGrain = NUM_CHANNELS * framesPerGrain;
  23. float grainBuffer [samplesPerGrain];
  24. float windowFunction[samplesPerGrain];
  25. int i, j;
  26. for(i=0; i<samplesPerGrain; i+=NUM_CHANNELS)
  27. for(j=0; j<NUM_CHANNELS; j++)
  28. windowFunction[i+j] = GAIN * 0.5 * (1-cos(2*PI*i/samplesPerGrain));
  29. //windowFunction[i+j] = GAIN * sin( i*PI / (double)samplesPerGrain );
  30. float pan, grainLocation;
  31. for(i=0; i<numGrains; i++)
  32. {
  33. pan = random() / (float)RAND_MAX;
  34. grainLocation = random() / (float)RAND_MAX;
  35. grainLocation *= (aiffDurationInFrames(preRecordedAudio) - framesPerGrain);
  36. aiffSetPlayheadToFrames(preRecordedAudio, grainLocation);
  37. aiffReadFloatingPointSamplesAtPlayhead(preRecordedAudio, grainBuffer, samplesPerGrain);
  38. for(j=0; j<samplesPerGrain; j+= NUM_CHANNELS)
  39. {
  40. grainBuffer[j] *= pan * windowFunction[j];
  41. grainBuffer[j+1] *= (1-pan) * windowFunction[j];
  42. }
  43. aiffSetPlayheadToFrames(aiff, i * framesPerGrain * GRAIN_OVERLAP);
  44. aiffAddFloatingPointSamplesAtPlayhead(aiff, grainBuffer, samplesPerGrain, aiffFloatSampleType, aiffNo);
  45. }
  46. aiffSaveWithFilename(aiff, "Layering.aif");
  47. aiffDestroy(aiff);
  48. aiffDestroy(preRecordedAudio);
  49. return 0;
  50. }

Output:

Explanation of the Concepts

This example uses granular synthesis to create a dense musical texture.

Conceptually, this example is identical to the previous example, except that here, grains are taken from random locations in the original audio file, rather than successive locations. Also, the grains here are panned to random spacial locations in the stereo field.

Explanation of the Code

Code Explanation