Skip to content

Commit

Permalink
LIB: MidiSynth: support different cc control values for each midi cha…
Browse files Browse the repository at this point in the history
…nnel

Signed-off-by: Stefan Westerfeld <[email protected]>
  • Loading branch information
swesterfeld committed Jun 11, 2024
1 parent 5ddbce3 commit 69b1a9c
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 19 deletions.
35 changes: 22 additions & 13 deletions lib/smmidisynth.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,15 @@ MidiSynth::freq_from_note (float note)
return 440 * exp (log (2) * (note - 69) / 12.0);
}

float
MidiSynth::voice_control (const Voice *voice, int c)
{
if (m_control_by_cc)
return channel_state[voice->channel].control[c];
else
return std::clamp (control[c] + voice->modulation[c], -1.f, 1.f);
}

void
MidiSynth::process_note_on (const NoteEvent& note)
{
Expand Down Expand Up @@ -306,7 +315,7 @@ MidiSynth::process_mod_value (const ModValueEvent& mod)
}

void
MidiSynth::process_midi_controller (int controller, int value)
MidiSynth::process_midi_controller (int channel, int controller, int value)
{
if (controller == SM_MIDI_CTL_SUSTAIN)
{
Expand All @@ -329,7 +338,7 @@ MidiSynth::process_midi_controller (int controller, int value)
if (controller == SM_MIDI_CTL_ALL_NOTES_OFF)
{
/* release sustain pedal, otherwise note off events will have no effect */
process_midi_controller (SM_MIDI_CTL_SUSTAIN, 0);
process_midi_controller (channel, SM_MIDI_CTL_SUSTAIN, 0);

/* check which notes are active */
std::set<std::pair<int, int>> channel_note_set;
Expand All @@ -350,15 +359,16 @@ MidiSynth::process_midi_controller (int controller, int value)
if (m_control_by_cc)
{
const float value_f = sm_bound (-1.0, (value / 127.) * 2 - 1, 1.0);
auto& cst_control = channel_state[channel].control;
switch (controller)
{
case SM_MIDI_CTL_CONTROL_1: control[0] = value_f;
case SM_MIDI_CTL_CONTROL_1: cst_control[0] = value_f;
break;
case SM_MIDI_CTL_CONTROL_2: control[1] = value_f;
case SM_MIDI_CTL_CONTROL_2: cst_control[1] = value_f;
break;
case SM_MIDI_CTL_CONTROL_3: control[2] = value_f;
case SM_MIDI_CTL_CONTROL_3: cst_control[2] = value_f;
break;
case SM_MIDI_CTL_CONTROL_4: control[3] = value_f;
case SM_MIDI_CTL_CONTROL_4: cst_control[3] = value_f;
break;
}
}
Expand Down Expand Up @@ -483,6 +493,7 @@ MidiSynth::add_midi_event (size_t offset, const unsigned char *midi_data)
Event event;
event.offset = offset;
event.type = EVENT_CC;
event.cc.channel = channel;
event.cc.controller = midi_data[1];
event.cc.value = midi_data[2];
events.push_back (event);
Expand Down Expand Up @@ -511,10 +522,8 @@ MidiSynth::process_audio (float *output, size_t n_values)

for (Voice *voice : active_voices)
{
voice->mp_voice->set_control_input (0, std::clamp (control[0] + voice->modulation[0], -1.f, 1.f));
voice->mp_voice->set_control_input (1, std::clamp (control[1] + voice->modulation[1], -1.f, 1.f));
voice->mp_voice->set_control_input (2, std::clamp (control[2] + voice->modulation[2], -1.f, 1.f));
voice->mp_voice->set_control_input (3, std::clamp (control[3] + voice->modulation[3], -1.f, 1.f));
for (int c = 0; c < MorphPlan::N_CONTROL_INPUTS; c++)
voice->mp_voice->set_control_input (c, voice_control (voice, c));

const float gain = voice->gain * m_gain;
const float *freq_in = nullptr;
Expand Down Expand Up @@ -685,7 +694,7 @@ MidiSynth::process (float *output, size_t n_values, MidiSynthCallbacks *process_
case EVENT_CC:
{
MIDI_DEBUG ("%" PRIu64 " | controller event, %d %d\n", audio_time_stamp, event.cc.controller, event.cc.value);
process_midi_controller (event.cc.controller, event.cc.value);
process_midi_controller (event.cc.channel, event.cc.controller, event.cc.value);
}
break;
}
Expand Down Expand Up @@ -833,12 +842,12 @@ MidiSynth::notify_active_voice_status()

m_notify_buffer.write_seq (velocity_seq, n_voices);

for (int i = 0; i < MorphPlan::N_CONTROL_INPUTS; i++)
for (int c = 0; c < MorphPlan::N_CONTROL_INPUTS; c++)
{
float control_input_seq[MAX_VOICES];

for (uint v = 0; v < n_voices; v++)
control_input_seq[v] = std::clamp (control[i] + voices[v]->modulation[i], -1.f, 1.f);
control_input_seq[v] = voice_control (voices[v], c);

m_notify_buffer.write_seq (control_input_seq, n_voices);
}
Expand Down
14 changes: 8 additions & 6 deletions lib/smmidisynth.hh
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ private:
};
struct CCEvent
{
int channel;
int controller;
int value;
};
Expand All @@ -88,12 +89,13 @@ private:
};
std::vector<Event> events;

typedef std::array<float, MorphPlan::N_CONTROL_INPUTS> ModArray;
typedef std::array<float, MorphPlan::N_CONTROL_INPUTS> ControlArray;

static constexpr int MIDI_CHANNELS = 16;
struct MidiChannelState
{
float pitch_bend_freq_factor = 1;
float pitch_bend_freq_factor = 1;
ControlArray control {};
};
std::array<MidiChannelState, MIDI_CHANNELS> channel_state;

Expand Down Expand Up @@ -125,14 +127,13 @@ private:
int note_id;
int clap_id;

ModArray modulation;
ControlArray modulation {};

Voice() :
mp_voice (NULL),
state (STATE_IDLE),
pedal (false)
{
modulation.fill (0);
}
~Voice()
{
Expand All @@ -148,7 +149,7 @@ private:
std::vector<Voice> voices;
std::vector<Voice *> idle_voices;
std::vector<Voice *> active_voices;
ModArray global_modulation;
ControlArray global_modulation {};
double m_mix_freq;
double m_gain = 1;
double m_tempo = 120;
Expand All @@ -173,12 +174,13 @@ private:
bool update_mono_voice();
float freq_from_note (float note);
void notify_active_voice_status();
float voice_control (const Voice *voice, int c);

void set_mono_enabled (bool new_value);
void process_audio (float *output, size_t n_values);
void process_note_on (const NoteEvent& note);
void process_note_off (int channel, int midi_note);
void process_midi_controller (int controller, int value);
void process_midi_controller (int channel, int controller, int value);
void process_pitch_bend (int channel, float value);
void process_mod_value (const ModValueEvent& mod);
void start_pitch_bend (Voice *voice, double dest_freq, double time_ms);
Expand Down

0 comments on commit 69b1a9c

Please sign in to comment.