Last active
May 10, 2025 14:10
-
-
Save ske2004/af02832b9a2566ec796b48dc0461be68 to your computer and use it in GitHub Desktop.
Generates Mario Theme Song
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 <math.h> | |
#define NUM_SAMPLES 44100 | |
#define PI 3.14159265 | |
// ------ NOTE IDS ------ | |
#define C_ 0 | |
#define CS 1 | |
#define D_ 2 | |
#define DS 3 | |
#define E_ 4 | |
#define F_ 5 | |
#define FS 6 | |
#define G_ 7 | |
#define GS 8 | |
#define A_ 9 | |
#define AS 10 | |
#define B_ 11 | |
#define MKNOTE(oct, note, frac) ((Note){(oct)*12+(note),1.0/(frac)}) | |
typedef struct { | |
int note; | |
float duration; | |
} Note; | |
// ------ EXAMPLE ------ | |
Note SUPER_MARIO_THEME_SONG[] = { | |
MKNOTE(4, E_, 4), | |
MKNOTE(4, E_, 2), | |
MKNOTE(4, E_, 2), | |
MKNOTE(4, C_, 4), | |
MKNOTE(4, E_, 2), | |
MKNOTE(4, G_, 1), | |
MKNOTE(3, G_, 1), | |
MKNOTE(4, C_, 1.5), | |
MKNOTE(3, G_, 1.5), | |
MKNOTE(3, E_, 2), | |
MKNOTE(3, A_, 2), | |
MKNOTE(3, B_, 2), | |
MKNOTE(3, AS, 4), | |
MKNOTE(3, A_, 2), | |
MKNOTE(3, G_, 4), | |
MKNOTE(4, E_, 4), | |
MKNOTE(4, G_, 4), | |
MKNOTE(4, A_, 2), | |
MKNOTE(4, F_, 4), | |
MKNOTE(4, G_, 2), | |
MKNOTE(4, E_, 2), | |
MKNOTE(4, C_, 4), | |
MKNOTE(4, D_, 4), | |
MKNOTE(3, B_, 1), | |
MKNOTE(4, C_, 1.5), | |
MKNOTE(3, G_, 1.5), | |
MKNOTE(3, E_, 2), | |
MKNOTE(3, A_, 2), | |
MKNOTE(3, B_, 2), | |
MKNOTE(3, AS, 4), | |
MKNOTE(3, A_, 2), | |
MKNOTE(3, G_, 4), | |
MKNOTE(4, E_, 4), | |
MKNOTE(4, G_, 4), | |
MKNOTE(4, A_, 2), | |
MKNOTE(4, F_, 4), | |
MKNOTE(4, G_, 2), | |
MKNOTE(4, E_, 2), | |
MKNOTE(4, C_, 4), | |
MKNOTE(4, D_, 4), | |
MKNOTE(3, B_, 1), | |
}; | |
const double noteFrequencies[] = { | |
261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88 | |
}; | |
int convertNote(int noteNumber) { | |
int octave = noteNumber/12; | |
double freq = noteFrequencies[noteNumber%12]*pow(2, octave-4); | |
return (int)(freq + 0.5); | |
} | |
void generateWaveFile(const char* filename, Note* notes, int numNotes, int bpm) { | |
float bps = bpm/60.0f; | |
int i, j, k = 0; | |
int overallNumSamples = 0; | |
for (i = 0; i < numNotes; i++) { | |
overallNumSamples += (notes[i].duration/bps)*NUM_SAMPLES; | |
} | |
short waveform[overallNumSamples]; | |
// Generate square wave | |
for (i = 0; i < numNotes; i++) { | |
int note = convertNote(notes[i].note); | |
float duration = notes[i].duration/2.0; | |
int samplesPerCycle = 44100 / note; | |
int numSamples = (int)(duration * 44100); | |
for (j = 0; j < numSamples; j++) { | |
if (j % samplesPerCycle < samplesPerCycle / 2) { | |
waveform[k++] = 32767/2; | |
} else { | |
waveform[k++] = -32767/2; | |
} | |
} | |
} | |
// Write the samples to a file in .wav format | |
FILE *fp = fopen(filename, "wb"); | |
short format = 1; | |
short numChannels = 1; | |
short bitsPerSample = 16; | |
int byteRate = NUM_SAMPLES * numChannels * bitsPerSample / 8; | |
short blockAlign = numChannels * bitsPerSample / 8; | |
int dataSize = overallNumSamples * 2; | |
int chunkSize = 16; | |
int sampleRate = NUM_SAMPLES; | |
fwrite("RIFF", 4, 1, fp); | |
int riffSize = 4 + (8 + chunkSize) + (8 + dataSize); | |
fwrite(&riffSize, 4, 1, fp); | |
fwrite("WAVE", 4, 1, fp); | |
fwrite("fmt ", 4, 1, fp); | |
fwrite(&chunkSize, 4, 1, fp); | |
fwrite(&format, 2, 1, fp); | |
fwrite(&numChannels, 2, 1, fp); | |
fwrite(&sampleRate, 4, 1, fp); | |
fwrite(&byteRate, 4, 1, fp); | |
fwrite(&blockAlign, 2, 1, fp); | |
fwrite(&bitsPerSample, 2, 1, fp); | |
fwrite("data", 4, 1, fp); | |
fwrite(&dataSize, 4, 1, fp); | |
fwrite(waveform, 2, overallNumSamples, fp); | |
fclose(fp); | |
} | |
int main() { | |
int numNotes = sizeof(SUPER_MARIO_THEME_SONG) / sizeof(SUPER_MARIO_THEME_SONG[0]); | |
generateWaveFile("mario.wav", SUPER_MARIO_THEME_SONG, numNotes, 108); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment