/* * Copyright (C) 2013-2019 Robin Gareus * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE // needed for M_PI #endif #include #include #include #include #ifndef COMPILER_MSVC #include #endif #include #ifndef BUFFER_SIZE_SAMPLES #define BUFFER_SIZE_SAMPLES 64 #endif #ifndef MIN #define MIN(A, B) ((A) < (B) ? (A) : (B)) #endif /* internal MIDI event abstraction */ enum RMIDI_EV_TYPE { INVALID = 0, NOTE_ON, NOTE_OFF, PROGRAM_CHANGE, CONTROL_CHANGE, }; struct rmidi_event_t { enum RMIDI_EV_TYPE type; uint8_t channel; /**< the MIDI channel number 0-15 */ union { struct { uint8_t note; uint8_t velocity; } tone; struct { uint8_t param; uint8_t value; } control; } d; }; typedef struct { uint32_t tme[3]; // attack, decay, release times [settings:ms || internal:samples] float vol[2]; // attack, sustain volume [0..1] uint32_t off[3]; // internal use (added attack,decay,release times) } ADSRcfg; typedef struct _RSSynthChannel { uint32_t keycomp; uint32_t adsr_cnt[128]; 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, const size_t n_samples, float* left, float* right); } RSSynthChannel; typedef void (*SynthFunction) (RSSynthChannel* sc, const uint8_t note, const float vol, const float pc, const size_t n_samples, float* left, float* right); typedef struct { uint32_t boffset; float buf[2][BUFFER_SIZE_SAMPLES]; RSSynthChannel sc[16]; float freqs[128]; float kcgain; float kcfilt; double rate; uint32_t xmas_on; uint32_t xmas_off; } RSSynthesizer; /* initialize ADSR values * * @param rate sample-rate * @param a attack time in seconds * @param d decay time in seconds * @param r release time in seconds * @param avol attack gain [0..1] * @param svol sustain volume level [0..1] */ static void init_adsr (ADSRcfg* adsr, const double rate, const uint32_t a, const uint32_t d, const uint32_t r, const float avol, const float svol) { adsr->vol[0] = avol; adsr->vol[1] = svol; adsr->tme[0] = a * rate / 1000.0; adsr->tme[1] = d * rate / 1000.0; adsr->tme[2] = r * rate / 1000.0; assert (adsr->tme[0] > 32); assert (adsr->tme[1] > 32); assert (adsr->tme[2] > 32); assert (adsr->vol[0] >= 0 && adsr->vol[1] <= 1.0); assert (adsr->vol[1] >= 0 && adsr->vol[1] <= 1.0); adsr->off[0] = adsr->tme[0]; adsr->off[1] = adsr->tme[1] + adsr->off[0]; adsr->off[2] = adsr->tme[2] + adsr->off[1]; } /* calculate per-sample, per-key envelope */ static inline float adsr_env (RSSynthChannel* sc, const uint8_t note) { if (sc->adsr_cnt[note] < sc->adsr.off[0]) { // attack const uint32_t p = ++sc->adsr_cnt[note]; if (p == sc->adsr.tme[0]) { sc->adsr_amp[note] = sc->adsr.vol[0]; return sc->adsr.vol[0]; } else { const float d = sc->adsr.vol[0] - sc->adsr_amp[note]; return sc->adsr_amp[note] + (p / (float)sc->adsr.tme[0]) * d; } } else if (sc->adsr_cnt[note] < sc->adsr.off[1]) { // decay const uint32_t p = ++sc->adsr_cnt[note] - sc->adsr.off[0]; if (p == sc->adsr.tme[1]) { sc->adsr_amp[note] = sc->adsr.vol[1]; return sc->adsr.vol[1]; } else { const float d = sc->adsr.vol[1] - sc->adsr_amp[note]; return sc->adsr_amp[note] + (p / (float)sc->adsr.tme[1]) * d; } } else if (sc->adsr_cnt[note] == sc->adsr.off[1]) { // sustain return sc->adsr.vol[1]; } else if (sc->adsr_cnt[note] < sc->adsr.off[2]) { // release const uint32_t p = ++sc->adsr_cnt[note] - sc->adsr.off[1]; if (p == sc->adsr.tme[2]) { sc->adsr_amp[note] = 0; return 0; } else { const float d = 0 - sc->adsr_amp[note]; return sc->adsr_amp[note] + (p / (float)sc->adsr.tme[2]) * d; } } else { sc->adsr_cnt[note] = 0; return 0; } } /*****************************************************************************/ /* piano like sound w/slight stereo phase */ static void synthesize_sineP (RSSynthChannel* sc, const uint8_t note, const float vol, const float fq, const size_t n_samples, float* left, float* right) { size_t i; float phase = sc->phase[note]; for (i = 0; i < n_samples; ++i) { float env = adsr_env (sc, note); if (sc->adsr_cnt[note] == 0) { break; } const float amp = vol * env; 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, 800, 100 }, { 1.0, 0.0 }, { 0, 0, 0 } }; /*****************************************************************************/ /* process note - move through ADSR states, count active keys,.. */ static void process_key (void* synth, const uint8_t chn, const uint8_t note, const size_t n_samples, float* left, float* right) { 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.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; sc->phase[note] = 0; sc->keycomp++; //printf("[On] Now %d keys active on chn %d\n", sc->keycomp, chn); } 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] || 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] && !sus) { if (sc->adsr_cnt[note] != sc->adsr.off[1]) { // 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->keycomp--; //printf("[off] Now %d keys active on chn %d\n", sc->keycomp, chn); } } /* synthesize a BUFFER_SIZE_SAMPLES's of audio-data */ static void synth_fragment (void* synth, const size_t n_samples, float* left, float* right) { RSSynthesizer* rs = (RSSynthesizer*)synth; memset (left, 0, n_samples * sizeof (float)); memset (right, 0, n_samples * sizeof (float)); uint8_t keycomp = 0; int c, k; size_t i; for (c = 0; c < 16; ++c) { for (k = 0; k < 128; ++k) { if (rs->sc[c].miditable[k] == 0) { continue; } process_key (synth, c, k, n_samples, left, right); } keycomp += rs->sc[c].keycomp; } #if 1 // key-compression float kctgt = 8.0 / (float)(keycomp + 7.0); if (kctgt < .5) kctgt = .5; if (kctgt > 1.0) kctgt = 1.0; const float _w = rs->kcfilt; for (i = 0; i < n_samples; ++i) { rs->kcgain += _w * (kctgt - rs->kcgain); left[i] *= rs->kcgain; right[i] *= rs->kcgain; } rs->kcgain += 1e-12; #endif } static void synth_reset_channel (RSSynthChannel* sc) { int k; for (k = 0; k < 128; ++k) { sc->adsr_cnt[k] = 0; sc->adsr_amp[k] = 0; sc->phase[k] = -10; sc->miditable[k] = 0; sc->midimsgs[k] = 0; } sc->keycomp = 0; } static void synth_reset (void* synth) { RSSynthesizer* rs = (RSSynthesizer*)synth; int c; for (c = 0; c < 16; ++c) { synth_reset_channel (&(rs->sc[c])); } rs->kcgain = 0; } static void synth_load (RSSynthChannel* sc, const double rate, SynthFunction synthesize, ADSRcfg const* const adsr) { synth_reset_channel (sc); init_adsr (&sc->adsr, rate, adsr->tme[0], adsr->tme[1], adsr->tme[2], adsr->vol[0], adsr->vol[1]); sc->synthesize = synthesize; } /** * internal abstraction of MIDI data handling */ 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; 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 */ } 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: break; } } /****************************************************************************** * PUBLIC API (used by lv2.c) */ /** * align LV2 and internal synth buffers * call synth_fragment as often as needed for the given LV2 buffer size * * @param synth synth-handle * @param written samples written so far (offset in \ref out) * @param nframes total samples to synthesize and write to the \out buffer * @param out pointer to stereo output buffers * @return end of buffer (written + nframes) */ static uint32_t synth_sound (void* synth, uint32_t written, const uint32_t nframes, float** out) { RSSynthesizer* rs = (RSSynthesizer*)synth; while (written < nframes) { uint32_t nremain = nframes - written; if (rs->boffset >= BUFFER_SIZE_SAMPLES) { 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)); memcpy (&out[0][written], &rs->buf[0][rs->boffset], nread * sizeof (float)); memcpy (&out[1][written], &rs->buf[1][rs->boffset], nread * sizeof (float)); written += nread; rs->boffset += nread; } return written; } /** * parse raw midi-data. * * @param synth synth-handle * @param data 8bit midi message * @param size number of bytes in the midi-message */ static void synth_parse_midi (void* synth, const uint8_t* data, const size_t size) { 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 = data[1] & 0x7f; ev.d.tone.velocity = data[2] & 0x7f; break; case 0x90: 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; 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); } 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() * as soon as the sample-rate is known * * @param synth synth-handle * @param rate sample-rate */ static void synth_init (void* synth, double rate) { RSSynthesizer* rs = (RSSynthesizer*)synth; rs->rate = rate; rs->boffset = BUFFER_SIZE_SAMPLES; const float tuning = 440; int c, k; for (k = 0; k < 128; k++) { 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; synth_reset (synth); for (c = 0; c < 16; c++) { synth_load (&rs->sc[c], rate, &synthesize_sineP, &piano_adsr); } rs->xmas_on = 0; rs->xmas_off = 0; } /** * Allocate data-structure, create a handle for all other synth_* functions. * * This data should be freeded with \ref synth_free when the synth is no * longer needed. * * The synth can only be used after calling \rev synth_init as well. * * @return synth-handle */ static void* synth_alloc (void) { return calloc (1, sizeof (RSSynthesizer)); } /** * release synth data structure * @param synth synth-handle */ static void synth_free (void* synth) { free (synth); }