From 3d79d24effb5a53517bd998ac4a7efbf191084e7 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 3 Aug 2025 11:18:23 +0200 Subject: [PATCH] procedural audio buffer, add mods to synth --- synth/synth.h | 37 +++++++++-------- util/audio_buffer.h | 97 +++++++++++---------------------------------- 2 files changed, 44 insertions(+), 90 deletions(-) diff --git a/synth/synth.h b/synth/synth.h index e9871dc..9aff873 100644 --- a/synth/synth.h +++ b/synth/synth.h @@ -1,5 +1,6 @@ #pragma once +#include "audio_buffer.h" #include #include #include @@ -8,15 +9,15 @@ using namespace std; namespace trnr { -enum m_event_type { +enum midi_event_type { note_on = 0, note_off, pitch_wheel, mod_wheel }; -struct m_event { - m_event_type type; +struct midi_event { + midi_event_type type; int offset; int midi_note; float velocity; @@ -26,35 +27,36 @@ struct m_event { constexpr size_t MAX_VOICES = 8; constexpr size_t MAX_EVENTS_PER_VOICE = 32; -template -void voice_process_block(voice& v, sample** audio, int num_frames, const array& events, - size_t num_events); +template +void voice_process_block(t_voice& v, t_sample** frames, size_t num_frames, midi_event* events, size_t num_events, + const vector>& mods = {}); -template +template struct synth { - array voices; - array, MAX_VOICES> voice_events; + array voices; + array, MAX_VOICES> voice_events; array counts; int active_voice_count = 1; size_t index_to_steal = 0; }; -template -void synth_init(synth& s, double samplerate) +template +void synth_init(synth& s, double samplerate) { for (size_t i = 0; i < MAX_VOICES; ++i) { - s.voices[i] = voice(); + s.voices[i] = t_voice(); s.voices[i].voice_init(samplerate); s.counts[i] = 0; } } -template -void synth_process_block(synth& s, sample** audio, const vector& midi_events, int num_frames) +template +void synth_process_block(synth& s, t_sample** frames, int num_frames, const vector& midi_events, + const vector>& mods = {}) { // reset voice events and counts for (int i = 0; i < MAX_VOICES; i++) { - s.voice_events[i].fill(m_event {}); + s.voice_events[i].fill(midi_event {}); s.counts[i] = 0; } @@ -106,8 +108,9 @@ void synth_process_block(synth& s, sample** audio, const vector& for (size_t i = 0; i < s.active_voice_count; ++i) { auto& v = s.voices[i]; - auto& events = s.voice_events[i]; - voice_process_block(v, audio, num_frames, events, s.counts[i]); + auto& events = s.voice_events[i].data(); + size_t num_events = s.counts[i]; + voice_process_block(v, frames, num_frames, events, num_events, mods); } } } // namespace trnr diff --git a/util/audio_buffer.h b/util/audio_buffer.h index bbbdf1f..568ee8c 100644 --- a/util/audio_buffer.h +++ b/util/audio_buffer.h @@ -1,81 +1,32 @@ #pragma once -#include -#include #include +using namespace std; + namespace trnr { template -class audio_buffer { -public: - audio_buffer(const t_sample** input, int channels, int frames) - : m_data(channels * frames) - , m_channels(channels) - , m_frames(frames) - , m_channel_ptrs(channels) - { - for (int ch = 0; ch < channels; ++ch) { - std::copy(input[ch], input[ch] + frames, m_data.begin() + ch * frames); - } - update_channel_ptrs(); - } +struct audio_buffer { + size_t channels; + size_t frames; - audio_buffer(int channels = 1, int frames = 1024) - : m_channels(channels) - , m_frames(frames) - , m_data(channels * frames) - , m_channel_ptrs(channels) - { - update_channel_ptrs(); - } - - void set_size(int channels, int frames) - { - m_channels = channels; - m_frames = frames; - m_data.resize(channels * frames); - m_channel_ptrs.resize(channels); - update_channel_ptrs(); - } - - void set_data(const t_sample** input, int channels, int frames) - { - set_size(channels, frames); - for (int ch = 0; ch < channels; ++ch) { - std::copy(input[ch], input[ch] + frames, m_data.begin() + ch * frames); - } - update_channel_ptrs(); - } - - int num_samples() const { return m_frames; } - - int num_channels() const { return m_channels; } - - t_sample* data() { return m_data.data(); } - - const t_sample* data() const { return m_data.data(); } - - // t_sample** access, always up-to-date after construction/resize - t_sample** write_ptrs() { return m_channel_ptrs.data(); } - - t_sample* write_ptr(int channel) - { - assert(channel >= 0 && channel < m_channels); - return m_channel_ptrs[channel]; - } - - const t_sample* const* channel_ptrs() const { return m_channel_ptrs.data(); } - -private: - void update_channel_ptrs() - { - for (int ch = 0; ch < m_channels; ++ch) { m_channel_ptrs[ch] = m_data.data() + ch * m_frames; } - } - - std::vector m_data; - std::vector m_channel_ptrs; - - int m_channels; - int m_frames; // samples per channel + vector flat_data; + vector channel_ptrs; }; -} // namespace trnr \ No newline at end of file + +template +void audio_buffer_init(audio_buffer& a, size_t channels, size_t frames) +{ + a.channels = channels; + a.frames = frames; + a.flat_data.resize(channels * frames); + a.channel_ptrs.resize(channels); + audio_buffer_update_ptrs(a); +} + +template +void audio_buffer_update_ptrs(audio_buffer& a) +{ + for (int ch = 0; ch < a.channels; ++ch) { a.channel_ptrs[ch] = a.flat_data.data() + ch * a.frames; } +} +} // namespace trnr