Created
April 29, 2018 23:02
-
-
Save CandyGumdrop/c989508fadc284de71c97c46cbf47c71 to your computer and use it in GitHub Desktop.
Sound of the C
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 <stdint.h> | |
#include <math.h> | |
#define RATE 44100.0 | |
#define PI 3.1415926535897932384626 | |
#define F_DOMAIN_SIZE 64 | |
#define SONG_LENGTH 96 | |
#define CHORD_LENGTH 4 | |
int song[SONG_LENGTH][CHORD_LENGTH + 1] = { | |
{40, 0, 0, 0, 0}, | |
{40, 44, 0, 0, 0}, | |
{40, 44, 47, 0, 0}, | |
{40, 44, 47, 52, 0}, | |
{35, 0, 0, 0, 0}, | |
{35, 39, 0, 0, 0}, | |
{35, 39, 42, 0, 0}, | |
{35, 39, 42, 47, 0}, | |
{37, 0, 0, 0, 0}, | |
{37, 40, 0, 0, 0}, | |
{37, 40, 44, 0, 0}, | |
{37, 40, 44, 49, 0}, | |
{32, 0, 0, 0, 0}, | |
{32, 35, 0, 0, 0}, | |
{32, 35, 39, 0, 0}, | |
{32, 35, 39, 44, 0}, | |
{33, 0, 0, 0, 0}, | |
{33, 37, 0, 0, 0}, | |
{33, 37, 40, 0, 0}, | |
{33, 37, 40, 45, 0}, | |
{28, 0, 0, 0, 0}, | |
{28, 32, 0, 0, 0}, | |
{28, 32, 35, 0, 0}, | |
{28, 32, 35, 40, 0}, | |
{33, 0, 0, 0, 0}, | |
{33, 37, 0, 0, 0}, | |
{33, 37, 40, 0, 0}, | |
{33, 37, 40, 45, 0}, | |
{35, 0, 0, 0, 0}, | |
{35, 39, 0, 0, 0}, | |
{35, 39, 42, 0, 0}, | |
{35, 39, 42, 47, 0}, | |
{40, 0, 0, 0, 56}, | |
{40, 44, 0, 0, 56}, | |
{40, 44, 47, 0, 56}, | |
{40, 44, 47, 52, 56}, | |
{35, 0, 0, 0, 54}, | |
{35, 39, 0, 0, 54}, | |
{35, 39, 42, 0, 54}, | |
{35, 39, 42, 47, 54}, | |
{37, 0, 0, 0, 52}, | |
{37, 40, 0, 0, 52}, | |
{37, 40, 44, 0, 52}, | |
{37, 40, 44, 49, 52}, | |
{32, 0, 0, 0, 51}, | |
{32, 35, 0, 0, 51}, | |
{32, 35, 39, 0, 51}, | |
{32, 35, 39, 44, 51}, | |
{33, 0, 0, 0, 49}, | |
{33, 37, 0, 0, 49}, | |
{33, 37, 40, 0, 49}, | |
{33, 37, 40, 45, 49}, | |
{28, 0, 0, 0, 47}, | |
{28, 32, 0, 0, 47}, | |
{28, 32, 35, 0, 47}, | |
{28, 32, 35, 40, 47}, | |
{33, 0, 0, 0, 49}, | |
{33, 37, 0, 0, 49}, | |
{33, 37, 40, 0, 49}, | |
{33, 37, 40, 45, 49}, | |
{35, 0, 0, 0, 51}, | |
{35, 39, 0, 0, 51}, | |
{35, 39, 42, 0, 52}, | |
{35, 39, 42, 47, 54}, | |
{40, 0, 0, 0, 56}, | |
{40, 44, 0, 0, 56}, | |
{40, 44, 47, 0, 56}, | |
{40, 44, 47, 52, 56}, | |
{35, 0, 0, 0, 54}, | |
{35, 39, 0, 0, 57}, | |
{35, 39, 42, 0, 56}, | |
{35, 39, 42, 47, 54}, | |
{37, 0, 0, 0, 52}, | |
{37, 40, 0, 0, 52}, | |
{37, 40, 44, 0, 52}, | |
{37, 40, 44, 49, 52}, | |
{32, 0, 0, 0, 51}, | |
{32, 35, 0, 0, 56}, | |
{32, 35, 39, 0, 59}, | |
{32, 35, 39, 44, 61}, | |
{33, 0, 0, 0, 57}, | |
{33, 37, 0, 0, 56}, | |
{33, 37, 40, 0, 54}, | |
{33, 37, 40, 45, 57}, | |
{28, 0, 0, 0, 56}, | |
{28, 32, 0, 0, 54}, | |
{28, 32, 35, 0, 52}, | |
{28, 32, 35, 40, 47}, | |
{33, 0, 0, 0, 49}, | |
{33, 37, 0, 0, 47}, | |
{33, 37, 40, 0, 45}, | |
{33, 37, 40, 45, 52}, | |
{35, 0, 0, 0, 51}, | |
{35, 39, 0, 0, 52}, | |
{35, 39, 42, 0, 51}, | |
{35, 39, 42, 47, 52} | |
}; | |
struct freq_domain { | |
double a[F_DOMAIN_SIZE], b[F_DOMAIN_SIZE]; | |
}; | |
static double note_freq(double note) | |
{ | |
return pow(2, (note - 49) / 12.0) * 440; | |
} | |
static void square_domain(double amplitude, struct freq_domain *domain) | |
{ | |
int n; | |
domain->a[0] = 0; | |
for (n = 1; n < F_DOMAIN_SIZE; n++) { | |
domain->a[n] = n % 2 ? sin(n * PI / 2) * 2 * amplitude / (n * PI) : 0; | |
domain->b[n] = 0; | |
} | |
} | |
static void lowpass(struct freq_domain *domain, double position) | |
{ | |
int n; | |
for (n = 1; n < F_DOMAIN_SIZE; n++) { | |
double filter; | |
filter = (1 - exp(n - position)); | |
if (filter < 0) { | |
filter = 0; | |
} | |
domain->a[n] *= filter; | |
domain->b[n] *= filter; | |
} | |
} | |
static double wave(struct freq_domain *domain, double time, double freq) | |
{ | |
int n; | |
double x; | |
x = domain->a[0]; | |
for (n = 1; n < F_DOMAIN_SIZE; n++) { | |
x += domain->a[n] * cos(2 * PI * freq * time * n); | |
x += domain->b[n] * sin(2 * PI * freq * time * n); | |
} | |
return x; | |
} | |
int main(void) | |
{ | |
uint64_t i; | |
uint32_t filesize, datasize, chunk, srate, brate; | |
uint16_t type, channels, balign, depth; | |
int n; | |
struct freq_domain square, thing; | |
square_domain(INT16_MAX / 4, &square); | |
thing.a[0] = 0; | |
for (n = 1; n < F_DOMAIN_SIZE; n++) { | |
thing.a[n] = n % 2 ? INT16_MAX / 12 / (n + 1) : INT16_MAX / 16 / (n + 1); | |
thing.b[n] = 0; | |
} | |
datasize = 2 * 2 * SONG_LENGTH * 10000; | |
filesize = datasize + 38; | |
chunk = 16; | |
type = 1; | |
channels = 2; | |
srate = RATE; | |
depth = 16; | |
brate = channels * srate * depth / 8; | |
balign = channels * depth / 8; | |
fwrite("RIFF", 1, 4, stdout); | |
fwrite(&filesize, sizeof filesize, 1, stdout); | |
fwrite("WAVE", 1, 4, stdout); | |
fwrite("fmt ", 1, 4, stdout); | |
fwrite(&chunk, sizeof chunk, 1, stdout); | |
fwrite(&type, sizeof type, 1, stdout); | |
fwrite(&channels, sizeof channels, 1, stdout); | |
fwrite(&srate, sizeof srate, 1, stdout); | |
fwrite(&brate, sizeof brate, 1, stdout); | |
fwrite(&balign, sizeof balign, 1, stdout); | |
fwrite(&depth, sizeof depth, 1, stdout); | |
fwrite("data", 1, 4, stdout); | |
fwrite(&datasize, sizeof datasize, 1, stdout); | |
for (i = 0; i < datasize; i++) { | |
int16_t left, right; | |
int cnote, *chord; | |
left = 0; | |
right = 0; | |
chord = song[(i / 10000) % SONG_LENGTH]; | |
for (cnote = 0; cnote < CHORD_LENGTH; cnote++) { | |
if (chord[cnote]) { | |
int16_t sound; | |
sound = wave(&thing, i / RATE, note_freq(chord[cnote])); | |
left += sound * 0.7; | |
right += sound * 0.3; | |
} | |
} | |
if (chord[CHORD_LENGTH]) { | |
int16_t sound; | |
sound = wave(&square, i / RATE, | |
note_freq(chord[CHORD_LENGTH] | |
+ sin(i / 1000.0) * 0.0006)); | |
left += sound; | |
right += sound; | |
} | |
fwrite(&left, sizeof left, 1, stdout); | |
fwrite(&right, sizeof right, 1, stdout); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment