132 lines
3.9 KiB
C++
132 lines
3.9 KiB
C++
#include "Application.h"
|
|
#include "Logger.h"
|
|
#include "Settings.h"
|
|
#include <string>
|
|
|
|
Application::Application(/* args */) {
|
|
init_synth();
|
|
init_audio();
|
|
}
|
|
|
|
Application::~Application() {
|
|
StopAudioStream(m_synth_stream);
|
|
UnloadAudioStream(m_synth_stream);
|
|
CloseAudioDevice();
|
|
CloseWindow();
|
|
// todo: move to gui state class destructor (make it a class)
|
|
for (int i = 0; i < m_synth_gui_state.oscillators.size(); i++) {
|
|
delete m_synth_gui_state.oscillators[i];
|
|
}
|
|
}
|
|
|
|
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)};
|
|
m_current_note->name.assign("G4");
|
|
// todo: move somewhere in initialization
|
|
std::vector<Oscillator*> oscillators = m_synth.GetOscillators();
|
|
m_synth_gui_state.oscillators.reserve(oscillators.size());
|
|
for (size_t i = 0; i < oscillators.size(); i++) {
|
|
Oscillator* osc = oscillators[i];
|
|
assert(osc);
|
|
|
|
OscillatorGuiState* ui =
|
|
new OscillatorGuiState{.freq = osc->GetFreq(),
|
|
.waveshape = osc->GetType(),
|
|
.volume = osc->GetVolume()};
|
|
m_synth_gui_state.oscillators.push_back(ui);
|
|
}
|
|
}
|
|
|
|
bool Application::detect_note_pressed(Note* note) {
|
|
std::size_t is_pressed = 0;
|
|
note->length = 8;
|
|
if (IsKeyDown(KEY_A)) {
|
|
note->name.assign("A2");
|
|
is_pressed = 1;
|
|
}
|
|
if (IsKeyDown(KEY_B)) {
|
|
note->name.assign("B2");
|
|
is_pressed = 1;
|
|
}
|
|
if (IsKeyDown(KEY_C)) {
|
|
note->name.assign("C2");
|
|
is_pressed = 1;
|
|
}
|
|
if (IsKeyDown(KEY_D)) {
|
|
note->name.assign("D2");
|
|
is_pressed = 1;
|
|
}
|
|
if (IsKeyDown(KEY_E)) {
|
|
note->name.assign("E2");
|
|
is_pressed = 1;
|
|
}
|
|
if (IsKeyDown(KEY_F)) {
|
|
note->name.assign("F2");
|
|
is_pressed = 1;
|
|
}
|
|
if (IsKeyDown(KEY_G)) {
|
|
note->name.assign("G2");
|
|
is_pressed = 1;
|
|
}
|
|
return is_pressed == 1;
|
|
}
|
|
|
|
bool is_note_up() {
|
|
return IsKeyReleased(KEY_A) || IsKeyReleased(KEY_B) ||
|
|
IsKeyReleased(KEY_C) || IsKeyReleased(KEY_D) ||
|
|
IsKeyReleased(KEY_E) || IsKeyReleased(KEY_F) || IsKeyReleased(KEY_G);
|
|
}
|
|
|
|
// Update On Input
|
|
void Application::update_on_note_input() {
|
|
if (detect_note_pressed(m_current_note)) {
|
|
|
|
if (!m_synth.GetIsNoteTriggered()) {
|
|
m_synth.TriggerNote((*m_current_note));
|
|
}
|
|
|
|
// m_sound_played_count = 0;
|
|
write_log("Note played: %s\n", m_current_note->name.c_str());
|
|
} else if (is_note_up() && m_synth.GetIsNoteTriggered()) {
|
|
m_synth.StopSound();
|
|
}
|
|
// will produce 0 signal if ADSR is in off state
|
|
m_synth.ProduceSound();
|
|
}
|
|
|
|
// Play ring-buffered audio
|
|
void Application::play_buffered_audio() {
|
|
if (IsAudioStreamProcessed(m_synth_stream)) {
|
|
// const float audio_frame_start_time = GetTime();
|
|
update_on_note_input();
|
|
UpdateAudioStream(m_synth_stream, m_synth.GetOutSignal().data(),
|
|
STREAM_BUFFER_SIZE);
|
|
// 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)));
|
|
}
|
|
}
|
|
|
|
void Application::Run() {
|
|
// Main game loop
|
|
while (!WindowShouldClose()) {
|
|
play_buffered_audio();
|
|
m_renderer.Draw(m_synth, m_synth_gui_state);
|
|
}
|
|
}
|