diff --git a/penger.png b/penger.png new file mode 100644 index 0000000..03360e8 Binary files /dev/null and b/penger.png differ 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(); }