[feature]: ADSR #15
@@ -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 */);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user