voice interface and type checks
This commit is contained in:
25
synth/ivoice.h
Normal file
25
synth/ivoice.h
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user