diff options
| author | frosty <gabriel@bwaaa.monster> | 2026-05-16 01:28:17 -0400 |
|---|---|---|
| committer | frosty <gabriel@bwaaa.monster> | 2026-05-16 01:28:17 -0400 |
| commit | 66deee38def0f968b9a6740e6cc5186cbfb1bc57 (patch) | |
| tree | 339512f0f74f4f2cee50947aaab5d59371c65f32 /src/Main.c | |
| download | PNDacc-66deee38def0f968b9a6740e6cc5186cbfb1bc57.tar.gz | |
antigizmodic commit
Diffstat (limited to 'src/Main.c')
| -rw-r--r-- | src/Main.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/Main.c b/src/Main.c new file mode 100644 index 0000000..d83511a --- /dev/null +++ b/src/Main.c @@ -0,0 +1,103 @@ +#include "Config.h" +#include <SDL3/SDL.h> +#include <SDL3_image/SDL_image.h> +#include <math.h> +#include <pulse/error.h> +#include <pulse/simple.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> + +SDL_AtomicInt is_speaking; +SDL_AtomicInt app_running; +float shared_rms = 0.0f; + +int SDLCALL audio_thread_func(void *data) { + (void)data; + pa_sample_spec ss = { + .format = PA_SAMPLE_S16LE, .rate = SAMPLE_RATE, .channels = 1}; + pa_buffer_attr attr = {.maxlength = -1, + .tlength = -1, + .prebuf = -1, + .minreq = -1, + .fragsize = BUFFER_SIZE * 2}; + int error; + pa_simple *s = pa_simple_new(NULL, "PNDacc", PA_STREAM_RECORD, NULL, "Record", + &ss, NULL, &attr, &error); + if (!s) + return -1; + int16_t buffer[BUFFER_SIZE]; + while (SDL_GetAtomicInt(&app_running)) { + if (pa_simple_read(s, buffer, sizeof(buffer), &error) < 0) + break; + double sum_squares = 0; + for (int i = 0; i < BUFFER_SIZE; i++) + sum_squares += (double)buffer[i] * buffer[i]; + float rms = (float)sqrt(sum_squares / BUFFER_SIZE); + shared_rms = rms; + SDL_SetAtomicInt(&is_speaking, rms > VOLUME_THRESHOLD ? 1 : 0); + } + pa_simple_free(s); + return 0; +} + +int main(void) { + SDL_SetAtomicInt(&app_running, 1); + if (!SDL_Init(SDL_INIT_VIDEO)) + return 1; + SDL_Window *window; + SDL_Renderer *renderer; + if (!SDL_CreateWindowAndRenderer("PNDacc", 600, 600, 0, &window, &renderer)) + return 1; + SDL_Texture *tex = IMG_LoadTexture(renderer, "profile.png"); + if (!tex) + fprintf(stderr, "[ERROR] 'profile.png' not found!\n"); + SDL_Thread *audio_thread = + SDL_CreateThread(audio_thread_func, "AudioThread", NULL); + float visual_rms = 0.0f; + while (SDL_GetAtomicInt(&app_running)) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_EVENT_QUIT) + SDL_SetAtomicInt(&app_running, 0); + } + float target_rms = shared_rms; + if (target_rms < VOLUME_THRESHOLD) + target_rms = 0.0f; + visual_rms += (target_rms - visual_rms) * LERP_SPEED; + SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); + SDL_RenderClear(renderer); + float volume_norm = visual_rms / MAX_VOLUME_REF; + if (volume_norm > 1.0f) + volume_norm = 1.0f; + float stretch_y = 1.0f + (volume_norm * SQUASH_STRETCH_INTENSITY); + float squash_x = 1.0f - (volume_norm * SQUASH_STRETCH_INTENSITY * 0.6f); + uint64_t ticks = SDL_GetTicks(); + float bob = sinf(ticks * IDLE_BOB_SPEED) * IDLE_BOB_AMP; + float tilt = sinf(ticks * (IDLE_BOB_SPEED * 0.7f)) * IDLE_TILT_AMP; + if (tex) { + float img_w, img_h; + SDL_GetTextureSize(tex, &img_w, &img_h); + float scale = 450.0f / (img_h > img_w ? img_h : img_w); + float base_w = img_w * scale; + float base_h = img_h * scale; + float final_w = base_w * squash_x; + float final_h = base_h * stretch_y; + SDL_FRect dst = {300.0f - (final_w / 2.0f), 550.0f - final_h + bob, + final_w, final_h}; + SDL_FPoint origin = {final_w / 2.0f, final_h}; + SDL_RenderTextureRotated(renderer, tex, NULL, &dst, (double)tilt, &origin, + SDL_FLIP_NONE); + } + SDL_RenderPresent(renderer); + SDL_Delay(8); + } + SDL_SetAtomicInt(&app_running, 0); + SDL_WaitThread(audio_thread, NULL); + if (tex) + SDL_DestroyTexture(tex); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + return 0; +} |
