added support for pitch wheel modulation
This commit is contained in:
46
synth/midi_event.h
Normal file
46
synth/midi_event.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
namespace trnr {
|
||||
|
||||
enum midi_event_type {
|
||||
note_on = 0,
|
||||
note_off,
|
||||
pitch_wheel,
|
||||
mod_wheel
|
||||
};
|
||||
|
||||
class midi_event {
|
||||
public:
|
||||
midi_event_type type;
|
||||
int offset = 0;
|
||||
int midi_note = 0;
|
||||
float velocity = 1.f;
|
||||
double data = 0;
|
||||
|
||||
void make_note_on(int _midi_note, float _velocity, int _offset = 0)
|
||||
{
|
||||
type = midi_event_type::note_on;
|
||||
midi_note = _midi_note;
|
||||
velocity = _velocity;
|
||||
offset = _offset;
|
||||
}
|
||||
|
||||
void make_note_off(int _midi_note, float _velocity, int _offset = 0)
|
||||
{
|
||||
type = midi_event_type::note_off;
|
||||
midi_note = _midi_note;
|
||||
velocity = _velocity;
|
||||
offset = _offset;
|
||||
}
|
||||
|
||||
void make_pitch_weel(double _pitch, int _offset = 0) {
|
||||
type = midi_event_type::pitch_wheel;
|
||||
data = _pitch;
|
||||
}
|
||||
|
||||
void make_mod_weel(double _mod, int _offset = 0) {
|
||||
type = midi_event_type::pitch_wheel;
|
||||
data = _mod;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "note_event.h"
|
||||
#include "midi_event.h"
|
||||
#include "voice_allocator.h"
|
||||
|
||||
namespace trnr {
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
block_size = samples_remaining;
|
||||
|
||||
while (!m_event_queue.empty()) {
|
||||
note_event event = m_event_queue.front();
|
||||
midi_event event = m_event_queue.front();
|
||||
|
||||
// we assume the messages are in chronological order. If we find one later than the current block we are done.
|
||||
if (event.offset > start_index + block_size)
|
||||
@@ -66,9 +66,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void add_event(note_event event)
|
||||
void add_event(midi_event event)
|
||||
{
|
||||
if (event.type == note_event_type::note_on)
|
||||
if (event.type == midi_event_type::note_on)
|
||||
m_voices_active = true;
|
||||
|
||||
m_event_queue.push_back(event);
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<note_event> m_event_queue;
|
||||
std::vector<midi_event> m_event_queue;
|
||||
int m_block_size;
|
||||
bool m_voices_active;
|
||||
};
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace trnr {
|
||||
|
||||
enum note_event_type {
|
||||
note_on = 0,
|
||||
note_off
|
||||
};
|
||||
|
||||
class note_event {
|
||||
public:
|
||||
note_event_type type;
|
||||
int midi_note;
|
||||
float velocity;
|
||||
int offset;
|
||||
|
||||
note_event(note_event_type type, int _midi_note, float _velocity, int _offset)
|
||||
: type { type }
|
||||
, midi_note { _midi_note }
|
||||
, velocity { _velocity }
|
||||
, offset { _offset }
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -20,7 +20,8 @@ public:
|
||||
bool trigger = false;
|
||||
int midi_note = 0;
|
||||
float velocity = 1.f;
|
||||
float pitch_mod = 0.f;
|
||||
float pitch_mod = 0.f; // modulates pitch in semi-tones
|
||||
float pitch_mod2 = 0.f; // modulates pitch in frequency
|
||||
|
||||
int algorithm;
|
||||
float pitch_env_amt;
|
||||
@@ -45,7 +46,7 @@ public:
|
||||
|
||||
float process_sample() {
|
||||
float pitch_env_signal = pitch_env.process_sample(gate, trigger) * pitch_env_amt;
|
||||
float pitched_freq = midi_to_frequency(midi_note) + pitch_env_signal + pitch_mod;
|
||||
float pitched_freq = midi_to_frequency(midi_note + pitch_mod) + pitch_env_signal + pitch_mod2;
|
||||
|
||||
float output = 0.f;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "midi_event.h"
|
||||
#include <vector>
|
||||
#include "note_event.h"
|
||||
|
||||
namespace trnr {
|
||||
|
||||
@@ -8,7 +8,7 @@ template <typename t_voice>
|
||||
class voice_allocator {
|
||||
public:
|
||||
std::vector<t_voice> voices;
|
||||
|
||||
|
||||
voice_allocator()
|
||||
: voices(8, t_voice())
|
||||
{
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
voices.resize(voice_count, voices.at(0));
|
||||
}
|
||||
|
||||
void note_on(const note_event& event)
|
||||
void note_on(const midi_event& event)
|
||||
{
|
||||
t_voice* voice = get_free_voice(event.midi_note);
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void note_off(const note_event& event)
|
||||
void note_off(const midi_event& event)
|
||||
{
|
||||
for (auto it = voices.begin(); it != voices.end(); it++) {
|
||||
if ((*it).midi_note == event.midi_note) {
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void add_event(note_event event)
|
||||
void add_event(midi_event event)
|
||||
{
|
||||
input_queue.push_back(event);
|
||||
}
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<note_event> input_queue;
|
||||
std::vector<midi_event> input_queue;
|
||||
|
||||
t_voice* get_free_voice(float frequency)
|
||||
{
|
||||
@@ -126,16 +126,21 @@ private:
|
||||
auto iterator = input_queue.begin();
|
||||
while (iterator != input_queue.end()) {
|
||||
|
||||
note_event& event = *iterator;
|
||||
midi_event& event = *iterator;
|
||||
if (event.offset == _start_index) {
|
||||
|
||||
switch (event.type) {
|
||||
case note_event_type::note_on:
|
||||
case midi_event_type::note_on:
|
||||
note_on(event);
|
||||
break;
|
||||
case note_event_type::note_off:
|
||||
case midi_event_type::note_off:
|
||||
note_off(event);
|
||||
break;
|
||||
case midi_event_type::pitch_wheel:
|
||||
access([&event](t_voice& voice) { voice.pitch_mod = event.data; });
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
iterator = input_queue.erase(iterator);
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace trnr {
|
||||
return pow(10, db/20);
|
||||
}
|
||||
|
||||
static inline float midi_to_frequency(int midi_note) {
|
||||
static inline float midi_to_frequency(float midi_note) {
|
||||
return 440.0 * powf(2.0, ((float)midi_note - 69.0) / 12.0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user