/* Example program that uses the WRAIFF utility to create 3 AIFF files. WRAIFF version 0.24, december, 2019. A tiny audiofile writing utility in C. Latest version available at: https://ecomaan.nl/c/wraiff */ #include #include #include /* For sin(). */ #include "wraiff.h" /* Also put wraiff.c in your project or makefile. */ /* Demonstrate (i.e. test) the writing of doubles to an 8 bit mono file. Passing only one single sample per call to WRAIFF_double() is not too efficient, but it is the easiest way to use the WRAIFF library. Returns non-zero in case of failure. */ static int write_double_mono(void) { const char* filename = "1-channel.aiff"; const long samplerate = 22050L; int e; WRAIFFp a; e = WRAIFF_open(&a, /* Receive pointer to WRAIFF object here. */ filename, /* String is duplicated in the object. */ samplerate, /* Number of samples per second (long). */ 1, /* Number of interleaved channels. */ 8); /* Number of bits resolution (1 to 56). */ if (e) printf("WRAIFF_open(%s)=%d!\n", filename, e); /* Sure a==NULL. */ else /* Sure a!=NULL. */ { long n; double single_sample; for (n = 0; n < 3 * samplerate; n++) /* A sinewave for 3 seconds. */ { single_sample = 0.25 * sin(0.1 * (double)n); /* 0.25 --> -12 dB. */ e = WRAIFF_double(a, /* Pointer to audiofile object. */ &single_sample, /* Pointer to data in double. */ 1); /* One single frame per call. */ if (e) { printf("WRAIFF_double()=%d!\n", e); break; } } WRAIFF_info(a, stdout); /* Print file statistics to stdout. */ e = WRAIFF_close(&a); /* Releases the WRAIFF object, rewrites the */ if (e) /* header, closes file and sets a to NULL. */ printf("WRAIFF_close(%s)=%d!\n", filename, e); } return e; } /* Demonstrate (i.e. test) the writing of floats to a 24 bit stereo file. Again, passing only 1 sampleframe per call to WRAIFF_float() is not too efficient, but it is the easiest way to use the WRAIFF library. */ static int write_float_stereo(void) { #define N_CHANNELS (2) /* For static allocation. */ const char* filename = "2-channel.aiff"; const long samplerate = 44100L; int e; WRAIFFp a; e = WRAIFF_open(&a, /* Receive ptr to WRAIFF object here. */ filename, /* String is duplicated in the object. */ samplerate, /* Number of samples per second (long). */ N_CHANNELS, /* Number of channels per frame. */ 24); /* Number of bits per sample (1 to 56). */ if (e) printf("WRAIFF_open(%s)=%d!\n", filename, e); else { long n; float single_frame[N_CHANNELS]; /* Array of interleaved data. */ for (n = 0; n < samplerate; n++) /* Sinewaves for 1 second. */ { double f = 0.1; /* First channel at (0.1 sr)/(2 PI) Hertz. */ short c; for (c = 0; c < N_CHANNELS; c++) { single_frame[c] = 0.5 * sin(f * (double)n); /* 0.5 --> -6 dB. */ f *= 1.2; /* Stack natural minor thirds (5:6). */ } e = WRAIFF_float(a, /* Pointer to audiofile object. */ single_frame, /* Pointer to array of doubles. */ 1); /* 1 single stereoframe per call. */ if (e) { printf("WRAIFF_float()=%d!\n", e); break; } } WRAIFF_info(a, stdout); /* Print file statistics to stdout. */ e = WRAIFF_close(&a); /* Releases the WRAIFF object, rewrites the */ if (e) /* header, closes file and sets a to NULL. */ printf("WRAIFF_close(%s)=%d!\n", filename, e); } return e; } /* Demonstrate (i.e. test) the writing of shorts to a 16-bit quadrophonic file. On most computers a short has 16 bits (signed). We now pass a buffer of 1024 sampleframes per call to WRAIFF_float() which is more efficient (it however complicates the code a bit further, like most optimizations do, and it also uses a bit more memory). */ static int write_short_quadro(void) { #define NUM_FRAMES (1024) /* Number of frames per buffer. */ #define NUM_CHANNELS (4) /* Number of samples per frame. */ const char* filename = "4-channel.aiff"; const long samplerate = 11025L; int e; WRAIFFp a; e = WRAIFF_open(&a, /* Receive pointer to WRAIFF object here. */ filename, /* String will be duplicated in the object. */ samplerate, /* Number of samples per second (long). */ NUM_CHANNELS, /* Number of interleaved channels. */ 16); /* Number of bits resolution (1 to 56). */ if (e) printf("WRAIFF_open(%s)=%d!\n", filename, e); /* Sure: a==NULL; */ else /* a!=NULL: */ { long togo = 2L * samplerate; /* Sinewaves for 2 seconds. */ while (togo) /* Number of sampleframes to go. */ { short buffer[NUM_FRAMES*NUM_CHANNELS]; /* Interleaved audio-data. */ long frames, b; short *sample = buffer; /* Set pointer to beginning, each time. */ if (togo > NUM_FRAMES) frames = NUM_FRAMES; else frames = togo; for (b = 0; b < frames; b++) { double frq = 0.1; /* First channel at (0.1 sr)/(2 PI) Hertz. */ short c; /* To count number of channels. */ for (c = 0; c < NUM_CHANNELS; c++) { double signal = 16384.0 * sin(frq * (double)togo); /* Amp=16384 gives -6 dB. */ if (signal >= 0.0) /* Convert double to short */ signal += 0.5; /* using correct rounding. */ else signal -= 0.5; *sample++ = (short)signal; /* Store and advance pointer. */ frq *= 1.25; /* Stack natural major thirds (4:5). */ } togo--; /* Count backwards. */ } e = WRAIFF_short(a, /* Pointer to audiofile object. */ buffer, /* Pointer to array of frames. */ frames); /* 1024 frames (4096 samples), */ if (e) /* some less at the last call. */ { printf("WRAIFF_short()=%d!\n", e); break; } } WRAIFF_info(a, stdout); /* Print file statistics to stdout. */ e = WRAIFF_close(&a); /* Releases the WRAIFF object, rewrites the */ if (e) /* header, closes file and sets a to NULL. */ printf("WRAIFF_close(%s)=%d!\n", filename, e); } return e; } int main(void) { int e = 0; if ((e = write_double_mono())) /* Generate 3 audiofiles. */ printf("write_double_mono failed!\n"); else if ((e = write_float_stereo())) printf("write_float_stereo failed!\n"); else if ((e = write_short_quadro())) printf("write_short_quadro failed!\n"); else printf("Ok.\n"); if (e) e = 1; return e; }