summaryrefslogtreecommitdiff
path: root/libs/plugins/reasonablesynth.lv2/rsynth.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/plugins/reasonablesynth.lv2/rsynth.c')
-rw-r--r--libs/plugins/reasonablesynth.lv2/rsynth.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/libs/plugins/reasonablesynth.lv2/rsynth.c b/libs/plugins/reasonablesynth.lv2/rsynth.c
index d2d5b3e905..061d72dbff 100644
--- a/libs/plugins/reasonablesynth.lv2/rsynth.c
+++ b/libs/plugins/reasonablesynth.lv2/rsynth.c
@@ -71,6 +71,7 @@ typedef struct _RSSynthChannel {
float adsr_amp[128];
float phase[128]; // various use, zero'ed on note-on
int8_t miditable[128]; // internal, note-on/off velocity
+ int8_t midimsgs [128]; // internal, note-off + on in same cycle
ADSRcfg adsr;
void (*synthesize) (struct _RSSynthChannel* sc,
const uint8_t note, const float vol, const float pc,
@@ -89,6 +90,8 @@ typedef struct {
float kcgain;
float kcfilt;
double rate;
+ uint32_t xmas_on;
+ uint32_t xmas_off;
} RSSynthesizer;
@@ -216,8 +219,10 @@ static void process_key (void *synth,
RSSynthesizer* rs = (RSSynthesizer*)synth;
RSSynthChannel* sc = &rs->sc[chn];
const int8_t vel = sc->miditable[note];
+ const int8_t msg = sc->midimsgs[note];
const float vol = /* master_volume */ 0.25 * fabsf(vel) / 127.0;
const float phase = sc->phase[note];
+ sc->midimsgs[note] = 0;
if (phase == -10 && vel > 0) {
// new note on
@@ -230,7 +235,7 @@ static void process_key (void *synth,
}
else if (phase >= -1.0 && phase <= 1.0 && vel > 0) {
// sustain note or re-start note while adsr in progress:
- if (sc->adsr_cnt[note] > sc->adsr.off[1]) {
+ if (sc->adsr_cnt[note] > sc->adsr.off[1] || msg == 3) {
// x-fade to attack
sc->adsr_amp[note] = adsr_env(sc, note);
sc->adsr_cnt[note] = 0;
@@ -305,6 +310,7 @@ static void synth_reset_channel(RSSynthChannel* sc) {
sc->adsr_amp[k] = 0;
sc->phase[k] = -10;
sc->miditable[k] = 0;
+ sc->midimsgs[k] = 0;
}
sc->keycomp = 0;
}
@@ -336,10 +342,12 @@ static void synth_process_midi_event(void *synth, struct rmidi_event_t *ev) {
RSSynthesizer* rs = (RSSynthesizer*)synth;
switch(ev->type) {
case NOTE_ON:
+ rs->sc[ev->channel].midimsgs[ev->d.tone.note] |= 1;
if (rs->sc[ev->channel].miditable[ev->d.tone.note] <= 0)
rs->sc[ev->channel].miditable[ev->d.tone.note] = ev->d.tone.velocity;
break;
case NOTE_OFF:
+ rs->sc[ev->channel].midimsgs[ev->d.tone.note] |= 2;
if (rs->sc[ev->channel].miditable[ev->d.tone.note] > 0)
rs->sc[ev->channel].miditable[ev->d.tone.note] *= -1.0;
break;
@@ -446,6 +454,44 @@ static void synth_parse_midi(void *synth, const uint8_t *data, const size_t size
synth_process_midi_event(synth, &ev);
}
+static const uint8_t jingle[] = { 71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,71 ,69 ,69 ,71 ,69 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,74 ,74 ,72 ,69 ,67 ,62 ,62 ,71 ,69 ,67 ,62 ,62 ,62 ,62 ,71 ,69 ,67 ,64 ,64 ,64 ,72 ,71 ,69 ,66 ,74 ,76 ,74 ,72 ,69 ,71 ,62 ,62 ,71 ,69 ,67 ,62 ,62 ,62 ,62 ,71 ,69 ,67 ,64 ,64 ,64 ,72 ,71 ,69 ,74 ,74 ,74 ,74 ,76 ,74 ,72 ,69 ,67 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,71 ,69 ,69 ,71 ,69 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,74 ,74 ,72 ,69 ,67 };
+
+static void synth_parse_xmas(void *synth, const uint8_t *data, const size_t size) {
+ RSSynthesizer* rs = (RSSynthesizer*)synth;
+ if (size < 2 || size > 3) return;
+ // All messages need to be 3 bytes; except program-changes: 2bytes.
+ if (size == 2 && (data[0] & 0xf0) != 0xC0) return;
+
+ struct rmidi_event_t ev;
+
+ ev.channel = data[0]&0x0f;
+ switch (data[0] & 0xf0) {
+ case 0x80:
+ ev.type=NOTE_OFF;
+ ev.d.tone.note=jingle[rs->xmas_off++];
+ ev.d.tone.velocity=data[2]&0x7f;
+ if (rs->xmas_off >= sizeof(jingle)) rs->xmas_off = 0;
+ break;
+ case 0x90:
+ ev.type=NOTE_ON;
+ ev.d.tone.note=jingle[rs->xmas_on++];
+ ev.d.tone.velocity=data[2]&0x7f;
+ if (rs->xmas_on >= sizeof(jingle)) rs->xmas_on = 0;
+ break;
+ case 0xB0:
+ ev.type=CONTROL_CHANGE;
+ ev.d.control.param=data[1]&0x7f;
+ ev.d.control.value=data[2]&0x7f;
+ break;
+ case 0xC0:
+ ev.type=PROGRAM_CHANGE;
+ ev.d.control.value=data[1]&0x7f;
+ break;
+ default:
+ return;
+ }
+ synth_process_midi_event(synth, &ev);
+}
/**
* initialize the synth
* This should be called after synth_alloc()
@@ -461,7 +507,7 @@ static void synth_init(void *synth, double rate) {
const float tuning = 440;
int c,k;
for (k=0; k < 128; k++) {
- rs->freqs[k] = (2.0 * tuning / 32.0f) * powf(2, (k - 9.0) / 12.0) / rate;
+ rs->freqs[k] = (tuning / 32.0f) * powf(2, (k - 9.0) / 12.0) / rate;
assert(rs->freqs[k] < M_PI/2); // otherwise spatialization may phase out..
}
rs->kcfilt = 12.0 / rate;
@@ -470,6 +516,8 @@ static void synth_init(void *synth, double rate) {
for (c=0; c < 16; c++) {
synth_load(&rs->sc[c], rate, &synthesize_sineP, &piano_adsr);
}
+ rs->xmas_on = 0;
+ rs->xmas_off = 0;
}
/**