From e3825b341d31a2ef312b9322a6e0bfde5a21c32b Mon Sep 17 00:00:00 2001 From: HiveBeats Date: Mon, 7 Aug 2023 13:27:25 +0400 Subject: [PATCH] wip: application class --- inc/Application.h | 27 ++++++++ inc/Renderer.h | 21 ++++++ inc/RingBuffer.h | 1 + src/Application.cpp | 157 ++++++++++++++++++++++++++++++++++++++++++++ src/Renderer.cpp | 17 +++++ 5 files changed, 223 insertions(+) create mode 100644 inc/Application.h create mode 100644 inc/Renderer.h create mode 100644 src/Application.cpp create mode 100644 src/Renderer.cpp diff --git a/inc/Application.h b/inc/Application.h new file mode 100644 index 0000000..c15f308 --- /dev/null +++ b/inc/Application.h @@ -0,0 +1,27 @@ +#pragma once +#include "Note.h" +#include "Synth.h" +#include "raylib.h" +#include "RingBuffer.h" +#include "Renderer.h" +class Application +{ +private: + Synth m_synth; + RingBuffer* m_ring_buffer; + AudioStream m_synth_stream; + int m_sound_played_count; + float* m_temp_buffer; + Note* m_current_note; + Renderer m_renderer; + std::size_t detect_note_pressed(Note* note); + void init_gui(); + void init_synth(); + void init_audio(); + +public: + Application(/* args */); + ~Application(); + void Run(); +}; + diff --git a/inc/Renderer.h b/inc/Renderer.h new file mode 100644 index 0000000..25e591a --- /dev/null +++ b/inc/Renderer.h @@ -0,0 +1,21 @@ +#pragma once + +class Renderer +{ +private: + /* data */ +public: + Renderer(/* args */); + ~Renderer(); + void Draw(); +}; + +Renderer::Renderer(/* args */) +{ +} + +Renderer::~Renderer() +{ +} + + diff --git a/inc/RingBuffer.h b/inc/RingBuffer.h index 2844601..32253b4 100644 --- a/inc/RingBuffer.h +++ b/inc/RingBuffer.h @@ -18,6 +18,7 @@ public: bool IsFull() { return m_is_full; } bool IsEmpty() { return m_is_empty; } std::size_t GetSize(); + std::size_t GetCapacity() { return m_size; } void Reset(); void Write(T* data, size_t count); bool Read(T* output, size_t count); diff --git a/src/Application.cpp b/src/Application.cpp new file mode 100644 index 0000000..72be04c --- /dev/null +++ b/src/Application.cpp @@ -0,0 +1,157 @@ +#include "Application.h" +#include "Settings.h" +#include "Logger.h" +#include +Application::Application(/* args */) +{ + m_ring_buffer = new RingBuffer((std::size_t)STREAM_BUFFER_SIZE); + m_temp_buffer = new float[STREAM_BUFFER_SIZE]; + init_gui(); + init_synth(); + init_audio(); +} + +Application::~Application() +{ + delete m_ring_buffer; + delete m_temp_buffer; +} + +void Application::init_gui() +{ + InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "SeeSynth - v0.2"); + SetTargetFPS(60); +} + +void Application::init_audio() +{ + m_sound_played_count = 0; + + InitAudioDevice(); + SetMasterVolume(SYNTH_VOLUME); + SetAudioStreamBufferSizeDefault(STREAM_BUFFER_SIZE); + m_synth_stream = LoadAudioStream(SAMPLE_RATE, sizeof(float) * 8, 1); + SetAudioStreamVolume(m_synth_stream, 0.5f); + + PlayAudioStream(m_synth_stream); +} + +void Application::init_synth() { + //todo: move that variables to Synth declaration + std::string* nameString = new std::string(std::string(new char[3])); + m_current_note = new Note { + .length = 1, + .name = (*nameString) + }; + + //todo: move somewhere in initialization + // synth.ui_oscillators = malloc(sizeof(OscillatorUI) * synth.oscillators.count); + // for (size_t i = 0; i < synth.oscillators.count; i++) + // { + // OscillatorUI* ui = &synth.ui_oscillators[i]; + // assert(ui); + + // ui->freq = synth.oscillators.array[i].freq; + // ui->waveshape = synth.oscillators.array[i].osc; + // ui->volume = synth.oscillators.array[i].volume; + // } +} + +std::size_t Application::detect_note_pressed(Note* note) { + std::size_t is_pressed = 0; + note->length = 8; + if (IsKeyPressed(KEY_A)) { + note->name.assign("A4"); + is_pressed = 1; + } + if (IsKeyPressed(KEY_B)) { + note->name.assign("B4"); + is_pressed = 1; + } + if (IsKeyPressed(KEY_C)) { + note->name.assign("C4"); + is_pressed = 1; + } + if (IsKeyPressed(KEY_D)) { + note->name.assign("D4"); + is_pressed = 1; + } + if (IsKeyPressed(KEY_E)) { + note->name.assign("E4"); + is_pressed = 1; + } + if (IsKeyPressed(KEY_F)) { + note->name.assign("F4"); + is_pressed = 1; + } + if (IsKeyPressed(KEY_G)) { + note->name.assign("G4"); + is_pressed = 1; + } + return is_pressed; +} + +void Application::Run() +{ + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update Audio states + //---------------------------------------------------------------------------------- + // Fill ring buffer from current sound + std::vector sound = m_synth.GetOutSignal(); + + size_t size_for_buffer = 0; + if (!m_ring_buffer->IsFull() && sound.size() != m_sound_played_count) { + write_log("[INFO] IsFull:%d Samples:%zu Played:%d\n", + m_ring_buffer->IsFull(), + sound.size(), + m_sound_played_count); + + // how many samples need write + std::size_t size_to_fill = 0; + + if ((sound.size() - m_sound_played_count) > m_ring_buffer->GetCapacity()) { + size_to_fill = m_ring_buffer->GetCapacity(); + } else { + size_to_fill = sound.size() - m_sound_played_count; + } + + write_log("[INFO] SizeToFill:%zu\n", size_to_fill); + for (size_t i = 0; i < size_to_fill; i++) { + m_temp_buffer[i] = sound[i]; + } + + m_ring_buffer->Write(m_temp_buffer, size_to_fill); + m_sound_played_count += size_to_fill; + } + + // Play ring-buffered audio + if (IsAudioStreamProcessed(m_synth_stream) && !m_ring_buffer->IsEmpty()) { + std::size_t size_to_read = m_ring_buffer->GetSize(); + + write_log("Samples to play:%zu \n", size_to_read); + //todo: try to start reading directly from ring buffer, avoiding temp_buffer + m_ring_buffer->Read(m_temp_buffer, size_to_read); + // can try the SetAudioStreamCallback + UpdateAudioStream(m_synth_stream, m_temp_buffer, size_to_read); + // can overwrite the ring buffer to avoid that + if (sound.size() == m_sound_played_count) { + m_ring_buffer->Reset(); + } + } + //---------------------------------------------------------------------------------- + + // Update On Input + //---------------------------------------------------------------------------------- + if (detect_note_pressed(m_current_note)) { + m_synth.ProduceNoteSound((*m_current_note)); + sound = m_synth.GetOutSignal(); + m_sound_played_count = 0; + write_log("Note played: %s\n", m_current_note->name); + } + //---------------------------------------------------------------------------------- + + m_renderer.Draw(); + } +} diff --git a/src/Renderer.cpp b/src/Renderer.cpp new file mode 100644 index 0000000..ce9eb70 --- /dev/null +++ b/src/Renderer.cpp @@ -0,0 +1,17 @@ +#include "Renderer.h" +#include "raylib.h" +#include "raygui.h" + +void Renderer::Draw() +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + //todo: implement renderer + //DrawUi(&synth); + //DrawSignal(&synth); + //DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); + //DrawFPS(0,0); + + EndDrawing(); +} \ No newline at end of file