voice interface and type checks

This commit is contained in:
Christopher Herb
2023-07-10 18:10:25 +02:00
parent 92fe1eea22
commit 7c1bd1c982
4 changed files with 41 additions and 8 deletions

25
synth/ivoice.h Normal file
View File

@@ -0,0 +1,25 @@
#pragma once
namespace trnr {
struct ivoice {
virtual ~ivoice() = default;
virtual float process_sample() = 0;
virtual bool is_busy() = 0;
virtual void set_samplerate(double samplerate) = 0;
virtual void note_on(int _note, float _velocity) = 0;
virtual void note_off() = 0;
virtual void modulate_pitch(float _pitch) = 0;
};
// check if a template derives from ivoice
template <class derived>
struct is_convertible {
template <class T>
static char test(T*);
template <class T>
static double test(...);
static const bool value = sizeof(test<ivoice>(static_cast<derived*>(0))) == 1;
};
}

View File

@@ -1,18 +1,22 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "ivoice.h"
#include "midi_event.h" #include "midi_event.h"
#include "voice_allocator.h" #include "voice_allocator.h"
namespace trnr { namespace trnr {
// a generic midi synth base class with sample accurate event handling. // a generic midi synth base class with sample accurate event handling.
// the templated type t_voice must derive from ivoice
template <typename t_voice> template <typename t_voice>
class midi_synth : public voice_allocator<t_voice> { class midi_synth : public voice_allocator<t_voice> {
public: public:
midi_synth(int _n_voices) midi_synth(int _n_voices)
: m_voices_active { false } : m_voices_active { false }
{ {
// checks whether template derives from ivoice
typedef t_voice assert_at_compile_time[is_convertible<t_voice>::value ? 1 : -1];
} }
void set_samplerate_blocksize(double _samplerate, int _block_size) void set_samplerate_blocksize(double _samplerate, int _block_size)

View File

@@ -2,11 +2,12 @@
#include "tx_sineosc.h" #include "tx_sineosc.h"
#include "tx_envelope.h" #include "tx_envelope.h"
#include "tx_operator.h" #include "tx_operator.h"
#include "ivoice.h"
#include "../util/audio_math.h" #include "../util/audio_math.h"
namespace trnr { namespace trnr {
class tx_voice { class tx_voice : public ivoice {
public: public:
tx_voice() tx_voice()
: algorithm { 0 } : algorithm { 0 }
@@ -32,23 +33,23 @@ public:
tx_operator op2; tx_operator op2;
tx_operator op3; tx_operator op3;
void note_on(int _note, float _velocity) { void note_on(int _note, float _velocity) override {
this->gate = true; this->gate = true;
this->trigger = true; this->trigger = true;
midi_note = _note; midi_note = _note;
velocity = _velocity; velocity = _velocity;
} }
void note_off() { void note_off() override {
this->gate = false; this->gate = false;
} }
// modulates the pitch in semitones // modulates the pitch in semitones
void modulate_pitch(float pitch) { void modulate_pitch(float _pitch) override {
this->pitch_mod = pitch; this->pitch_mod = _pitch;
} }
float process_sample() { float process_sample() override {
float pitch_env_signal = pitch_env.process_sample(gate, trigger) * pitch_env_amt; float pitch_env_signal = pitch_env.process_sample(gate, trigger) * pitch_env_amt;
float pitched_freq = midi_to_frequency(midi_note + pitch_mod + additional_pitch_mod) + pitch_env_signal; float pitched_freq = midi_to_frequency(midi_note + pitch_mod + additional_pitch_mod) + pitch_env_signal;
@@ -79,9 +80,9 @@ public:
return redux(output, bit_resolution); return redux(output, bit_resolution);
} }
bool is_busy() { return gate || op1.envelope.is_busy() || op2.envelope.is_busy() || op3.envelope.is_busy(); } bool is_busy() override { return gate || op1.envelope.is_busy() || op2.envelope.is_busy() || op3.envelope.is_busy(); }
void set_samplerate(double samplerate) { void set_samplerate(double samplerate) override {
pitch_env.set_samplerate(samplerate); pitch_env.set_samplerate(samplerate);
feedback_osc.set_samplerate(samplerate); feedback_osc.set_samplerate(samplerate);
op1.set_samplerate(samplerate); op1.set_samplerate(samplerate);

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "midi_event.h" #include "midi_event.h"
#include "ivoice.h"
#include <vector> #include <vector>
namespace trnr { namespace trnr {
@@ -12,6 +13,8 @@ public:
voice_allocator() voice_allocator()
: voices(8, t_voice()) : voices(8, t_voice())
{ {
// checks whether template derives from ivoice
typedef t_voice assert_at_compile_time[is_convertible<t_voice>::value ? 1 : -1];
} }
void set_voice_count(const int& voice_count) void set_voice_count(const int& voice_count)