From c2fec4c197637cb4795e1a52ebd54d1a40cc31e0 Mon Sep 17 00:00:00 2001 From: sandyx Date: Wed, 25 Sep 2024 15:19:43 -0500 Subject: [PATCH] bendy, visuals --- penger.png | Bin 0 -> 5329 bytes src/main.c | 131 +++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 106 insertions(+), 25 deletions(-) create mode 100644 penger.png diff --git a/penger.png b/penger.png new file mode 100644 index 0000000000000000000000000000000000000000..03360e85dc2815bc2c1a9b9dbd58bcad4601c991 GIT binary patch literal 5329 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 literal 0 HcmV?d00001 diff --git a/src/main.c b/src/main.c index 49ab362..6b61c75 100644 --- a/src/main.c +++ b/src/main.c @@ -16,8 +16,10 @@ char *window_title = "synthesizer"; const int sample_rate = 44100; float duration = 1.0f; float pcm_volume = 10000.0f; -const float pitch_standard = 440.0; //A440 +const float pitch_standard = 480.0; //A440 int active_notes = 0; +float freqmod = 0.5f; //for pitch bending +Color visual; //convert semitone starting from pitch_standard to frequency float semitone(float semitone) { @@ -34,7 +36,7 @@ typedef struct note { bool released; } note; -note scale[26]; +note scale[36]; typedef struct keymap { int key; @@ -50,25 +52,45 @@ typedef struct note_stack { //so the stack can be accessed in the callback note_stack *nsptr; -static inline void push_note(note_stack *ns, note n) { +static inline void set_visual_color(void) { + visual.r = rand(); + visual.g = rand(); + visual.b = rand(); +} + +static inline void darken_visual(void) { + if (visual.r) { + visual.r--; + } + + if (visual.g) { + visual.g--; + } + + if (visual.b) { + visual.b--; + } +} + +static inline void push_note(note_stack *ns, note n, int key) { + ns->keys[ns->nsp % MAX_NOTES].key = key; + ns->keys[ns->nsp % MAX_NOTES].idx = ns->nsp % MAX_NOTES; //might not need + ns->nsp = ns->nsp % MAX_NOTES; - //printf("%s: %d\n", "push_note", ns->nsp); ns->notes[ns->nsp] = n; ns->nsp++; } -//must come before push_note +//must come before push_note, probably dont need static inline void push_key(note_stack *ns, int k) { ns->keys[ns->nsp % MAX_NOTES].key = k; ns->keys[ns->nsp % MAX_NOTES].idx = ns->nsp % MAX_NOTES; //might not need - //printf("%s: %d %d %d\n", "push_key", ns->nsp % MAX_NOTES, ns->keys[ns->nsp % MAX_NOTES].key, ns->keys[ns->nsp % MAX_NOTES].idx); } static inline void release_note(note_stack *ns, int k) { for (int i = 0; i < MAX_NOTES; i++) { if (ns->keys[i].key == k) { - //printf("%s %d %d\n", "release note", k, i); - ns->notes[i].released = true; //try i first + ns->notes[i].released = true; ns->keys[i].key = 0; } } @@ -104,18 +126,15 @@ static inline int count_active_notes(note_stack *ns) { for (size_t i = 0; i < MAX_NOTES; i++) { if (ns->notes[i].volume > 0.0f) { - //printf("%s %f\n", "wtf?:", ns->notes[i].volume); active++; } } - //printf("%s: %d\n", "active notes", active); return active; } static inline float add_notes(note_stack *ns) { float m = 0.0f; - //int active = count_active_notes(ns); float compress = 0.0f; for (size_t i = 0; i < MAX_NOTES; i++) { @@ -138,7 +157,7 @@ static inline float calc_note_step(note *n) { static inline void reset_index(note_stack *ns) { for (size_t i = 0; i < MAX_NOTES; i++) { - ns->notes[i].index += ns->notes[i].step; + ns->notes[i].index += ns->notes[i].step * freqmod * 2; if (ns->notes[i].index > 1.0f && ns->notes[i].volume > 0.0f) { ns->notes[i].index -= 1.0f; } @@ -146,7 +165,6 @@ static inline void reset_index(note_stack *ns) { } void AudioInputCallback2(void *buffer, uint32_t frames) { - //audio_frequency = frequency + (audio_frequency - frequency) * 0.95f; short *d = (short *)buffer; for (size_t i = 0; i < frames; i++) { @@ -158,18 +176,21 @@ void AudioInputCallback2(void *buffer, uint32_t frames) { void key_press(int key, note_stack *ns, note n) { if (IsKeyPressed(key)) { - push_key(ns, key); - push_note(ns, n); - //n->released = false; + set_visual_color(); + push_note(ns, n, key); } if (IsKeyReleased(key)) { - //ns->notes[/*saved idx*/].released = true; release_note(ns, key); - //n->released = true; } } +typedef struct penger { + Vector2 position; + Vector2 velocity; + Texture2D texture; +} penger; + int main(int argc, char *argv[]) { InitWindow(window_width, window_height, window_title); SetTargetFPS(60); @@ -178,7 +199,17 @@ int main(int argc, char *argv[]) { SetAudioStreamBufferSizeDefault(4096); AudioStream stream = LoadAudioStream(44100, 16, 1); - SetAudioStreamCallback(stream, AudioInputCallback2); + SetAudioStreamCallback(stream, AudioInputCallback2); + + Image penger_image = LoadImage("penger.png"); + Texture2D penger_texture = LoadTextureFromImage(penger_image); + UnloadImage(penger_image); + + //init penger + penger penger; + penger.position = (Vector2){window_width/2, window_height/2}; + penger.velocity = (Vector2){0, 0}; + penger.texture = penger_texture; PlayAudioStream(stream); @@ -200,8 +231,8 @@ int main(int argc, char *argv[]) { const float volume_release_step = 0.04f; //init scale - for (int i = 0; i < 26; i++) { - scale[i].frequency = semitone(i-24); + for (int i = 0; i < 36; i++) { + scale[i].frequency = semitone(i-36); scale[i].index = 0.0f; scale[i].volume = 1.0f; scale[i].step = calc_note_step(&scale[i]); @@ -235,12 +266,23 @@ int main(int argc, char *argv[]) { key_press(KEY_I, &ns, scale[23]); key_press(KEY_O, &ns, scale[24]); key_press(KEY_P, &ns, scale[25]); + + key_press(KEY_ONE, &ns, scale[26]); + key_press(KEY_TWO, &ns, scale[27]); + key_press(KEY_THREE, &ns, scale[28]); + key_press(KEY_FOUR, &ns, scale[29]); + key_press(KEY_FIVE, &ns, scale[30]); + key_press(KEY_SIX, &ns, scale[31]); + key_press(KEY_SEVEN, &ns, scale[32]); + key_press(KEY_EIGHT, &ns, scale[33]); + key_press(KEY_NINE, &ns, scale[34]); + key_press(KEY_ZERO, &ns, scale[35]); for (int i = 0; i < MAX_NOTES; i++) { if (ns.notes[i].released) { //printf("lowering volume: %f\n", ns.notes[i].volume); ns.notes[i].volume -= volume_release_step; - //printf("lowering volume: %f\n", ns.notes[i].volume); + if (ns.notes[i].volume < 0.0f) { ns.notes[i].volume = 0.0f; ns.notes[i].index = 0.0f; @@ -250,7 +292,6 @@ int main(int argc, char *argv[]) { for (int i = 0; i < MAX_NOTES; i++) { if (!ns.notes[i].released) { - //printf("%s\n", "bugs?"); ns.notes[i].volume += volume_attack_step; if (ns.notes[i].volume > 1.0f) { ns.notes[i].volume = 1.0f; @@ -258,11 +299,51 @@ int main(int argc, char *argv[]) { } } + if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) { + freqmod = -GetMouseY()/1000.0f; + } - ClearBackground(BLACK); + if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) { + freqmod = 1.0f; + } + + ClearBackground(visual); + + darken_visual(); BeginDrawing(); - + + DrawTextureEx(penger.texture, penger.position, 0.0f, 0.125f, WHITE); + penger.velocity.x = (rand() % (2 - -2 + 2)) + 0; + penger.velocity.y = (rand() % (2 - -2 + 2)) + 0; + + penger.velocity.x += -(rand() % (2 - -2 + 2)) + 0; + penger.velocity.y += -(rand() % (2 - -2 + 2)) + 0; + + penger.position.x += penger.velocity.x; + penger.position.y += penger.velocity.y; + + if (penger.position.x > window_width) { + //penger.position.x = window_width/2; + penger.velocity.x = -penger.velocity.x; + } + + if (penger.position.x < 0) { + //penger.position.x = 0; + penger.velocity.x = -penger.velocity.x; + } + + + if (penger.position.y > window_height) { + //penger.position.y = window_height/2; + penger.velocity.y = -penger.velocity.y; + } + + if (penger.position.y < 0) { + //penger.position.y = 0; + penger.velocity.y = -penger.velocity.y; + } + EndDrawing(); }