Created
February 13, 2014 07:18
-
-
Save apg/8971130 to your computer and use it in GitHub Desktop.
ride the wave file, man.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Compile: | |
$ LDFLAGS="-lm" make wavrider | |
Run: | |
$ ./wavrider < wavrider.c | |
$ mplayer output.wav | |
Wavrider will turn 40 characters into solid gold waves. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <math.h> | |
#define FREQ 440 | |
#define VOLUME 20000 | |
#define SAMPRATE 11025 | |
#define SECONDS .5 | |
#define CHANNELS 1 | |
#define BITDEPTH 16 | |
static int FREQS[] = { | |
32, 34, 36, 38, 41, 43, 46, 49, 51, 55, 58, 61, 65, 69, 73, 77, | |
82, 87, 92, 98, 103, 110, 116, 123, 130, 138, 146, 155, 164, 174, | |
185, 196, 207, 220, 233, 246, 261, 277, 293, 311, 329, 349, 369, 392, | |
415, 440, 466, 493, 523, 554, 587, 622, 659, 698, 739, 783, 830, 880, | |
932, 987, 1046, 1108, 1174, 1244, 1318, 1396, 1479, 1567, 1661, 1760, 1864, | |
1975, 2093, 2217, 2349, 2489, 2637, 2793, 2959, 3135, 3322, 3520, 3729, 3951, | |
4186, 4434, 4698, 4978, 5274, 5587, 5919, 6271, 6644, 7040, 7458, 7902 | |
}; | |
static unsigned char * | |
tolittle(int value, unsigned char *buf, size_t len) | |
{ | |
int i = 0; | |
for (; len > 0; len--) { | |
buf[i++] = (unsigned char) value & 255; | |
value >>= 8; | |
} | |
return buf; | |
} | |
/** Waves */ | |
static float | |
wave(int freq, int i, int sampleRate) | |
{ | |
return (float)sin((2 * M_PI) * (i / (float)sampleRate) * freq); | |
} | |
static float | |
sqwave(int freq, int i, int sampleRate) | |
{ | |
float coef = sampleRate / (float)freq; | |
return (i % (int)coef) / (coef < .5 ? 1 : -1); | |
} | |
static float | |
triwave(int freq, int i, int sampleRate) | |
{ | |
return (float)asin((float)sin((2 * M_PI) * (i / (float)sampleRate) * freq)); | |
} | |
static float | |
sawwave(int freq, int i, int sampleRate) | |
{ | |
float coef = sampleRate / (float)freq; | |
return (float)(-1 + 2 * ((i % (int)coef) / coef)); | |
} | |
static void | |
writefmt(int fd, int channels, int samprate, int bitdepth) | |
{ | |
unsigned char buf[4]; | |
write(fd, "fmt ", 4); | |
write(fd, tolittle(16, buf, 4), 4); | |
write(fd, tolittle(1, buf, 2), 2); | |
write(fd, tolittle(channels, buf, 2), 2); | |
write(fd, tolittle(samprate, buf, 4), 4); | |
/* byte rate */ | |
write(fd, tolittle(samprate * channels * bitdepth / 8, buf, 4), 4); | |
write(fd, tolittle(channels * bitdepth / 8, buf, 2), 2); | |
write(fd, tolittle(bitdepth, buf, 2), 2); | |
} | |
static void | |
writedata(int fd, int channels, int bitdepth, int *samples, int numsamples) | |
{ | |
int i; | |
unsigned char buf[4]; | |
write(fd, "data", 4); | |
/* chunk length */ | |
write(fd, tolittle(numsamples * channels * bitdepth / 8, buf, 4), 4); | |
for (i = 0; i < numsamples; i++) { | |
write(fd, tolittle(samples[i], buf, 2), 2); | |
} | |
} | |
static void | |
writefile(char *outfile, int datlen, int *samples, int numsamples) | |
{ | |
unsigned char buf[4]; | |
int fd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, 0660); | |
if (fd < 0) { | |
perror("open"); | |
exit(EXIT_FAILURE); | |
} | |
write(fd, "RIFF", 4); | |
write(fd, tolittle(datlen, buf, 4), 4); | |
write(fd, "WAVE", 4); | |
writefmt(fd, CHANNELS, SAMPRATE, BITDEPTH); | |
writedata(fd, CHANNELS, BITDEPTH, samples, numsamples); | |
close(fd); | |
} | |
static void | |
append(int *buf, int *s, float (*wav)(int, int, int), int freq, float seconds) | |
{ | |
int b = SAMPRATE * seconds; | |
int i; | |
for (i = 0; i < b; i++) { | |
buf[*s] = VOLUME * wav(freq, i, b); | |
*s += 1; | |
} | |
} | |
int | |
main(int argc, char **argv) | |
{ | |
int i, s, c; | |
int tot; | |
int samples[SAMPRATE * 20]; | |
int numsamples = SAMPRATE * 20; /* 20 seconds total */ | |
int numchars = 20 / SECONDS; | |
printf("Samples total: %d\nNum characters: %d\n", numsamples, numchars); | |
i = 0; | |
s = 0; | |
while (i < numchars) { | |
c = getc(stdin); | |
if (c >= 32 && c < 127) { | |
append(samples, &s, sawwave, FREQS[c - 32], SECONDS); | |
} | |
printf("%d ... %d ... %lf\n", s, SAMPRATE, (double)s / SAMPRATE); | |
i++; | |
} | |
/* | |
for (i = 0; i < SAMPRATE * 2; i++) { | |
samples[s++] = VOLUME * wave(FREQ * RANDOM, i, SAMPRATE); | |
} | |
for (i = 0; i < SAMPRATE * 2; i++) { | |
samples[s++] = VOLUME * sqwave(FREQ * RANDOM, i, SAMPRATE); | |
} | |
for (i = 0; i < SAMPRATE * 2; i++) { | |
samples[s++] = VOLUME * triwave(FREQ * RANDOM, i, SAMPRATE); | |
} | |
for (i = 0; i < SAMPRATE * 2; i++) { | |
samples[s++] = VOLUME * sawwave(FREQ * RANDOM, i, SAMPRATE); | |
} | |
tot = 32 + numsamples * CHANNELS * (BITDEPTH / 2); | |
*/ | |
writefile("output.wav", tot, samples, numsamples); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment