Created
August 8, 2023 12:47
-
-
Save fredrb/d2fbfe5787e4e78c4a1ab0ded46d33ef to your computer and use it in GitHub Desktop.
Playing A4 with SDL
This file contains 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 "SDL2/SDL_audio.h" | |
#include "SDL2/SDL_timer.h" | |
#include <SDL2/SDL.h> | |
#include <errno.h> | |
#include <math.h> | |
#include <stdbool.h> | |
#include <stdio.h> | |
const int SAMPLE_RATE = 44100; | |
const int BUFFER_SIZE = 4096; | |
const float A4_OSC = (float)SAMPLE_RATE / 440.00f; | |
FILE *plot_output; | |
typedef struct { | |
float current_step; | |
float step_size; | |
float volume; | |
} oscillator; | |
oscillator oscillate(float rate, float volume) { | |
oscillator o = { | |
.current_step = 0, | |
.volume = volume, | |
.step_size = (2 * M_PI) / rate, | |
}; | |
return o; | |
} | |
float next(oscillator *os) { | |
float ret = sinf(os->current_step); | |
os->current_step += os->step_size; | |
return ret * os->volume; | |
} | |
oscillator *A4_oscillator; | |
void oscillator_callback(void *userdata, Uint8 *stream, int len) { | |
float *fstream = (float *)stream; | |
for (int i = 0; i < BUFFER_SIZE; i++) { | |
float v = next(A4_oscillator); | |
fstream[i] = v; | |
#ifdef PLOT | |
fprintf(plot_output, "%.5f\n", fstream[i]); | |
#endif | |
} | |
} | |
void close() { | |
#ifdef PLOT | |
fclose(plot_output); | |
#endif | |
} | |
int main() { | |
if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_EVENTS) < 0) { | |
printf("Failed to initialize SDL: %s\n", SDL_GetError()); | |
return 1; | |
} | |
#ifdef PLOT | |
plot_output = fopen("plot_output", "w"); | |
if (plot_output == NULL) { | |
printf("Failed to open file: %d", errno); | |
return 1; | |
} | |
#endif | |
oscillator a4 = oscillate(A4_OSC, 0.8f); | |
A4_oscillator = &a4; | |
SDL_AudioSpec spec = { | |
.format = AUDIO_F32, | |
.channels = 1, | |
.freq = SAMPLE_RATE, | |
.samples = 4096, | |
.callback = oscillator_callback, | |
}; | |
if (SDL_OpenAudio(&spec, NULL) < 0) { | |
printf("Failed to open Audio Device: %s\n", SDL_GetError()); | |
return 1; | |
} | |
SDL_PauseAudio(0); | |
while (true) { | |
SDL_Event e; | |
while (SDL_PollEvent(&e)) { | |
switch (e.type) { | |
case SDL_QUIT: | |
close(); | |
return 0; | |
} | |
} | |
} | |
close(); | |
return 0; | |
} |
This file contains 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
import matplotlib.pyplot as plt | |
import numpy as np | |
plt.rcParams["figure.figsize"] = [7.50, 3.50] | |
plt.rcParams["figure.autolayout"] = True | |
with open("plot_output") as f: | |
plt.style.use('dark_background') | |
fig, axs = plt.subplots(1, 1) | |
num_samples = 441 | |
lines = f.readlines()[:num_samples] | |
y = [float(i.strip()) for i in lines] | |
ticks = range(len(lines)) | |
axs.plot(ticks, y) | |
axs.set_xticks(np.arange(0, num_samples, num_samples//10), np.arange(0, 11, 1)) | |
axs.set_yticks([-1, -0.5, 0, 0.5, 1]) | |
plt.ylabel("Amplitude") | |
plt.xlabel("Time (ms)") | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can compile this with plot output as:
Then run
plot.py
to consumeplot_output
and generate the sine wave graphs.