[feature]: ADSR #15

Merged
e1lama merged 13 commits from feature/adsr into master 2023-09-06 08:29:46 +00:00
11 changed files with 211 additions and 98 deletions
Showing only changes of commit 73aae9a490 - Show all commits

View File

@@ -1,7 +1,6 @@
#pragma once #pragma once
#include "Note.h" #include "Note.h"
#include "Renderer.h" #include "Renderer.h"
#include "RingBuffer.h"
#include "Synth.h" #include "Synth.h"
#include "SynthGuiState.h" #include "SynthGuiState.h"
#include "raylib.h" #include "raylib.h"
@@ -10,10 +9,8 @@ class Application {
private: private:
Synth m_synth; Synth m_synth;
SynthGuiState m_synth_gui_state; SynthGuiState m_synth_gui_state;
RingBuffer<float>* m_ring_buffer;
AudioStream m_synth_stream; AudioStream m_synth_stream;
int m_sound_played_count; int m_sound_played_count;
float* m_temp_buffer;
Note* m_current_note; Note* m_current_note;
Renderer m_renderer; Renderer m_renderer;
bool detect_note_pressed(Note* note); bool detect_note_pressed(Note* note);
@@ -21,7 +18,6 @@ class Application {
void init_audio(); void init_audio();
void update_on_note_input(); void update_on_note_input();
void play_buffered_audio(); void play_buffered_audio();
void fill_audio_buffer();
public: public:
Application(/* args */); Application(/* args */);

View File

@@ -4,8 +4,6 @@
#include <string> #include <string>
Application::Application(/* args */) { Application::Application(/* args */) {
m_ring_buffer = new RingBuffer<float>((std::size_t)STREAM_BUFFER_SIZE);
m_temp_buffer = new float[STREAM_BUFFER_SIZE];
init_synth(); init_synth();
init_audio(); init_audio();
} }
@@ -15,8 +13,6 @@ Application::~Application() {
UnloadAudioStream(m_synth_stream); UnloadAudioStream(m_synth_stream);
CloseAudioDevice(); CloseAudioDevice();
CloseWindow(); CloseWindow();
delete m_ring_buffer;
delete[] m_temp_buffer;
// todo: move to gui state class destructor (make it a class) // todo: move to gui state class destructor (make it a class)
for (int i = 0; i < m_synth_gui_state.oscillators.size(); i++) { for (int i = 0; i < m_synth_gui_state.oscillators.size(); i++) {
delete m_synth_gui_state.oscillators[i]; delete m_synth_gui_state.oscillators[i];
@@ -59,31 +55,31 @@ bool Application::detect_note_pressed(Note* note) {
std::size_t is_pressed = 0; std::size_t is_pressed = 0;
note->length = 8; note->length = 8;
if (IsKeyDown(KEY_A)) { if (IsKeyDown(KEY_A)) {
note->name.assign("A4"); note->name.assign("A2");
is_pressed = 1; is_pressed = 1;
} }
if (IsKeyDown(KEY_B)) { if (IsKeyDown(KEY_B)) {
note->name.assign("B4"); note->name.assign("B2");
is_pressed = 1; is_pressed = 1;
} }
if (IsKeyDown(KEY_C)) { if (IsKeyDown(KEY_C)) {
note->name.assign("C5"); note->name.assign("C2");
is_pressed = 1; is_pressed = 1;
} }
if (IsKeyDown(KEY_D)) { if (IsKeyDown(KEY_D)) {
note->name.assign("D5"); note->name.assign("D2");
is_pressed = 1; is_pressed = 1;
} }
if (IsKeyDown(KEY_E)) { if (IsKeyDown(KEY_E)) {
note->name.assign("E5"); note->name.assign("E2");
is_pressed = 1; is_pressed = 1;
} }
if (IsKeyDown(KEY_F)) { if (IsKeyDown(KEY_F)) {
note->name.assign("F5"); note->name.assign("F2");
is_pressed = 1; is_pressed = 1;
} }
if (IsKeyDown(KEY_G)) { if (IsKeyDown(KEY_G)) {
note->name.assign("G5"); note->name.assign("G2");
is_pressed = 1; is_pressed = 1;
} }
return is_pressed == 1; return is_pressed == 1;
@@ -92,14 +88,13 @@ bool Application::detect_note_pressed(Note* note) {
// Update On Input // Update On Input
void Application::update_on_note_input() { void Application::update_on_note_input() {
if (detect_note_pressed(m_current_note)) { if (detect_note_pressed(m_current_note)) {
// if (detect_note_pressed(m_current_note)) {
if (!m_synth.GetIsNoteTriggered()){ if (!m_synth.GetIsNoteTriggered()){
m_synth.TriggerNote((*m_current_note)); m_synth.TriggerNote((*m_current_note));
} }
m_synth.ProduceSound(); m_synth.ProduceSound();
//m_sound_played_count = 0; //m_sound_played_count = 0;
write_log("Note played: %s\n", m_current_note->name.c_str()); write_log("Note played: %s\n", m_current_note->name.c_str());
//}
} }
else { else {
m_synth.StopSound(); m_synth.StopSound();
@@ -109,57 +104,12 @@ void Application::update_on_note_input() {
// Play ring-buffered audio // Play ring-buffered audio
void Application::play_buffered_audio() { void Application::play_buffered_audio() {
//std::size_t size_to_read = m_ring_buffer->GetSize();
size_t sample_count = STREAM_BUFFER_SIZE;//(size_t)(1.f/FPS * SAMPLE_RATE);
if (IsAudioStreamProcessed(m_synth_stream)) { if (IsAudioStreamProcessed(m_synth_stream)) {
//write_log("Samples to play:%zu \n", size_to_read);
// todo: try to start reading directly from ring buffer, avoiding
// temp_buffer
//todo: can be optimized to only move pointers, without the usage of temp buffer
//m_synth.ProduceNoteSound((*m_current_note));
// can try the SetAudioStreamCallback
const float audio_frame_start_time = GetTime(); const float audio_frame_start_time = GetTime();
update_on_note_input(); update_on_note_input();
UpdateAudioStream(m_synth_stream, m_synth.GetOutSignal().data(), sample_count); UpdateAudioStream(m_synth_stream, m_synth.GetOutSignal().data(), STREAM_BUFFER_SIZE);
// can overwrite the ring buffer to avoid that
const float audio_freme_duration = GetTime() - audio_frame_start_time; const float audio_freme_duration = GetTime() - audio_frame_start_time;
write_log("Frame time: %.3f%% \n", 100.0f / ((1.0f / audio_freme_duration) / ((float)SAMPLE_RATE/STREAM_BUFFER_SIZE))); write_log("Frame time: %.3f%% \n", 100.0f / ((1.0f / audio_freme_duration) / ((float)SAMPLE_RATE/STREAM_BUFFER_SIZE)));
// if (m_synth.GetOutSignal().size() == m_sound_played_count) {
// m_ring_buffer->Reset();
// }
}
//m_ring_buffer->Read(m_temp_buffer, sample_count);
//m_ring_buffer->Reset();
//if (m_ring_buffer->IsFull() || m_ring_buffer->IsEmpty()) {
//}
}
// Fill ring buffer from current sound
void Application::fill_audio_buffer() {
if (!m_ring_buffer->IsFull() &&
m_synth.GetOutSignal().size() != m_sound_played_count) {
write_log("[INFO] IsFull:%d Samples:%zu Played:%d\n",
m_ring_buffer->IsFull(), m_synth.GetOutSignal().size(),
m_sound_played_count);
// how many samples need write
std::size_t size_to_fill = m_ring_buffer->GetCapacity() - m_synth.GetOutSignal().size();
// if ((m_synth.GetOutSignal().size() - m_sound_played_count) >
// m_ring_buffer->GetCapacity()) {
// } else {
// size_to_fill = m_synth.GetOutSignal().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] = m_synth.GetOutSignal()[i];
// }
m_ring_buffer->Write((float*)m_synth.GetOutSignal().data(), size_to_fill);
m_sound_played_count += size_to_fill;
} }
} }
@@ -167,10 +117,7 @@ void Application::Run() {
// Main game loop // Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key while (!WindowShouldClose()) // Detect window close button or ESC key
{ {
//fill_audio_buffer();
//update_on_note_input();
play_buffered_audio(); play_buffered_audio();
m_renderer.Draw(m_synth, m_synth_gui_state); m_renderer.Draw(m_synth, m_synth_gui_state);
} }
} }