- //WindowFunctions.c
- //gcc MKAiff.c WindowFunctions.c -o WindowFunctions
- #include "MKAiff.h"
- #include <math.h>
- #define SAMPLE_RATE 44100
- #define NUM_CHANNELS 1
- #define BITS_PER_SAMPLE 16
- #define GRAIN_DURATION 1
- const int framesPerGrain = GRAIN_DURATION * SAMPLE_RATE;
- const int samplesPerGrain = GRAIN_DURATION * SAMPLE_RATE * NUM_CHANNELS;
- #define PI 3.141592653589793
- #define e 2.718281828459045
- const double TWO_PI_OVER_SAMPLE_RATE = 2 * PI / SAMPLE_RATE;
- int main()
- {
- MKAiff* aiff = aiffWithDurationInSeconds(NUM_CHANNELS, SAMPLE_RATE, BITS_PER_SAMPLE, GRAIN_DURATION);
- if(aiff == NULL) return 1;
- float windowFunction[framesPerGrain];
- int i;
- for(i=0; i<framesPerGrain; i++)
- {
- //SINE
- //windowFunction[i] = sin( PI * (double)i / samplesPerGrain );
- //HANN
- //windowFunction[i] = 0.5 * (1-cos(2*PI*i/samplesPerGrain));
- //HAMMING
- //windowFunction[i] = 0.54 - 0.46 * cos(2*PI*i/samplesPerGrain);
- //TUKEY
- //float truncationHeight = 0.5;
- //float f = 1/(2*truncationHeight) * (1-cos(2*PI*i/samplesPerGrain));
- //windowFunction[i] = f < 1 ? f : 1;
- //GAUSSIAN
- float sigma = 0.3;
- windowFunction[i] = pow(e, -0.5* pow(((i-samplesPerGrain/2) / (sigma*samplesPerGrain/2)), 2) );
- //TRAPEZOIDAL
- //float slope = 10;
- //float x = (float) i / framesPerGrain;
- //float f1 = slope * x;
- //float f2 = -1 * slope * (x-(slope-1) / slope) + 1;
- //windowFunction[i] = x < 0.5 ? (f1 < 1 ? f1 : 1) : (f2 < 1 ? f2 : 1);
- }
- float audioBuffer[samplesPerGrain];
- double frequency = 440, angle = 0;
- for(i=0; i<samplesPerGrain; i+=NUM_CHANNELS)
- {
- audioBuffer[i] = sin(angle) * windowFunction[i/NUM_CHANNELS];
- angle += frequency * TWO_PI_OVER_SAMPLE_RATE;
- }
- aiffAppendFloatingPointSamples(aiff, audioBuffer, samplesPerGrain, aiffFloatSampleType);
- aiffSaveWithFilename(aiff, "WindowFunctions.aif");
- aiffDestroy(aiff);
- return 0;
- }
Output:
Explanation of the Concepts
This example shows how to create several various window functions for creating 'grains' for use in granular synthesis. Here, for the sake of demonstration, the window function is applied to a simple audio-rate sine-wave, and the result is one very simple (and somewhat long) grain of audio.
The following graphs represent amplitude plotted as a function of time for various window functions.
SINE
The sine window function is just the top half of a sine wave, between 0 and 180 degrees:HANN
A Hann window is an entire cosine wave, between 0 and 360 degrees, but it is raised up so that it does not dip below y=0. For this reason, it is also known as a "raised cosine" window.HAMMING
An Hamming window is also a type of "raised cosine" window, but it has been raised a little further, so the bottom does not touch y=0. This type of window is often used in DFT algorithms (discussed in the chapter on Fourier Synthesis) because it produces a very accurate spectrum. It, however, is not great for granular synthesis because, since it does not reach y=0, it can cause popping noises as it is begins and ends.TUKEY
A Tukey window is a Hann window that has had its top chopped off, and the result has been stretched to fit between y=0 and y=1. The height at which it has been chopped of is known as H. Tukey windows are good for making grains out of speech. If the window is chopped off low, then it reaches its maximum amplitude quickly and stays there for a large percentage of the windows duration, which preserves the intelligibility of individual words. Higher values of H decrease the intelligibility.GAUSSIAN
A Gaussian function is the plot of the familiar "bell curve", that often represents natural probability distributions. Its shape makes it good for use here. The coefficient 'Sigma' determines the width of the function. Because the function never reaches y=0, it can cause popping as the grain begins and ends, especially for values of sigma much above 0.3. Nonetheless, in a dense, granular music, manipulating sigma gives an interesting control over the overall texture of the music. Low values of sigma produce choppy textures and higher values produce a smoother texture. For high values of sigma, popping can be avoided by multiplying the Gaussian function by a trapezoidal function (or another function that reaches 0).TRAPEZOIDAL
Trapezoidal windows are useful for convolving other window functions that do not reach y=0. Notice too, that a triangular window is just the special case of a trapezoidal window in which Slope=2;
Explanation of the Code
In this example, the window function is written into a separate buffer for before being applied to the audio buffer. The window buffer is allocated on line 22. Lines 22-40 then write a window function into the buffer, according to which lines of code are not commented out. Lines 52-59 then applies the window function to the a sine wave that is written into an audio buffer, Identical to the usage in many of the examples in the chapter on envelopes.