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

  1. //PreparingSamples.c
  2. //gcc MKAiff.c PreparingSamples.c -o PreparingSamples
  3. #include "MKAiff.h"
  4. #define PRERECORDED_AUDIO_PATH "demo.aif"
  5. #define SUSTAIN_LOOP_START_MARKER_ID 0x01
  6. #define SUSTAIN_LOOP_END_MARKER_ID 0x02
  7. #define SUSTAIN_START_POSITION 56191
  8. #define SUSTAIN_END_POSITION 110000
  9. int main()
  10. {
  11. MKAiff* prerecordedAudio = aiffWithContentsOfFile(PRERECORDED_AUDIO_PATH);
  12. if(prerecordedAudio==NULL) return 1;
  13. aiffRemoveAllMarkers(prerecordedAudio);
  14. aiffAddMarkerWithPositionInSamples(prerecordedAudio, "Sustain Loop Start", SUSTAIN_LOOP_START_MARKER_ID, SUSTAIN_START_POSITION);
  15. aiffAddMarkerWithPositionInSamples(prerecordedAudio, "Sustain Loop End" , SUSTAIN_LOOP_END_MARKER_ID , SUSTAIN_END_POSITION);
  16. aiffSetupInstrumentInfo(prerecordedAudio, //aiff
  17. 0x40, //baseNote
  18. 0x00, //detune
  19. 0x00, //lowNote
  20. 0x7F, //highNote
  21. 0x00, //lowVelocity
  22. 0x7F, //highVelocity
  23. 0x00, //decibelsGain
  24. //AIFF_LOOP_MODE_FORWARD, //sustainLoopPlayMode
  25. AIFF_LOOP_MODE_FORWARD_BACKWARD, //sustainLoopPlayMode
  26. //AIFF_LOOP_MODE_OFF, //sustainLoopPlayMode
  27. SUSTAIN_LOOP_START_MARKER_ID, //sustainLoopStartMarkerID
  28. SUSTAIN_LOOP_END_MARKER_ID, //sustainLoopEndMarkerID
  29. AIFF_LOOP_MODE_OFF, //releaseLoopPlayMode
  30. 0x00, //releaseLoopStartMarkerID
  31. 0x00 //releaseLoopEndMarkerID
  32. );
  33. //overwrites existing file!
  34. aiffSaveWithFilename(prerecordedAudio, PRERECORDED_AUDIO_PATH);
  35. aiffDestroy(prerecordedAudio);
  36. return 0;
  37. }

Output:

Builds On

AIFF Template

Explanation of the Concepts

This example adds "Instrument Info" to the file "demo.aif" so that it can be used by digital samplers, or by users of this book who are implementing wavetable synthesis algorithms.

The following description of the variables comes from the AIFF 1.3 specification:

baseNote is the note at which the instrument plays back the sound data without pitch modification. Units are MIDI (MIDI is an acronym for Musical Instrument Digital Interface) note numbers, and are in the range 0 through 127. Middle C is 60.

detune determines how much the instrument should alter the pitch of the sound when it is played back. Units are in cents (1/100 of a semitone) and range from -50 to +50. Negative numbers mean that the pitch of the sound should be lowered, while positive numbers mean that it should be raised.

lowNote and highNote specify the suggested range on a keyboard for playback of the sound data. The sound data should be played if the instrument is requested to play a note between the low and high notes, inclusive. The base note does not have to be within this range. Units for lowNote and highNote are MIDI note values.

lowVelocity and highVelocity specify the suggested range of velocities for playback of the sound data. The sound data should be played if the note-on velocity is is between low and high velocity,inclusive. Units are MIDI velocity values, 1 (lowest velocity) through 127 (highest velocity).

deciblesGain is the amount by which to change the gain of the sound when it is played. Units are decibels. For example, 0 db means no change, 6 db means double the value of each sample point, while -6 db means halve the value of each sample point.

sustainLoop specifies a loop that is to be played when an instrument is sustaining a sound.

releaseLoop specifies a loop that is to be played when an instrument is in the release phase of playing back a sound. The release phase usually occurs after a key on an instrument is released.

The last two items on that list, the loops are defined in terms of markers that mark their starting and ending positions, their play mode. The markers have to be added separately, and the marker ID of the corresponding marker is given to the instrument info. Regarding the play mode, the AIFF 1.3 specification says:

A loop is marked with two points, a begin position and an end position. There are two ways to play a loop, forward looping and forward/backward looping. In the case of forward looping, playback begins at the beginning of the sound, continues past the begin position and continues to the end position, at which point playback restarts again at the begin position. The segment between the begin and end positions, called the loop segment, is played over and over again, until interrupted by something, such as the release of a key on a sampling instrument, for example. begin position end position sample frames loop segment With forward/backward looping, the loop segment is first played from the begin position to the end position, and then played backwards from the end position back to the begin position. This flip-flop pattern is repeated over and over again until interrupted.


playMode specifies which type of looping is to be performed. The following values are valid:
AIFF_LOOP_MODE_FORWARD
AIFF_LOOP_MODE_FORWARD_BACKWARD
AIFF_LOOP_MODE_OFF

Remember that all of these values are just numbers stored in the file for later use. If you want the associated action to actually happen, you will have to write the code that actually does it. In the following chapters, we will examine code that implements an attack period, forward-backward sustain loop, release period, and uses the baseNote as a basis for changing pitch.

Explanation of the Code

All of the functions that are called in this unit are documented in the header file MKAiff.h, which is accessible through the link above.