wip: continious sound
This commit is contained in:
@@ -9,7 +9,7 @@ struct Adder {
|
|||||||
static std::vector<float>&
|
static std::vector<float>&
|
||||||
SumOscillators(const std::vector<Oscillator*>& oscillators,
|
SumOscillators(const std::vector<Oscillator*>& oscillators,
|
||||||
float duration) {
|
float duration) {
|
||||||
size_t sample_count = (size_t)(duration * SAMPLE_RATE);
|
size_t sample_count = (size_t)(1.f/FPS * SAMPLE_RATE);
|
||||||
|
|
||||||
std::vector<float>* output = new std::vector<float>();
|
std::vector<float>* output = new std::vector<float>();
|
||||||
output->reserve(sample_count);
|
output->reserve(sample_count);
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
#define PITCH_STANDARD 440.f
|
#define PITCH_STANDARD 440.f
|
||||||
#define VOLUME 0.5f
|
#define VOLUME 0.5f
|
||||||
#define ATTACK_MS 100.f
|
#define ATTACK_MS 100.f
|
||||||
#define STREAM_BUFFER_SIZE 4096
|
#define STREAM_BUFFER_SIZE 1024
|
||||||
|
#define FPS 60
|
||||||
|
|
||||||
#define SYNTH_PI 3.1415926535f
|
#define SYNTH_PI 3.1415926535f
|
||||||
#define SYNTH_VOLUME 0.5f
|
#define SYNTH_VOLUME 0.5f
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
ADSR::ADSR(/* args */) {
|
ADSR::ADSR(/* args */) {
|
||||||
m_parameters.attack_time = 0.025f;
|
m_parameters.attack_time = 1.f;
|
||||||
m_parameters.decay_time = 0.3f;
|
m_parameters.decay_time = 0.3f;
|
||||||
m_parameters.sustain_level = 0.6f;
|
m_parameters.sustain_level = 0.6f;
|
||||||
m_parameters.release_time = 1.0f;
|
m_parameters.release_time = 1.0f;
|
||||||
@@ -35,7 +35,7 @@ void ADSR::process_sample(float* sample, std::size_t attack_samples,
|
|||||||
|
|
||||||
set_state(attack_samples, decay_samples, release_samples);
|
set_state(attack_samples, decay_samples, release_samples);
|
||||||
if (m_state == Attack) {
|
if (m_state == Attack) {
|
||||||
(*sample) = (float)(1.f / attack_samples) * m_counter;
|
(*sample) = (*sample) * ((float)(1.f / attack_samples) * m_counter);
|
||||||
} else if (m_state == Decay) {
|
} else if (m_state == Decay) {
|
||||||
}
|
}
|
||||||
m_counter++;
|
m_counter++;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ void Application::init_synth() {
|
|||||||
// todo: move that variables to Synth declaration
|
// todo: move that variables to Synth declaration
|
||||||
std::string* nameString = new std::string(std::string(new char[3]));
|
std::string* nameString = new std::string(std::string(new char[3]));
|
||||||
m_current_note = new Note{.length = 1, .name = (*nameString)};
|
m_current_note = new Note{.length = 1, .name = (*nameString)};
|
||||||
|
m_current_note->name.assign("G4");
|
||||||
// todo: move somewhere in initialization
|
// todo: move somewhere in initialization
|
||||||
std::vector<Oscillator*> oscillators = m_synth.GetOscillators();
|
std::vector<Oscillator*> oscillators = m_synth.GetOscillators();
|
||||||
m_synth_gui_state.oscillators.reserve(oscillators.size());
|
m_synth_gui_state.oscillators.reserve(oscillators.size());
|
||||||
@@ -91,28 +91,35 @@ std::size_t 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)) {
|
detect_note_pressed(m_current_note);
|
||||||
|
// if (detect_note_pressed(m_current_note)) {
|
||||||
m_synth.ProduceNoteSound((*m_current_note));
|
m_synth.ProduceNoteSound((*m_current_note));
|
||||||
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());
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Play ring-buffered audio
|
// Play ring-buffered audio
|
||||||
void Application::play_buffered_audio() {
|
void Application::play_buffered_audio() {
|
||||||
if (IsAudioStreamProcessed(m_synth_stream) && !m_ring_buffer->IsEmpty()) {
|
std::size_t size_to_read = m_ring_buffer->GetSize();
|
||||||
std::size_t size_to_read = m_ring_buffer->GetSize();
|
size_t sample_count = (size_t)(1.f/FPS * SAMPLE_RATE);
|
||||||
|
if (IsAudioStreamProcessed(m_synth_stream)) {
|
||||||
write_log("Samples to play:%zu \n", size_to_read);
|
write_log("Samples to play:%zu \n", size_to_read);
|
||||||
// todo: try to start reading directly from ring buffer, avoiding
|
// todo: try to start reading directly from ring buffer, avoiding
|
||||||
// temp_buffer
|
// temp_buffer
|
||||||
m_ring_buffer->Read(m_temp_buffer, size_to_read);
|
//todo: can be optimized to only move pointers, without the usage of temp buffer
|
||||||
|
|
||||||
// can try the SetAudioStreamCallback
|
// can try the SetAudioStreamCallback
|
||||||
UpdateAudioStream(m_synth_stream, m_temp_buffer, size_to_read);
|
UpdateAudioStream(m_synth_stream, m_temp_buffer, sample_count);
|
||||||
// can overwrite the ring buffer to avoid that
|
// can overwrite the ring buffer to avoid that
|
||||||
if (m_synth.GetOutSignal().size() == m_sound_played_count) {
|
|
||||||
m_ring_buffer->Reset();
|
// 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()) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,21 +132,20 @@ void Application::fill_audio_buffer() {
|
|||||||
m_sound_played_count);
|
m_sound_played_count);
|
||||||
|
|
||||||
// how many samples need write
|
// how many samples need write
|
||||||
std::size_t size_to_fill = 0;
|
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()) {
|
||||||
|
|
||||||
if ((m_synth.GetOutSignal().size() - m_sound_played_count) >
|
// } else {
|
||||||
m_ring_buffer->GetCapacity()) {
|
// size_to_fill = m_synth.GetOutSignal().size() - m_sound_played_count;
|
||||||
size_to_fill = 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);
|
write_log("[INFO] SizeToFill:%zu\n", size_to_fill);
|
||||||
for (size_t i = 0; i < size_to_fill; i++) {
|
// for (size_t i = 0; i < size_to_fill; i++) {
|
||||||
m_temp_buffer[i] = m_synth.GetOutSignal()[i];
|
// m_temp_buffer[i] = m_synth.GetOutSignal()[i];
|
||||||
}
|
// }
|
||||||
|
|
||||||
m_ring_buffer->Write(m_temp_buffer, size_to_fill);
|
m_ring_buffer->Write((float*)m_synth.GetOutSignal().data(), size_to_fill);
|
||||||
m_sound_played_count += size_to_fill;
|
m_sound_played_count += size_to_fill;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
Renderer::Renderer(/* args */) {
|
Renderer::Renderer(/* args */) {
|
||||||
InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "SeeSynth - v0.2");
|
InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "SeeSynth - v0.2");
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(FPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::~Renderer() {}
|
Renderer::~Renderer() {}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ std::vector<float>& Synth::get_note(int semitone, float beats) {
|
|||||||
void Synth::apply_effects() {
|
void Synth::apply_effects() {
|
||||||
for (Effect* effect : m_effects) {
|
for (Effect* effect : m_effects) {
|
||||||
// maybe not here
|
// maybe not here
|
||||||
effect->RetriggerState();
|
//effect->RetriggerState();
|
||||||
effect->Process(m_out_signal);
|
effect->Process(m_out_signal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user