#include <stdlib.h>
#include <string.h>
#include <stdint.h>
+
+#ifndef COMPILER_MSVC
+#include <stdbool.h>
+#endif
+
#include <assert.h>
#ifndef BUFFER_SIZE_SAMPLES
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, sustained-off
+ int8_t sustain; // sustain pedal pressed
ADSRcfg adsr;
void (*synthesize) (struct _RSSynthChannel* sc,
const uint8_t note, const float vol, const float pc,
float kcgain;
float kcfilt;
double rate;
+ uint32_t xmas_on;
+ uint32_t xmas_off;
} RSSynthesizer;
float env = adsr_env(sc, note);
if (sc->adsr_cnt[note] == 0) break;
const float amp = vol * env;
-
- left[i] += amp * sinf(2.0 * M_PI * phase);
- left[i] += .300 * amp * sinf(2.0 * M_PI * phase * 2.0);
- left[i] += .150 * amp * sinf(2.0 * M_PI * phase * 3.0);
- left[i] += .080 * amp * sinf(2.0 * M_PI * phase * 4.0);
- //left[i] -= .007 * amp * sinf(2.0 * M_PI * phase * 5.0);
- //left[i] += .010 * amp * sinf(2.0 * M_PI * phase * 6.0);
- //left[i] += .020 * amp * sinf(2.0 * M_PI * phase * 7.0);
- phase += fq;
- right[i] += amp * sinf(2.0 * M_PI * phase);
- right[i] += .300 * amp * sinf(2.0 * M_PI * phase * 2.0);
- right[i] += .150 * amp * sinf(2.0 * M_PI * phase * 3.0);
- right[i] -= .080 * amp * sinf(2.0 * M_PI * phase * 4.0);
- //right[i] += .007 * amp * sinf(2.0 * M_PI * phase * 5.0);
- //right[i] += .010 * amp * sinf(2.0 * M_PI * phase * 6.0);
- //right[i] -= .020 * amp * sinf(2.0 * M_PI * phase * 7.0);
+ if (amp > 1e-10) {
+ left[i] += amp * sinf(2.0 * M_PI * phase);
+ left[i] += .300 * amp * sinf(2.0 * M_PI * phase * 2.0);
+ left[i] += .150 * amp * sinf(2.0 * M_PI * phase * 3.0);
+ left[i] += .080 * amp * sinf(2.0 * M_PI * phase * 4.0);
+ //left[i] -= .007 * amp * sinf(2.0 * M_PI * phase * 5.0);
+ //left[i] += .010 * amp * sinf(2.0 * M_PI * phase * 6.0);
+ left[i] += .020 * amp * sinf(2.0 * M_PI * phase * 7.0);
+ phase += fq;
+ right[i] += amp * sinf(2.0 * M_PI * phase);
+ right[i] += .300 * amp * sinf(2.0 * M_PI * phase * 2.0);
+ right[i] += .150 * amp * sinf(2.0 * M_PI * phase * 3.0);
+ right[i] -= .080 * amp * sinf(2.0 * M_PI * phase * 4.0);
+ //right[i] += .007 * amp * sinf(2.0 * M_PI * phase * 5.0);
+ //right[i] += .010 * amp * sinf(2.0 * M_PI * phase * 6.0);
+ right[i] -= .020 * amp * sinf(2.0 * M_PI * phase * 7.0);
+ } else {
+ phase += fq;
+ }
if (phase > 1.0) phase -= 2.0;
}
sc->phase[note] = phase;
}
-static const ADSRcfg piano_adsr = {{ 5, 1300, 100}, { 1.0, 0.0}, {0,0,0}};
+static const ADSRcfg piano_adsr = {{ 5, 800, 100}, { 1.0, 0.0}, {0,0,0}};
/*****************************************************************************/
RSSynthesizer* rs = (RSSynthesizer*)synth;
RSSynthChannel* sc = &rs->sc[chn];
const int8_t vel = sc->miditable[note];
- const float vol = /* master_volume */ 0.25 * fabsf(vel) / 127.0;
+ const int8_t msg = sc->midimsgs[note];
+ const float vol = /* master_volume */ 0.1f * abs(vel) / 127.f;
const float phase = sc->phase[note];
+ const int8_t sus = sc->sustain;
+ sc->midimsgs[note] &= ~3;
if (phase == -10 && vel > 0) {
// new note on
+ sc->midimsgs[note] &= ~4;
assert(sc->adsr_cnt[note] == 0);
sc->adsr_amp[note] = 0;
sc->adsr_cnt[note] = 0;
}
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 || msg == 5 || msg == 7) {
+ sc->midimsgs[note] &= ~4;
// x-fade to attack
sc->adsr_amp[note] = adsr_env(sc, note);
sc->adsr_cnt[note] = 0;
}
}
else if (phase >= -1.0 && phase <= 1.0 && vel < 0) {
+ sc->midimsgs[note] |= 4;
// note off
- if (sc->adsr_cnt[note] <= sc->adsr.off[1]) {
+ if (sc->adsr_cnt[note] <= sc->adsr.off[1] && !sus) {
if (sc->adsr_cnt[note] != sc->adsr.off[1]) {
- // x-fade to release
- sc->adsr_amp[note] = adsr_env(sc, note);
+ // x-fade to release
+ sc->adsr_amp[note] = adsr_env(sc, note);
}
sc->adsr_cnt[note] = sc->adsr.off[1] + 1;
}
+ else if (sus && sc->adsr_cnt[note] == sc->adsr.off[1]) {
+ sc->adsr_cnt[note] = sc->adsr.off[1] + 1;
+ }
}
else {
+ //printf("FORCE NOTE OFF: %d %d\n", vel, sus);
/* note-on + off in same cycle */
sc->miditable[note] = 0;
sc->adsr_cnt[note] = 0;
sc->phase[note] = -10;
return;
}
+ //printf("NOTE: %d (%d %d %d)\n", sc->adsr_cnt[note], sc->adsr.off[0], sc->adsr.off[1], sc->adsr.off[2]);
// synthesize actual sound
sc->synthesize(sc, note, vol, rs->freqs[note], n_samples, left, right);
if (sc->adsr_cnt[note] == 0) {
//printf("Note %d,%d released\n", chn, note);
+ sc->midimsgs[note] = 0;
sc->miditable[note] = 0;
sc->adsr_amp[note] = 0;
sc->phase[note] = -10;
sc->adsr_amp[k] = 0;
sc->phase[k] = -10;
sc->miditable[k] = 0;
+ sc->midimsgs[k] = 0;
}
sc->keycomp = 0;
}
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;
+ 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;
+ rs->sc[ev->channel].miditable[ev->d.tone.note] *= -1.0;
break;
case PROGRAM_CHANGE:
break;
case CONTROL_CHANGE:
if (ev->d.control.param == 0x00 || ev->d.control.param == 0x20) {
- /* 0x00 and 0x20 are used for BANK select */
- break;
- } else
- if (ev->d.control.param == 121) {
- /* reset all controllers */
- break;
- } else
- if (ev->d.control.param == 120 || ev->d.control.param == 123) {
- /* Midi panic: 120: all sound off, 123: all notes off*/
- synth_reset_channel(&(rs->sc[ev->channel]));
- break;
- } else
- if (ev->d.control.param >= 120) {
- /* params 122-127 are reserved - skip them. */
- break;
+ /* 0x00 and 0x20 are used for BANK select */
+ } else if (ev->d.control.param == 64) {
+ /* damper pedal*/
+ rs->sc[ev->channel].sustain = ev->d.control.value < 64 ? 0: 1;
+ } else if (ev->d.control.param == 121) {
+ /* reset all controllers */
+ } else if (ev->d.control.param == 120 || ev->d.control.param == 123) {
+ /* Midi panic: 120: all sound off, 123: all notes off*/
+ synth_reset_channel(&(rs->sc[ev->channel]));
+ } else if (ev->d.control.param >= 120) {
+ /* params 122-127 are reserved - skip them. */
}
break;
default:
uint32_t nremain = nframes - written;
if (rs->boffset >= BUFFER_SIZE_SAMPLES) {
- rs->boffset = 0;
- synth_fragment(rs, BUFFER_SIZE_SAMPLES, rs->buf[0], rs->buf[1]);
+ const uint32_t tosynth = MIN(BUFFER_SIZE_SAMPLES, nremain);
+ rs->boffset = BUFFER_SIZE_SAMPLES - tosynth;
+ synth_fragment(rs, tosynth, &(rs->buf[0][rs->boffset]), &(rs->buf[1][rs->boffset]));
}
uint32_t nread = MIN(nremain, (BUFFER_SIZE_SAMPLES - rs->boffset));
ev.type=NOTE_ON;
ev.d.tone.note=data[1]&0x7f;
ev.d.tone.velocity=data[2]&0x7f;
+ if (ev.d.tone.velocity == 0) {
+ ev.type=NOTE_OFF;
+ }
break;
case 0xB0:
ev.type=CONTROL_CHANGE;
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()
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;
for (c=0; c < 16; c++) {
synth_load(&rs->sc[c], rate, &synthesize_sineP, &piano_adsr);
}
+ rs->xmas_on = 0;
+ rs->xmas_off = 0;
}
/**
static void synth_free(void *synth) {
free(synth);
}
-/* vi:set ts=8 sts=2 sw=2: */
+/* vi:set ts=8 sts=2 sw=2 et: */