commit f5f0369625d186ad69f968453b7dfcb10f9543de
parent 48f965ae8a00b74431d6498baae4cd900010900f
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Wed, 30 Dec 2020 23:18:52 +0000
attack, delay, release & sustain
Diffstat:
M | main.cpp | | | 59 | ++++++++++++++++++++++++++++++++++++++++++++++------------- |
1 file changed, 46 insertions(+), 13 deletions(-)
diff --git a/main.cpp b/main.cpp
@@ -167,28 +167,43 @@ int cb_sample_rate(jack_nframes_t nframes, void* arg)
static struct voice
{
float envelope, freq, sample;
+ unsigned char active : 1, velocity : 7, state : 2;
} voices[128];
int cb_process(jack_nframes_t nframes, void* arg)
{
+ static char sustain;
void* buf = jack_port_get_buffer(*p1, nframes);
jack_midi_event_t event;
for (uint32_t i = 0; not jack_midi_event_get(&event, buf, i); ++i)
{
- midi_data.write(event.buffer, event.size);
- ++midi_events;
-
+ auto& voice = voices[event.buffer[1]];
switch (event.buffer[0] >> 4 & 0x7)
{
case 0: // Note off
- voices[event.buffer[1]].envelope = 0;
- break;
+ voice.active = 0;
+ continue;
case 1: // Note on
- voices[event.buffer[1]].envelope = event.buffer[2] / 128.f;
- break;
+ voice.active = 1;
+ voice.state = 2;
+ voice.velocity = event.buffer[2];
+ continue;
+ case 3: // Controller change
+ switch (event.buffer[1])
+ {
+ case 0x40: // Sustain
+ sustain = event.buffer[2] > 63;
+ if (not sustain)
+ for (auto& v : voices)
+ if (not v.active and v.state == 1)
+ v.state = 0;
+ continue;
+ }
+ /* FALLTHROUGH */
default:
- ;
+ midi_data.write(event.buffer, event.size);
+ ++midi_events;
}
}
@@ -201,13 +216,33 @@ int cb_process(jack_nframes_t nframes, void* arg)
float accum = 0;
for (auto& v : voices)
{
- if (v.envelope < .02f)
- continue;
-
accum += std::sin(v.sample * 6.28318530718f / srate) * v.envelope;
v.sample += v.freq;
if (v.sample >= srate)
v.sample -= srate;
+
+ float velocity = v.velocity / 127.f;
+
+ if (v.state == 2)
+ {
+ v.envelope += velocity / 5000.f;
+ if (v.envelope >= velocity)
+ {
+ v.envelope = velocity;
+ v.state = 1;
+ }
+ }
+ else if (v.state == 1)
+ {
+ v.envelope -= (v.envelope - velocity * 0.2f) * 0.00005f;
+ if (not (sustain || v.active))
+ v.state = 0;
+ }
+ else
+ {
+ v.velocity = 0;
+ v.envelope *= 0.9998f;
+ }
}
audio_buf[i] = 2 / (1 + std::exp(accum)) - 1;
}
@@ -261,8 +296,6 @@ int main()
{
v.envelope = 0;
v.freq = 440 * std::pow(std::pow(2.f, 1.f/12), note++ - 69);
-
- std::cout << v.freq << "Hz\n";
}
client.set_process_callback(cb_process, nullptr);