-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
113 lines (91 loc) · 2.48 KB
/
main.cpp
File metadata and controls
113 lines (91 loc) · 2.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <SDL2/SDL.h>
#include <cmath>
#include <unordered_map>
class Synthesizer {
private:
float m_timestep = 0;
float m_phasestep = 0;
float m_phase = 0;
float m_freq;
bool m_playing = false;
public:
Synthesizer(int sample_rate) { m_timestep = 1.f / sample_rate; }
void synthesize(float *buffer, size_t buffer_size) {
for (int i = 0; i < buffer_size; i++) {
if (!m_playing && m_phase < 0.001f) {
return;
}
buffer[i] = sinf(m_phase * 2 * M_PI) * 0.5f;
m_phase += m_phasestep;
m_phase = fmodf(m_phase, 1.f);
}
}
void play(float freq) {
m_phasestep = m_timestep * freq;
m_freq = freq;
m_playing = true;
}
void stop() { m_playing = false; }
};
std::unordered_map<SDL_Keycode, int> piano_keys = {
{SDLK_z, 0}, {SDLK_s, 1}, {SDLK_x, 2}, {SDLK_d, 3},
{SDLK_c, 4}, {SDLK_v, 5}, {SDLK_g, 6}, {SDLK_b, 7},
{SDLK_h, 8}, {SDLK_n, 9}, {SDLK_j, 10}, {SDLK_m, 11},
};
float get_freq(SDL_Keycode key) {
return 440.f * powf(2.f, piano_keys[key] / 12.f);
}
int main() {
SDL_Init(SDL_INIT_EVERYTHING);
Synthesizer synth(48000);
SDL_AudioSpec spec;
spec.freq = 48000;
spec.channels = 1;
spec.format = AUDIO_F32SYS;
spec.samples = 256;
spec.callback = [](void *userdata, Uint8 *bytes, int len) {
Synthesizer *synth = (Synthesizer *)userdata;
memset(bytes, 0, len);
synth->synthesize((float *)bytes, len / sizeof(float));
};
spec.userdata = &synth;
SDL_AudioDeviceID device = SDL_OpenAudioDevice(nullptr, 0, &spec, &spec, 0);
SDL_PauseAudioDevice(device, 0);
SDL_Window *window = SDL_CreateWindow("synth", 0, 0, 800, 600, 0);
SDL_Surface *surface = SDL_GetWindowSurface(window);
SDL_Event event;
bool running = true;
// 16ms of latency
const int lag = 1000 / 60;
Uint64 start, elapsed;
SDL_Keycode pressed_key;
while (running) {
start = SDL_GetTicks64();
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
running = false;
break;
case SDL_KEYDOWN:
pressed_key = event.key.keysym.sym;
if (piano_keys.count(pressed_key)) {
synth.play(get_freq(pressed_key));
}
break;
case SDL_KEYUP:
if (event.key.keysym.sym == pressed_key) {
synth.stop();
}
break;
default:
break;
}
}
SDL_UpdateWindowSurface(window);
elapsed = SDL_GetTicks() - start;
if (lag > elapsed) {
SDL_Delay(lag - elapsed);
}
}
SDL_Quit();
}