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
|
#pragma once
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "note_event.h"
|
#include "midi_event.h"
|
||||||
#include "voice_allocator.h"
|
#include "voice_allocator.h"
|
||||||
|
|
||||||
namespace trnr {
|
namespace trnr {
|
||||||
@@ -35,7 +35,7 @@ public:
|
|||||||
block_size = samples_remaining;
|
block_size = samples_remaining;
|
||||||
|
|
||||||
while (!m_event_queue.empty()) {
|
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.
|
// 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)
|
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_voices_active = true;
|
||||||
|
|
||||||
m_event_queue.push_back(event);
|
m_event_queue.push_back(event);
|
||||||
@@ -82,7 +82,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<note_event> m_event_queue;
|
std::vector<midi_event> m_event_queue;
|
||||||
int m_block_size;
|
int m_block_size;
|
||||||
bool m_voices_active;
|
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;
|
bool trigger = false;
|
||||||
int midi_note = 0;
|
int midi_note = 0;
|
||||||
float velocity = 1.f;
|
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;
|
int algorithm;
|
||||||
float pitch_env_amt;
|
float pitch_env_amt;
|
||||||
@@ -45,7 +46,7 @@ public:
|
|||||||
|
|
||||||
float process_sample() {
|
float process_sample() {
|
||||||
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_env_signal + pitch_mod;
|
float pitched_freq = midi_to_frequency(midi_note + pitch_mod) + pitch_env_signal + pitch_mod2;
|
||||||
|
|
||||||
float output = 0.f;
|
float output = 0.f;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "midi_event.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "note_event.h"
|
|
||||||
|
|
||||||
namespace trnr {
|
namespace trnr {
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ public:
|
|||||||
voices.resize(voice_count, voices.at(0));
|
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);
|
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++) {
|
for (auto it = voices.begin(); it != voices.end(); it++) {
|
||||||
if ((*it).midi_note == event.midi_note) {
|
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);
|
input_queue.push_back(event);
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<note_event> input_queue;
|
std::vector<midi_event> input_queue;
|
||||||
|
|
||||||
t_voice* get_free_voice(float frequency)
|
t_voice* get_free_voice(float frequency)
|
||||||
{
|
{
|
||||||
@@ -126,16 +126,21 @@ private:
|
|||||||
auto iterator = input_queue.begin();
|
auto iterator = input_queue.begin();
|
||||||
while (iterator != input_queue.end()) {
|
while (iterator != input_queue.end()) {
|
||||||
|
|
||||||
note_event& event = *iterator;
|
midi_event& event = *iterator;
|
||||||
if (event.offset == _start_index) {
|
if (event.offset == _start_index) {
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case note_event_type::note_on:
|
case midi_event_type::note_on:
|
||||||
note_on(event);
|
note_on(event);
|
||||||
break;
|
break;
|
||||||
case note_event_type::note_off:
|
case midi_event_type::note_off:
|
||||||
note_off(event);
|
note_off(event);
|
||||||
break;
|
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);
|
iterator = input_queue.erase(iterator);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace trnr {
|
|||||||
return pow(10, db/20);
|
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);
|
return 440.0 * powf(2.0, ((float)midi_note - 69.0) / 12.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user