added support for pitch wheel modulation

This commit is contained in:
Christopher Herb
2023-07-10 17:04:16 +02:00
parent 2372d93c6f
commit bc213362f0
6 changed files with 69 additions and 42 deletions

46
synth/midi_event.h Normal file
View 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;
}
};
}

View File

@@ -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;
};

View File

@@ -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 }
{
}
};
}

View File

@@ -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;

View File

@@ -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);