aboutsummaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
authorspl3g <spleefer6@yandex.ru>2025-10-02 18:52:47 +0300
committerspl3g <spleefer6@yandex.ru>2025-10-02 19:02:59 +0300
commit5fad25abc6ab0632b8594c84f59fa5c1eec06d2f (patch)
tree46bc6d9aaa1e72f0fe8877aedab8b09cb3f88c54 /src/main.c
parent136d9e824a583977d798d934bbd3b8089d769668 (diff)
Replace raylib with sdl3
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c238
1 files changed, 160 insertions, 78 deletions
diff --git a/src/main.c b/src/main.c
index f8972c1..3a3a5dc 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,112 +1,194 @@
-#include <stdio.h>
-#include "sounds.h"
#include <alsa/asoundlib.h>
-#include <raylib.h>
#include <pthread.h>
-#include <stdbool.h>
+#include <stdio.h>
+
+#include "clay/clay.h"
+
+#define SDL_MAIN_USE_CALLBACKS 1
+#include <SDL3/SDL.h>
+#include <SDL3/SDL_main.h>
+#include <SDL3/SDL_scancode.h>
+#include <SDL3/SDL_keycode.h>
+
+#include "sounds.h"
+
+const int SCREEN_FPS = 60;
+const int SCREEN_TICKS_PER_FRAME = 1000 / SCREEN_FPS;
typedef struct {
char key;
float freq;
} freq_map;
-int main() {
+typedef struct {
+ SDL_Window *window;
+ SDL_Renderer *renderer;
+ bool last_keys[12];
+
snd_pcm_t *sound_device;
+ message_queue msg_queue;
+ pthread_t sound_thread;
+} app_state;
+
+int init_sounds(app_state *state) {
int err;
- err = snd_pcm_open(&sound_device, "default", SND_PCM_STREAM_PLAYBACK, 0);
+ err =
+ snd_pcm_open(&state->sound_device, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) {
- printf("error: failed to open device: %s", snd_strerror(err));
- return 1;
+ printf("error: failed to open device: %s", snd_strerror(err));
+ return err;
}
- err = set_hw_params(sound_device);
+ err = set_hw_params(state->sound_device);
if (err < 0) {
- printf("error: failed to set parameters: %s", snd_strerror(err));
- return 1;
+ printf("error: failed to set parameters: %s", snd_strerror(err));
+ return err;
}
- SetConfigFlags(FLAG_WINDOW_RESIZABLE);
- InitWindow(800, 800, "crynth");
- SetTargetFPS(60);
-
- message_queue queue;
- mqueue_init(&queue);
+ mqueue_init(&state->msg_queue);
- sound_thread_meta sound_thread_params = {
- .pcm = sound_device,
- .queue = &queue,
- };
+ sound_thread_meta *sound_thread_params = malloc(sizeof(sound_thread_meta));
+ sound_thread_params->pcm = state->sound_device;
+ sound_thread_params->queue = &state->msg_queue;
pthread_t sound_thread;
- pthread_create(&sound_thread, NULL, sound_thread_start, &sound_thread_params);
-
- /* synth_message param_message = { */
- /* .type = MSG_PARAM_CHANGE, */
- /* .param_change = { */
- /* .param_type = PARAM_OSC, */
- /* .value = OSC_SINE, */
- /* }, */
- /* }; */
- /* mqueue_push(&queue, param_message); */
- /* param_message = (synth_message){ */
- /* .type = MSG_PARAM_CHANGE, */
- /* .param_change = { */
- /* .param_type = PARAM_VOLUME, */
- /* .value = 0.2, */
- /* }, */
- /* }; */
- /* mqueue_push(&queue, param_message); */
-
- int keys[12] = {
- KEY_Z,
- KEY_S,
- KEY_X,
- KEY_D,
- KEY_C,
- KEY_V,
- KEY_G,
- KEY_B,
- KEY_H,
- KEY_N,
- KEY_J,
- KEY_M,
+ pthread_create(&sound_thread, NULL, sound_thread_start, sound_thread_params);
+
+ state->sound_thread = sound_thread;
+
+ synth_message param_message = {
+ .type = MSG_PARAM_CHANGE,
+ .param_change =
+ {
+ .param_type = PARAM_OSC,
+ .value = OSC_SQUARE,
+ },
};
+ mqueue_push(&state->msg_queue, param_message);
+ param_message = (synth_message){
+ .type = MSG_PARAM_CHANGE,
+ .param_change =
+ {
+ .param_type = PARAM_VOLUME,
+ .value = 1,
+ },
+ };
+ mqueue_push(&state->msg_queue, param_message);
+ return 0;
+}
+
+SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
+ app_state *state = malloc(sizeof(app_state));
+ *appstate = state;
- while (!WindowShouldClose()) {
+ if (!SDL_Init(SDL_INIT_VIDEO)) {
+ printf("Couldn't initialize SDL: %s", SDL_GetError());
+ return SDL_APP_FAILURE;
+ }
+
+ if (!SDL_CreateWindowAndRenderer("crynth", 640, 480, 0, &state->window,
+ &state->renderer)) {
+ printf("Couldn't create window/renderer: %s", SDL_GetError());
+ return SDL_APP_FAILURE;
+ }
+
+ if (init_sounds(state) != 0) {
+ return SDL_APP_FAILURE;
+ }
+
+ return SDL_APP_CONTINUE;
+}
+
+
+SDL_AppResult SDL_AppIterate(void *appstate) {
+ app_state *state = appstate;
+
+ int start_tick = SDL_GetTicks();
+
+ const double now = ((double)SDL_GetTicks()) / 1000.0;
+ const float red = (float)(0.5 + 0.5 * SDL_sin(now));
+ const float green = (float)(0.5 + 0.5 * SDL_sin(now + SDL_PI_D * 2 / 3));
+ const float blue = (float)(0.5 + 0.5 * SDL_sin(now + SDL_PI_D * 4 / 3));
+ SDL_SetRenderDrawColorFloat(state->renderer, red, green, blue, SDL_ALPHA_OPAQUE_FLOAT);
+
+ SDL_RenderClear(state->renderer);
+
+ SDL_RenderPresent(state->renderer);
+
+ int end_tick = SDL_GetTicks();
+ int frame_ticks = end_tick - start_tick;
+
+ if (frame_ticks < SCREEN_TICKS_PER_FRAME) {
+ SDL_Delay(SCREEN_TICKS_PER_FRAME - frame_ticks);
+ }
+
+ return SDL_APP_CONTINUE;
+}
+
+SDL_Keycode keys[12] = {
+ SDL_SCANCODE_Z, SDL_SCANCODE_S,
+ SDL_SCANCODE_X, SDL_SCANCODE_D,
+ SDL_SCANCODE_C,
+ SDL_SCANCODE_V, SDL_SCANCODE_G,
+ SDL_SCANCODE_B, SDL_SCANCODE_H,
+ SDL_SCANCODE_N, SDL_SCANCODE_J,
+ SDL_SCANCODE_M,
+};
+
+SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
+ app_state *state = appstate;
+
+ switch (event->type) {
+ case SDL_EVENT_QUIT: {
+ return SDL_APP_SUCCESS;
+ }
+ case SDL_EVENT_KEY_DOWN: {
for (int i = 0; i < 12; i++) {
- if (IsKeyPressed(keys[i])) {
- synth_message message = {
+ if (event->key.scancode == keys[i]) {
+ if (state->last_keys[i]) {
+ break;
+ }
+ state->last_keys[i] = true;
+
+ mqueue_push(&state->msg_queue, (synth_message){
.type = MSG_NOTE_ON,
- .note = {
- .note_id = i,
- },
- };
- mqueue_push(&queue, message);
+ .note = { .note_id = i },
+ });
}
-
- if (IsKeyReleased(keys[i])) {
- synth_message message = {
+ }
+ break;
+ }
+
+ case SDL_EVENT_KEY_UP: {
+ for (int i = 0; i < 12; i++) {
+ if (event->key.scancode == keys[i]) {
+ if (!state->last_keys[i]) {
+ break;
+ }
+ state->last_keys[i] = false;
+ mqueue_push(&state->msg_queue, (synth_message){
.type = MSG_NOTE_OFF,
- .note = {
- .note_id = i,
- },
- };
- mqueue_push(&queue, message);
+ .note = { .note_id = i },
+ });
}
}
+ break;
+ }
- BeginDrawing();
- ClearBackground(RAYWHITE);
- EndDrawing();
+ default: {};
}
+ return SDL_APP_CONTINUE;
+}
- synth_message stop_msg = {.type = MSG_STOP};
- mqueue_push(&queue, stop_msg);
- CloseWindow();
+void SDL_AppQuit(void *appstate, SDL_AppResult result) {
+ app_state *state = appstate;
- pthread_join(sound_thread, NULL);
- check(snd_pcm_close(sound_device));
+ message_queue *queue = &state->msg_queue;
- return 0;
+ synth_message stop_msg = {.type = MSG_STOP};
+ mqueue_push(queue, stop_msg);
+
+ pthread_join(state->sound_thread, NULL);
+ check(snd_pcm_close(state->sound_device));
}