Skip to content

Instantly share code, notes, and snippets.

@apg
Created February 13, 2014 07:18
Show Gist options
  • Save apg/8971130 to your computer and use it in GitHub Desktop.
Save apg/8971130 to your computer and use it in GitHub Desktop.
ride the wave file, man.
Compile:
$ LDFLAGS="-lm" make wavrider
Run:
$ ./wavrider < wavrider.c
$ mplayer output.wav
Wavrider will turn 40 characters into solid gold waves.
#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