Exemple #1
0
static void filter_preproc_midichord(MidiFilter* self) {
	int c,k,i;
	int identical_cfg = 1;
	int newchord = 0;

	for (i=0; i < 10; ++i) {
		if ((*self->cfg[i+2]) != 0) newchord |= 1<<i;
		if (floor(self->lcfg[i+2]) != floor(*self->cfg[i+2])) {
			identical_cfg = 0;
		}
	}
	if (floor(self->lcfg[1]) != floor(*self->cfg[1])) {
			identical_cfg = 0;
	}
	if (identical_cfg) return;

	const int newscale = RAIL(floor(*self->cfg[1]), 0, 11);
	const int oldscale = RAIL(floor(self->lcfg[1]), 0, 11);

	for (c=0; c < 16; ++c) {
		for (k=0; k < 127; ++k) {
			if (self->memCM[c][k] == 0) continue;
			if (self->memCI[c][k] == -1000) continue;

			const uint8_t vel = self->memCM[c][k];
			const int t0 = (k + 12 - oldscale) % 12;
			const int t1 = (k + 12 - newscale) % 12;

			const int oldchord = self->memCI[c][k];
			int chord = newchord;

			if (! filter_midichord_isonscale(t1)) {
				chord = 1;
			}

			for (i=0; i < 10 ; ++i) {

				if ((chord & (1<<i)) == (oldchord & (1<<i))
						&& !(chord & (1<<i))) {
					continue;
				}

				if ((chord & (1<<i)) == (oldchord & (1<<i))
						&& (filter_midichord_halftoneoffset(t0, i) == filter_midichord_halftoneoffset(t1, i))
						&& t0 == t1) {
						continue;
				}

				if (oldchord & (1<<i)) {
					filter_midichord_noteoff(self, 0, c, k + filter_midichord_halftoneoffset(t0, i), 0);
				}
				if (chord & (1<<i)) {
					filter_midichord_noteon(self, 0, c, k + filter_midichord_halftoneoffset(t1, i), vel);
				}
			}
			self->memCI[c][k] = chord;
		}
	}
}
Exemple #2
0
static void filter_preproc_enforcescale(MidiFilter* self) {
	if (floorf(self->lcfg[1]) == floorf(*self->cfg[1])) return;
	const int scale = RAIL(floorf(*self->cfg[1]), 0, 11);

	int c,k;
	uint8_t buf[3];
	buf[2] = 0;
	for (c=0; c < 16; ++c) {
		for (k=0; k < 127; ++k) {
			if (self->memCS[c][k] ==0) continue;

			if (filter_enforcescale_check(scale, k)) {
				self->memCI[c][k] = 0;
				continue;
			}

			buf[0] = MIDI_NOTEOFF | c;
			buf[1] = midi_limit_val(k);
			buf[2] = 0;
			forge_midimessage(self, 0, buf, 3);
			self->memCS[c][k] = 0;
			self->memCI[c][k] = 0;
		}
	}
}
Exemple #3
0
static void filter_preproc_keyrange(MidiFilter* self) {
	if (   floorf(self->lcfg[1]) == floorf(*self->cfg[1])
			&& floorf(self->lcfg[2]) == floorf(*self->cfg[2])
			&& floorf(self->lcfg[3]) == floorf(*self->cfg[3])
			) return;

	int c,k;
	uint8_t buf[3];
	buf[2] = 0;

	const int mode = RAIL(floorf(*self->cfg[3]),0, 3);
	const uint8_t low = midi_limit_val(floorf(*self->cfg[1]));
	const uint8_t upp = midi_limit_val(floorf(*self->cfg[2]));

	for (c=0; c < 16; ++c) {
		for (k=0; k < 127; ++k) {
			const uint8_t vel = self->memCM[c][k];
			if (vel == 0) continue;
			if (mode != 0 && (k >= low && k <= upp) ^ (mode == 2)) continue;
			buf[0] = MIDI_NOTEOFF | c;
			buf[1] = midi_limit_val(k + self->memCI[c][k]);
			forge_midimessage(self, 0, buf, 3);
			self->memCM[c][k] = 0;
		}
	}
}
static void filter_preproc_mapkeyscale(MidiFilter* self) {
	int i;
	int identical_cfg = 1;
	int keymap[12];
	for (i=0; i < 12; ++i) {
		keymap[i] = RAIL(floorf(*self->cfg[i+1]), -13, 12);
		if (floorf(self->lcfg[i+1]) != floorf(*self->cfg[i+1])) {
			identical_cfg = 0;
		}
	}
	if (identical_cfg) return;

	int c,k;
	uint8_t buf[3];
	buf[2] = 0;
	for (c=0; c < 16; ++c) {
		for (k=0; k < 127; ++k) {
			int note;
			const int n = 1 + k%12;
			if (!self->memCM[c][k]) continue;
			if (floorf(self->lcfg[n]) == floorf(*self->cfg[n])) continue;

			note = k + self->memCI[c][k];

			if (midi_valid(note)) {
				note = midi_limit_val(note);
				if (self->memCS[c][note] > 0) {
					self->memCS[c][note]--;
					if (self->memCS[c][note] == 0) {
						buf[0] = MIDI_NOTEOFF | c;
						buf[1] = note;
						buf[2] = 0;
						forge_midimessage(self, 0, buf, 3);
					}
				}
			}

			note = k + keymap[k%12];

			if (midi_valid(note)) {
				note = midi_limit_val(note);
				buf[0] = MIDI_NOTEON | c;
				buf[1] = note;
				buf[2] = self->memCM[c][k];
				self->memCI[c][k] = note - k;
				self->memCS[c][note]++;
				if (self->memCS[c][note] == 1) {
					forge_midimessage(self, 0, buf, 3);
				}
			} else {
				self->memCM[c][k] = 0;
				self->memCI[c][k] = -1000;
			}
		}
	}
}
static void
filter_preproc_ntabdelay(MidiFilter* self)
{
	int i,c,k;

	if (*self->cfg[4] != 0 && self->lcfg[4] == 0) for (c=0; c < 16; ++c) for (k=0; k < 127; ++k) {
		self->memCM[c][k] = 0; // remember velocity of note-on
		self->memCI[c][k] = -1; // remember time of note-on
	}

	float newbpm = MAX(*self->cfg[2], 1.0);
	if (*self->cfg[1] && (self->available_info & NFO_BPM)) {
		newbpm = self->bpm;
	}
	if (newbpm <= 0) newbpm = 60;

	if (self->memF[0] == newbpm && *self->cfg[2] == self->lcfg[2]) return;

	const float oldbpm = self->memF[0];
	self->memF[0] = newbpm;

	const float old_grid = RAIL((self->lcfg[3]), 1/256.0, 4.0);
	const double old_samples_per_beat = 60.0 / oldbpm * self->samplerate;
	const float new_grid = RAIL((*self->cfg[3]), 1/256.0, 4.0);
	const double new_samples_per_beat = 60.0 / newbpm * self->samplerate;

	const double fact = (new_grid * new_samples_per_beat) / (old_grid * old_samples_per_beat);

	const int max_delay = self->memI[0];
	const int roff = self->memI[1];
	const int woff = self->memI[2];

	for (i=0; i < max_delay; ++i) {
		const int off = (i + roff) % max_delay;
		if (self->memQ[off].size > 0) {
			self->memQ[off].reltime = rint(self->memQ[off].reltime * fact);
		}
		if (off == woff) break;
	}
}
Exemple #6
0
static void
filter_midi_keyrange(MidiFilter* self,
		uint32_t tme,
		const uint8_t* const buffer,
		uint32_t size)
{
	const int mode = RAIL(floorf(*self->cfg[3]),0, 3);
	const uint8_t chs = midi_limit_chn(floorf(*self->cfg[0]) -1);
	const uint8_t chn = buffer[0] & 0x0f;
	uint8_t mst = buffer[0] & 0xf0;

	if (size != 3
			|| !(mst == MIDI_NOTEON || mst == MIDI_NOTEOFF)
			|| !(floorf(*self->cfg[0]) == 0 || chs == chn)
			|| mode == 0
		 )
	{
		forge_midimessage(self, tme, buffer, size);
		return;
	}

	const uint8_t low = midi_limit_val(floorf(*self->cfg[1]));
	const uint8_t upp = midi_limit_val(floorf(*self->cfg[2]));
	const uint8_t key = buffer[1] & 0x7f;
	const uint8_t vel = buffer[2] & 0x7f;

	if (mst == MIDI_NOTEON && vel ==0 ) {
		mst = MIDI_NOTEOFF;
	}

	switch(mst) {
		case MIDI_NOTEON:
			if ((key >= low && key <= upp) ^ (mode == 2)) {
				forge_midimessage(self, tme, buffer, size);
				self->memCM[chn][key] = vel;
			}
			break;
		case MIDI_NOTEOFF:
			if (self->memCM[chn][key] > 0) {
				forge_midimessage(self, tme, buffer, size);
			}
			self->memCM[chn][key] = 0;
			break;
	}
}
Exemple #7
0
void
filter_midi_sostenuto(MidiFilter* self,
		const uint32_t tme,
		const uint8_t* const buffer,
		const uint32_t size)
{
	const uint8_t chs = midi_limit_chn(floorf(*self->cfg[0]) -1);
	const uint32_t delay = floor(self->samplerate * RAIL((*self->cfg[1]), 0, 120));

	const int pedal = RAIL(*self->cfg[2], 0, 2);
	int state;

	const uint8_t chn = buffer[0] & 0x0f;
	const uint8_t vel = buffer[2] & 0x7f;
	uint8_t mst = buffer[0] & 0xf0;

	/* pedal CC 64 -- TODO make CC (and theshold) configurable !? */
	if (size == 3 && mst == MIDI_CONTROLCHANGE && (buffer[1]) == 64) {
		self->memI[16 + chn] = vel > 63 ? 1 : 0;
	}

	if (size != 3
			|| !(mst == MIDI_NOTEON || mst == MIDI_NOTEOFF)
			|| !(floorf(*self->cfg[0]) == 0 || chs == chn)
			)
	{
		forge_midimessage(self, tme, buffer, size);
		return;
	}

	switch(pedal) {
		default:
		case 0: state = 0; break;
		case 1: state = 1; break;
		case 2: state = self->memI[16 + chn]; break;
	}

	if (mst == MIDI_NOTEON && vel ==0 ) {
		mst = MIDI_NOTEOFF;
	}

	if (size == 3 && mst == MIDI_NOTEON && state == 1) {
		const uint8_t chn = buffer[0] & 0x0f;
		const uint8_t key = buffer[1] & 0x7f;
		if (sostenuto_check_dup(self, chn, key, -1)) {
			/* note was already on,
			 * send note off + immediate note on, again
			 */
			uint8_t buf[3];
			buf[0] = MIDI_NOTEOFF | chn;
			buf[1] = key;
			buf[2] = 0;
			forge_midimessage(self, tme, buf, size);
		}
		forge_midimessage(self, tme, buffer, size);
	}
	else if (size == 3 && mst == MIDI_NOTEOFF && state == 1) {
		const uint8_t chn = buffer[0] & 0x0f;
		const uint8_t key = buffer[1] & 0x7f;

		if (!sostenuto_check_dup(self, chn, key, tme + delay)) {
			// queue note-off if not already queued
			MidiEventQueue *qm = &(self->memQ[self->memI[2]]);
			memcpy(qm->buf, buffer, size);
			qm->size = size;
			qm->reltime = tme + delay;
			self->memI[2] = (self->memI[2] + 1) % self->memI[0];
		}
	}
	else {
		forge_midimessage(self, tme, buffer, size);
	}

	/* only note-off are queued in the buffer.
	 * Interleave delay-buffer with messages sent in-process above
	 * to retain sequential order.
	 */
	self->memI[3] = tme + 1;
	filter_postproc_sostenuto(self);
	self->memI[3] = -1;
}
Exemple #8
0
static void
filter_preproc_sostenuto(MidiFilter* self)
{
	int i;
	const int max_delay = self->memI[0];
	const int roff = self->memI[1];
	const int woff = self->memI[2];
	const int pedal = RAIL(*self->cfg[2], 0, 2);
	int state;

	if (self->lcfg[1] == *self->cfg[1]
			&& (self->lcfg[2] == *self->cfg[2] && self->lcfg[2] < 2)) {
		/* no change: same pedal state for all channels and same time */
		for (i=32; i < 48; ++i) {
			/* remember per channel pedal state */
			self->memI[i] = pedal & 1;
		}
		return;
	}

	/* adjust time if changed || per-channel pedal state */

	const float diff = *self->cfg[1] - self->lcfg[1];
	const int delay = rint(self->samplerate * diff);

	for (i=0; i < max_delay; ++i) {
		const int off = (i + roff) % max_delay;

		if (pedal == 2) {
			const uint8_t chn = self->memQ[off].buf[0] & 0x0f;
			const int ostate = self->memI[32 + chn];
			state = self->memI[16 + chn];

			if (self->lcfg[1] == *self->cfg[1] && state == ostate) {
				/* no change: same pedal state for this channels and same time */
				if (off == woff) break;
				continue;
			}
		} else {
			state = pedal & 1;
		}

		if (self->memQ[off].size > 0) {
			if (state == 0) {
				self->memQ[off].reltime = 0;
			} else {
				self->memQ[off].reltime = MAX(0, self->memQ[off].reltime + delay);
			}
		}
		if (off == woff) break;
	}

	self->memI[3] = 1;
	filter_postproc_sostenuto(self);
	self->memI[3] = -1;

	/* remember per channel pedal state */
	for (i=16; i < 32; ++i) {
		if (pedal < 2) {
			self->memI[16+i] = pedal & 1;
		} else {
			self->memI[16+i] = self->memI[i];
		}
	}
}
Exemple #9
0
static void
filter_midi_enforcescale(MidiFilter* self,
		uint32_t tme,
		const uint8_t* const buffer,
		uint32_t size)
{
	const int chs = midi_limit_chn(floorf(*self->cfg[0]) -1);
	const int scale = RAIL(floorf(*self->cfg[1]), 0, 11);
	const int mode  = RAIL(floorf(*self->cfg[2]), 0, 2);

	const uint8_t chn = buffer[0] & 0x0f;
	const uint8_t key = buffer[1] & 0x7f;
	uint8_t mst = buffer[0] & 0xf0;

	if (midi_is_panic(buffer, size)) {
		filter_enforcescale_panic(self, chn, tme);
	}

	if (size != 3
			|| !(mst == MIDI_NOTEON || mst == MIDI_NOTEOFF || mst == MIDI_POLYKEYPRESSURE)
			|| !(floorf(*self->cfg[0]) == 0 || chs == chn)
			)
	{
		forge_midimessage(self, tme, buffer, size);
		return;
	}

	int transp = 0;

	if (!filter_enforcescale_check(scale, key)) {
		switch (mode) {
			case 1:
					transp = -1;
				break;
			case 2:
					transp = +1;
				break;
			case 0: /* discard */
			default:
				return;
		}
	}

	if (!midi_valid(key + transp)) {
		return;
	}

	if (!filter_enforcescale_check(scale, key + transp)) {
		return;
	}

	int note;
	uint8_t buf[3];
	memcpy(buf, buffer, 3);

	switch (mst) {
		case MIDI_NOTEON:
			note = key + transp;
			if (midi_valid(note)) {
				buf[1] = note;
				self->memCS[chn][note]++;
				if (self->memCS[chn][note] == 1)
					forge_midimessage(self, tme, buf, size);
			}
			self->memCI[chn][key] = transp;
			break;
		case MIDI_NOTEOFF:
			note = key + self->memCI[chn][key];
			if (midi_valid(note)) {
				buf[1] = note;
				if (self->memCS[chn][note] > 0) {
					self->memCS[chn][note]--;
					if (self->memCS[chn][note] == 0)
						forge_midimessage(self, tme, buf, size);
					self->memCI[chn][key] = 0;
				}
			}
			break;
		case MIDI_POLYKEYPRESSURE:
			note = key + transp;
			if (midi_valid(note)) {
				buf[1] = note;
				forge_midimessage(self, tme, buf, size);
			}
			break;
	}
}
Exemple #10
0
static void
run(LV2_Handle instance, uint32_t n_samples)
{
    XfadeControl* self = (XfadeControl*)instance;
    const float xfade = *self->xfade;
    const float shape = RAIL(*self->shape, 0.0, 1.0);
    const int   mode  = (int) RAIL(*self->mode, 0.0, 1.0);
    const uint32_t fade_len = (n_samples >= FADE_LEN) ? FADE_LEN : n_samples;
    float gain[IPORTS];
    float gainP[IPORTS];
    float gainL[IPORTS];

    if (mode == 1) { /* V-fade - non overlapping */
        if (xfade < 0) {
            gainL[0] = 1.0;
            gainP[0] = 1.0;
            gainL[1] = 1.0 + RAIL(xfade, -1.0, 0.0);
            gainP[1] = sqrt(1.0 + RAIL(xfade, -1.0, 0.0));
        } else if (xfade > 0) {
            gainL[0] = 1.0 - RAIL(xfade, 0.0, 1.0);
            gainP[0] = sqrt(1.0 - RAIL(xfade, 0.0, 1.0));
            gainL[1] = 1.0;
            gainP[1] = 1.0;
        } else {
            gainL[0] = 1.0;
            gainL[1] = 1.0;
            gainP[0] = 1.0;
            gainP[1] = 1.0;
        }

    } else { /* X-fade overlapping */

        gainL[1] = 0.5 + RAIL(xfade, -1.0, 1.0)/2.0;
        gainL[0] = 1.0 - gainL[1];

        /* equal power gain */
        if (xfade == -1.0) {
            gainP[0] = 1.0;
            gainP[1] = 0.0;
        } else if (xfade == 1.0) {
            gainP[0] = 0.0;
            gainP[1] = 1.0;
        } else {
            gainP[1] = sqrt(.5 + RAIL(xfade/2.0, -.5, .5));
            gainP[0] = sqrt(.5 - RAIL(xfade/2.0, -.5, .5));
        }

    }


    gain[0] = shape * gainP[0] + (1.0 - shape) * gainL[0];
    gain[1] = shape * gainP[1] + (1.0 - shape) * gainL[1];

#if 0 // debug
#define VALTODB(V) (20.0f * log10f(V))
    printf("%.2fdB %.2fdB ||A: %.2f %.2f || B: %.2f %.2f || s:%.2f m:%d\n",
           VALTODB(gain[0]), VALTODB(gain[1]),
           gainL[0], gainL[1],
           gainP[0], gainP[1], shape, mode
          );
#endif

    for (int c = 0; c < CHANNELS; ++c) {
        uint32_t pos = 0;
        if (self->c_amp[0] == gain[0] &&  self->c_amp[1] == gain[1]) {
            for (pos = 0; pos < n_samples; pos++) {
                self->output[c][pos] =
                    self->input[0][c][pos] * gain[0]
                    + self->input[1][c][pos] * gain[1];
            }
        } else {
            for (pos = 0; pos < n_samples; pos++) {
                self->output[c][pos] =
                    self->input[0][c][pos] * SMOOTHGAIN(self->c_amp[0], gain[0])
                    + self->input[1][c][pos] * SMOOTHGAIN(self->c_amp[1], gain[1]);
            }
        }
    }

    self->c_amp[0] = gain[0];
    self->c_amp[1] = gain[1];
}
static void
filter_midi_mapkeyscale(MidiFilter* self,
		uint32_t tme,
		const uint8_t* const buffer,
		uint32_t size)
{
	int i;
	const int chs = midi_limit_chn(floorf(*self->cfg[0]) -1);
	int keymap[12];
	for (i=0; i < 12; ++i) {
		keymap[i] = RAIL(floorf(*self->cfg[i+1]), -13, 12);
	}

	const uint8_t chn = buffer[0] & 0x0f;
	uint8_t mst = buffer[0] & 0xf0;

	if (midi_is_panic(buffer, size)) {
		filter_mapkeyscale_panic(self, chn, tme);
	}

	if (size != 3
			|| !(mst == MIDI_NOTEON || mst == MIDI_NOTEOFF || mst == MIDI_POLYKEYPRESSURE)
			|| !(floorf(*self->cfg[0]) == 0 || chs == chn)
			)
	{
		forge_midimessage(self, tme, buffer, size);
		return;
	}

	const uint8_t key = buffer[1] & 0x7f;
	const uint8_t vel = buffer[2] & 0x7f;

	if (mst == MIDI_NOTEON && vel ==0 ) {
		mst = MIDI_NOTEOFF;
	}

	int note;
	uint8_t buf[3];
	memcpy(buf, buffer, 3);

	switch (mst) {
		case MIDI_NOTEON:
			if (keymap[key%12] < -12) return;
			note = key + keymap[key%12];
			// TODO keep track of dup result note-on -- see enforcescale.c
			if (midi_valid(note)) {
				buf[1] = note;
				self->memCS[chn][note]++;
				if (self->memCS[chn][note] == 1) {
					forge_midimessage(self, tme, buf, size);
				}
				self->memCM[chn][key] = vel;
				self->memCI[chn][key] = note - key;
			}
			break;
		case MIDI_NOTEOFF:
			note = key + self->memCI[chn][key];
			if (midi_valid(note)) {
				buf[1] = note;
				if (self->memCS[chn][note] > 0) {
					self->memCS[chn][note]--;
					if (self->memCS[chn][note] == 0)
						forge_midimessage(self, tme, buf, size);
				}
			}
			self->memCM[chn][key] = 0;
			self->memCI[chn][key] = -1000;
			break;
		case MIDI_POLYKEYPRESSURE:
			if (keymap[key%12] < -12) return;
			note = key + keymap[key%12];
			if (midi_valid(note)) {
				buf[1] = note;
				forge_midimessage(self, tme, buf, size);
			}
			break;
	}
}
Exemple #12
0
static void
filter_midi_midichord(MidiFilter* self,
		uint32_t tme,
		const uint8_t* const buffer,
		uint32_t size)
{
	int i;
	const int chs = midi_limit_chn(floor(*self->cfg[0]) -1);
	const int scale = RAIL(floor(*self->cfg[1]), 0, 11);

	int chord = 0;
	for (i=0; i < 10 ; ++i) {
		if ((*self->cfg[i+2]) != 0) chord |= 1<<i;
	}

	const uint8_t chn = buffer[0] & 0x0f;
	uint8_t mst = buffer[0] & 0xf0;

	if (midi_is_panic(buffer, size)) {
		filter_midichord_panic(self, chn, tme);
	}

	if (size != 3
			|| !(mst == MIDI_NOTEON || mst == MIDI_NOTEOFF || mst == MIDI_POLYKEYPRESSURE)
			|| !(floor(*self->cfg[0]) == 0 || chs == chn)
			)
	{
		forge_midimessage(self, tme, buffer, size);
		return;
	}

	const uint8_t key = buffer[1] & 0x7f;
	const uint8_t vel = buffer[2] & 0x7f;
	const int tonika = (key + 12 - scale) % 12;

	if (! filter_midichord_isonscale(tonika)) {
		chord = 1;
	}

	switch (mst) {
		case MIDI_NOTEON:
			self->memCI[chn][key] = chord;
			self->memCM[chn][key] = vel;
			for (i=0; i < 10 ; ++i) {
				if (!(chord & (1<<i))) continue;
				filter_midichord_noteon(self, tme, chn, key + filter_midichord_halftoneoffset(tonika, i), vel);
			}
			break;
		case MIDI_NOTEOFF:
			chord = self->memCI[chn][key];
			for (i=0; i < 10 ; ++i) {
				if (!(chord & (1<<i))) continue;
				filter_midichord_noteoff(self, tme, chn, key + filter_midichord_halftoneoffset(tonika, i), vel);
			}
			self->memCI[chn][key] = -1000;
			self->memCM[chn][key] = 0;
			break;
		case MIDI_POLYKEYPRESSURE:
			for (i=0; i < 10 ; ++i) {
				uint8_t buf[3];
				if (!(chord & (1<<i))) continue;
				int note = key + filter_midichord_halftoneoffset(tonika, i);
				if (midi_valid(note)) {
					buf[0] = buffer[0];
					buf[1] = note;
					buf[2] = buffer[2];
					forge_midimessage(self, tme, buf, size);
				}
			}
			break;
	}
}
Exemple #13
0
static void
run(LV2_Handle instance, uint32_t n_samples)
{
	uint32_t i,c;
	BalanceControl* self = (BalanceControl*)instance;
	const float balance = *self->balance;
	const float trim = db_to_gain(*self->trim);
	float gain_left  = 1.0;
	float gain_right = 1.0;

	const int ascnt = self->samplerate / UPDATE_FREQ;

  const uint32_t capacity = self->notify->atom.size;
  lv2_atom_forge_set_buffer(&self->forge, (uint8_t*)self->notify, capacity);
  lv2_atom_forge_sequence_head(&self->forge, &self->frame, 0);

  /* reset after state restore */
	if (self->queue_stateswitch) {
		self->queue_stateswitch = 0;
		self->peak_integrate_pref = self->state[0] * self->samplerate;
		self->meter_falloff = self->state[1] / UPDATE_FREQ;
		self->peak_hold = self->state[2] * UPDATE_FREQ;

		self->peak_integrate_pref = MAX(0, self->peak_integrate_pref);
		self->peak_integrate_pref = MIN(self->peak_integrate_pref, self->peak_integrate_max);

		self->meter_falloff = MAX(0, self->meter_falloff);
		self->meter_falloff = MIN(self->meter_falloff, 1000);

		self->peak_hold = MAX(0, self->peak_hold);
		self->peak_hold = MIN(self->peak_hold, 60 * UPDATE_FREQ);
		reset_uicom(self);
		send_cfg_to_ui(self);
	}

  /* Process incoming events from GUI */
  if (self->control) {
    LV2_Atom_Event* ev = lv2_atom_sequence_begin(&(self->control)->body);
    while(!lv2_atom_sequence_is_end(&(self->control)->body, (self->control)->atom.size, ev)) {
      if (ev->body.type == self->uris.atom_Blank || ev->body.type == self->uris.atom_Object) {
				const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body;
				if (obj->body.otype == self->uris.blc_meters_on) {
					if (self->uicom_active == 0) {
						reset_uicom(self);
						send_cfg_to_ui(self);
						self->uicom_active = 1;
					}
				}
				if (obj->body.otype == self->uris.blc_meters_off) {
					self->uicom_active = 0;
				}
				if (obj->body.otype == self->uris.blc_meters_cfg) {
					const LV2_Atom* key = NULL;
					const LV2_Atom* value = NULL;
					lv2_atom_object_get(obj, self->uris.blc_cckey, &key, self->uris.blc_ccval, &value, 0);
					if (value && key) {
						update_meter_cfg(self, ((LV2_Atom_Int*)key)->body, ((LV2_Atom_Float*)value)->body);
					}
				}
			}
      ev = lv2_atom_sequence_next(ev);
    }
	}

	/* pre-calculate parameters */
	if (balance < 0) {
		gain_right = 1.0 + RAIL(balance, -1.0, 0.0);
	} else if (balance > 0) {
		gain_left = 1.0 - RAIL(balance, 0.0, 1.0);
	}

	switch ((int) *self->unitygain) {
		case 1:
			{
				/* maintain amplitude sum */
				const double gaindiff = (gain_left - gain_right);
				gain_left = 1.0 + gaindiff;
				gain_right = 1.0 - gaindiff;
			}
			break;
		case 2:
			{
				/* equal power*/
				if (balance < 0) {
					gain_right = MAX(.5, gain_right);
					gain_left = db_to_gain(-gain_to_db(gain_right));
				} else {
					gain_left = MAX(.5, gain_left);
					gain_right = db_to_gain(-gain_to_db(gain_left));
				}
			}
		case 0:
			/* 'tradidional' balance */
			break;
	}

	if (*(self->phase[C_LEFT])) gain_left *=-1;
	if (*(self->phase[C_RIGHT])) gain_right *=-1;

	/* keep track of input levels -- only if GUI is visiable */
	if (self->uicom_active) {
		for (c=0; c < CHANNELS; ++c) {
			for (i=0; i < n_samples; ++i) {
				/* input peak meter */
				const float ps = fabsf(self->input[c][i]);
				if (ps > self->p_peak_in[c]) self->p_peak_in[c] = ps;

				if (self->peak_integrate_pref < 1) {
					const float psm = ps * ps;
					if (psm > self->p_peak_inM[c]) self->p_peak_inM[c] = psm;
					continue;
				}

				/* integrated level, peak */
				const int pip = (self->peak_integrate_pos + i ) % self->peak_integrate_pref;
				const double p_sig = SQUARE(self->input[c][i]);
				self->p_peak_inP[c] += p_sig - self->p_peak_inPi[c][pip];
				self->p_peak_inPi[c][pip] = p_sig;
				/* peak of integrated signal */
				const float psm = self->p_peak_inP[c] / (double) self->peak_integrate_pref;
				if (psm > self->p_peak_inM[c]) self->p_peak_inM[c] = psm;
			}
		}
	}

	/* process audio -- delayline + balance & gain */
	process_channel(self, gain_left * trim,  C_LEFT, n_samples);
	process_channel(self, gain_right * trim, C_RIGHT, n_samples);

	/* swap/assign channels */
	uint32_t pos = 0;

	if (self->c_monomode != (int) *self->monomode) {
		/* smooth change */
		const uint32_t fade_len = (n_samples >= FADE_LEN) ? FADE_LEN : n_samples;
		for (; pos < fade_len; pos++) {
			const float gain = (float)pos / (float)fade_len;
			float x1[CHANNELS], x2[CHANNELS];
			channel_map_change(self, self->c_monomode, pos, x1);
			channel_map_change(self, (int) *self->monomode, pos, x2);
			self->output[C_LEFT][pos] = x1[C_LEFT] * (1.0 - gain) + x2[C_LEFT] * gain;
			self->output[C_RIGHT][pos] = x1[C_RIGHT] * (1.0 - gain) + x2[C_RIGHT] * gain;
		}
	}

	channel_map(self, (int) *self->monomode, pos, n_samples);
	self->c_monomode = (int) *self->monomode;

	/* audio processing done */

	if (!self->uicom_active) {
		return;
	}

	/* output peak meter */
	for (c=0; c < CHANNELS; ++c) {
		for (i=0; i < n_samples; ++i) {
			/* peak */
			const float ps = fabsf(self->output[c][i]);
			if (ps > self->p_peak_out[c]) self->p_peak_out[c] = ps;

				if (self->peak_integrate_pref < 1) {
				const float psm = ps * ps;
				if (psm > self->p_peak_outM[c]) self->p_peak_outM[c] = psm;
				continue;
			}

			/* integrated level, peak */
			const int pip = (self->peak_integrate_pos + i ) % self->peak_integrate_pref;
			const double p_sig = SQUARE(self->output[c][i]);
			self->p_peak_outP[c] += p_sig - self->p_peak_outPi[c][pip];
			self->p_peak_outPi[c][pip] = p_sig;
			/* peak of integrated signal */
			const float psm = self->p_peak_outP[c] / (double) self->peak_integrate_pref;
			if (psm > self->p_peak_outM[c]) self->p_peak_outM[c] = psm;
		}
	}
	if (self->peak_integrate_pref > 0) {
		self->peak_integrate_pos = (self->peak_integrate_pos + n_samples ) % self->peak_integrate_pref;
	}

	/* simple output phase correlation */
	for (i=0; i < n_samples; ++i) {
		const double p_pos = SQUARE(self->output[C_LEFT][i] + self->output[C_RIGHT][i]);
		const double p_neg = SQUARE(self->output[C_LEFT][i] - self->output[C_RIGHT][i]);

		/* integrate over 500ms */
		self->p_phase_outP += p_pos - self->p_phase_outPi[self->phase_integrate_pos];
		self->p_phase_outN += p_neg - self->p_phase_outNi[self->phase_integrate_pos];
		self->p_phase_outPi[self->phase_integrate_pos] = p_pos;
		self->p_phase_outNi[self->phase_integrate_pos] = p_neg;
		self->phase_integrate_pos = (self->phase_integrate_pos + 1) % self->phase_integrate_max;
	}

/* abs peak hold */
#define PKM(A,CHN,ID) \
{ \
	const float peak = VALTODB(self->p_peak_##A[CHN]); \
	if (peak > self->p_max_##A[CHN]) { \
		self->p_max_##A[CHN] = peak; \
		self->p_tme_##A[CHN] = 0; \
		forge_kvcontrolmessage(&self->forge, &self->uris, ID, self->p_max_##A[CHN]); \
	} else if (self->peak_hold <= 0) { \
		(self->p_tme_##A[CHN])=0; /* infinite hold */ \
	} else if (self->p_tme_##A[CHN] <= self->peak_hold) { \
		(self->p_tme_##A[CHN])++; \
	} else if (self->meter_falloff == 0) { \
		self->p_max_##A[CHN] = peak; \
		forge_kvcontrolmessage(&self->forge, &self->uris, ID, self->p_max_##A[CHN]); \
	} else { \
		self->p_max_##A[CHN] -= self->meter_falloff; \
		self->p_max_##A[CHN] = MAX(peak, self->p_max_##A[CHN]); \
		forge_kvcontrolmessage(&self->forge, &self->uris, ID, self->p_max_##A[CHN]); \
	} \
}

/* RMS meter */
#define PKF(A,CHN,ID) \
{ \
	float dbp = VALTODB(sqrt(2.0 * self->p_peak_##A##M[CHN])); \
	if (dbp > self->p_vpeak_##A[CHN]) { \
		self->p_vpeak_##A[CHN] = dbp; \
	} else if (self->meter_falloff == 0) { \
		self->p_vpeak_##A[CHN] = dbp; \
	} else { \
		self->p_vpeak_##A[CHN] -= self->meter_falloff; \
		self->p_vpeak_##A[CHN] = MAX(dbp, self->p_vpeak_##A[CHN]); \
	} \
	forge_kvcontrolmessage(&self->forge, &self->uris, ID, (self->p_vpeak_##A [CHN])); \
}

	/* report peaks to UI */
	self->p_peakcnt += n_samples;
	if (self->p_peakcnt > ascnt) {

		PKF(in,  C_LEFT,  METER_IN_LEFT)
		PKF(in,  C_RIGHT, METER_IN_RIGHT);
		PKF(out, C_LEFT,  METER_OUT_LEFT);
		PKF(out, C_RIGHT, METER_OUT_RIGHT);

		PKM(in,  C_LEFT,  PEAK_IN_LEFT);
		PKM(in,  C_RIGHT, PEAK_IN_RIGHT);
		PKM(out, C_LEFT,  PEAK_OUT_LEFT);
		PKM(out, C_RIGHT, PEAK_OUT_RIGHT);

#define RMSF(A) sqrt( ( (A) / (double)self->phase_integrate_max ) + 1.0e-12 )
		double phase = 0.0;
		const double phasdiv = self->p_phase_outP + self->p_phase_outN;
		if (phasdiv >= 1.0e-6) {
			phase = (RMSF(self->p_phase_outP) - RMSF(self->p_phase_outN)) / RMSF(phasdiv);
		} else if (self->p_phase_outP > .001 && self->p_phase_outN > .001) {
			phase = 1.0;
		}

		forge_kvcontrolmessage(&self->forge, &self->uris, PHASE_OUT, phase);

		self->p_peakcnt -= ascnt;
		for (c=0; c < CHANNELS; ++c) {
			self->p_peak_in[c] = -INFINITY;
			self->p_peak_out[c] = -INFINITY;
			self->p_peak_inM[c] = -INFINITY;
			self->p_peak_outM[c] = -INFINITY;
		}
	}

	/* report values to UI - if changed*/
	float bal = gain_to_db(fabsf(gain_left));
	if (bal != self->p_bal[C_LEFT]) {
		forge_kvcontrolmessage(&self->forge, &self->uris, GAIN_LEFT, bal);
	}
	self->p_bal[C_LEFT] = bal;

	bal = gain_to_db(fabsf(gain_right));
	if (bal != self->p_bal[C_RIGHT]) {
		forge_kvcontrolmessage(&self->forge, &self->uris, GAIN_RIGHT, bal);
	}
	self->p_bal[C_RIGHT] = bal;

	if (self->p_dly[C_LEFT] != self->c_dly[C_LEFT]) {
		forge_kvcontrolmessage(&self->forge, &self->uris, DELAY_LEFT, (float) self->c_dly[C_LEFT] / self->samplerate);
	}
	self->p_dly[C_LEFT] = self->c_dly[C_LEFT];

	if (self->p_dly[C_RIGHT] != self->c_dly[C_RIGHT]) {
		forge_kvcontrolmessage(&self->forge, &self->uris, DELAY_RIGHT, (float) self->c_dly[C_RIGHT] / self->samplerate);
	}
	self->p_dly[C_RIGHT] = self->c_dly[C_RIGHT];

}
Exemple #14
0
static void
filter_midistrum_process(MidiFilter* self, int tme)
{
	int i;
	const int max_collect = 1 + rintf(self->samplerate * (*self->cfg[3]) / 1000.0);
	if (self->memI[5] == 0) return; // no notes collected

	if (MSC_DIFF(self->memI[3], self->memI[4]) + tme < 0) {
		/* collection time not over */
		if (self->memI[5] < MAX_STRUM_CHORDNOTES) {
			/* buffer is not full, either */
			return;
		}
	}


	float bpm = (*self->cfg[1]);
	if (*self->cfg[0] && (self->available_info & NFO_BPM)) {
		bpm = self->bpm;
	}
	if (bpm <= 0) bpm = 60;
	const int strum_time = floor(self->samplerate * (*self->cfg[4]) * 60.0 / bpm);

	int dir = 0; // 0: down (low notes first), 1: up (high-notes first)
	switch ((int) floorf(*self->cfg[2])) {
		case 0: // always down
			break;
		case 1: // always up
			dir = 1;
			break;
		case 2: // alternate
			dir = (self->memI[6]) ? 1 : 0;
			break;
		case 3: // depending on beat.. 1,2,3,4 down ;; 1+,2+,3+,4+ up
			if ((self->available_info & NFO_BEAT)) {
				const double samples_per_beat = 60.0 / self->bpm * self->samplerate;
				if (ROUND_PARTIAL_BEATS(self->beat_beats + ((tme - max_collect) / samples_per_beat), 12.0) >= 0.5) {
					dir = 1;
				}
			}
			break;
		case 4: // depending on 8th
			if ((self->available_info & NFO_BEAT)) {
				const double samples_per_beat = 60.0 / self->bpm * self->samplerate;
				const float pos = ROUND_PARTIAL_BEATS(self->beat_beats + ((tme - max_collect) / samples_per_beat), 16.0) * 2.0;
				if ( pos - floorf(pos) >= 0.5) {
					dir = 1;
				}
			}
			break;
	}
	self->memI[6] = !dir;

	int reltime = MSC_DIFF(self->memI[4], self->memI[3]);
	int tdiff = strum_time / self->memI[5];


	float spdcfg = -(*self->cfg[5]);
	float velcfg = (*self->cfg[6]) / -112.0;

	spdcfg +=  (*self->cfg[7]) * (2.0 * random() / (float)RAND_MAX - 1.0);
	velcfg +=  (*self->cfg[8]) * (2.0 * random() / (float)RAND_MAX - 1.0);

	spdcfg = RAIL(spdcfg, -1.0, 1.0);

	const float veladj = RAIL(velcfg, -1.0, 1.0);
	const float spdadj = fabsf(spdcfg);
	const int   spddir = spdcfg < 0 ? 1 : 0;

	/* sort notes by strum direction.. */
	for (i=0; i < self->memI[5]; ++i) {
		int nextup = -1;
		int ii;
		for (ii=0; ii < self->memI[5]; ++ii) {
			if (self->memS[ii].size == 0) continue;
			if (nextup < 0) { nextup = ii; continue;}
			if (dir) {
				if (self->memS[nextup].buf[1] < self->memS[ii].buf[1] ) nextup = ii;
			} else {
				if (self->memS[nextup].buf[1] > self->memS[ii].buf[1] ) nextup = ii;
			}
		}

		if ((self->memI[2] + 1) % self->memI[0] == self->memI[1]) { break; }

		/* velocity adjustment */
		int vel = self->memS[nextup].buf[2] & 0x7f;
		const float p0 = (float)(i+1.0) / (float)(self->memI[5] + 1.0);

		vel -= fabsf(veladj) * 56.0;
		if (veladj < 0)
			vel += fabsf(veladj) * 112.0 * p0;
		else
			vel += fabsf(veladj) * 112.0 * (1.0 - p0);
		self->memS[nextup].buf[2] = RAIL(vel, 1, 127);

		/* speed adjustment */
		const float p1 = (float)(i+1.0) / (float)(self->memI[5]);
		float sfact = pow(spdadj+1.0, p1) - spdadj;
		if (spddir) {
			sfact = sfact ==0 ? 0 : 1.0 / sqrt(sfact);
		}

		MidiEventQueue *qm = &(self->memQ[self->memI[2]]);
		memcpy(qm->buf, self->memS[nextup].buf, self->memS[nextup].size);
		qm->size = self->memS[nextup].size;
		qm->reltime = reltime + rint((float)(tdiff * i) * sfact);
		self->memI[2] = (self->memI[2] + 1) % self->memI[0];
		self->memS[nextup].size = 0; // mark as processed
	}

	self->memI[5] = 0;
}
void
filter_midi_ntabdelay(MidiFilter* self,
		const uint32_t tme,
		const uint8_t* const buffer,
		const uint32_t size)
{
	int i;
	float bpm = MAX(*self->cfg[2], 1.0);
	if (*self->cfg[1] && (self->available_info & NFO_BPM)) {
		bpm = self->bpm;
	}
	if (bpm <= 0) bpm = 60;

	if (midi_is_panic(buffer, size)) {
		filter_ntapdelay_panic(self, buffer[0]&0x0f, tme);
	}

	forge_midimessage(self, tme, buffer, size);

	const uint8_t chs = midi_limit_chn(floor(*self->cfg[0]) -1);
	const uint8_t chn = buffer[0] & 0x0f;
	uint8_t mst = buffer[0] & 0xf0;

	if (size != 3
			|| !(mst == MIDI_NOTEON || mst == MIDI_NOTEOFF || mst == MIDI_POLYKEYPRESSURE)
			|| !(floor(*self->cfg[0]) == 0 || chs == chn)
		 )
	{
		return;
	}

	if ((self->memI[2] + 1) % self->memI[0] == self->memI[1]) {
		return;
	}

	const float grid = RAIL((*self->cfg[3]), 1/256.0, 4.0);
	const double samples_per_beat = 60.0 / bpm * self->samplerate;
	const uint8_t key = buffer[1] & 0x7f;
	const uint8_t vel = buffer[2] & 0x7f;

	uint8_t buf[3];
	memcpy(buf, buffer, 3);

	/* treat note-on w/velocity==0 as note-off */
	if (mst == MIDI_NOTEON && vel == 0) {
		mst = MIDI_NOTEOFF;
		buf[0] = MIDI_NOTEOFF | chn;
	}

	if (mst == MIDI_NOTEON) {
		self->memCI[chn][key] = tme + rint(grid * samples_per_beat);
		self->memCM[chn][key] = vel;
	}
	else if (mst == MIDI_NOTEOFF) {
		self->memCI[chn][key] = -1;
		self->memCM[chn][key] = 0;
	}

	for (i=0; i < RAIL(*self->cfg[4], 0, 128); ++i) {
		int delay = rint( grid * samples_per_beat * (i+1.0));
		buf[2] = RAIL(rint(vel + (i+1.0) * (*self->cfg[5])), 1, 127);
		MidiEventQueue *qm = &(self->memQ[self->memI[2]]);
		memcpy(qm->buf, buf, 3);
		qm->size = size;
		qm->reltime = tme + delay;
		self->memI[2] = (self->memI[2] + 1) % self->memI[0];

		if ((self->memI[2] + 1) % self->memI[0] == self->memI[1]) {
			return;
		}
	}
}
static void
filter_postproc_ntabdelay(MidiFilter* self)
{
	int i,c,k;
	const int max_delay = self->memI[0];
	const int roff = self->memI[1];
	const int woff = self->memI[2];
	const uint32_t n_samples = self->n_samples;
	int skipped = 0;

	float bpm = MAX(*self->cfg[2], 1.0);
	if (*self->cfg[1] && (self->available_info & NFO_BPM)) {
		bpm = self->bpm;
	}
	if (bpm <= 0) bpm = 60;
	const float grid = RAIL((*self->cfg[3]), 1/256.0, 4.0);
	const double samples_per_beat = 60.0 / bpm * self->samplerate;

	/* add note-on/off for held notes..
	 * TODO: use a preallocated stack-like structure
	 */
	if (*self->cfg[4] == 0) for (c=0; c < 16; ++c) for (k=0; k < 127; ++k) {
		if (self->memCM[c][k] == 0) continue;

		if (self->memCI[c][k] >= n_samples) {
			self->memCI[c][k] -= n_samples;
			continue;
		}

		while (1) {
			self->memCM[c][k] = RAIL(rint(self->memCM[c][k] + (*self->cfg[5])), 1, 127);
			/* enqueue note-off + note-on */
			MidiEventQueue *qm = &(self->memQ[self->memI[2]]);
			qm->buf[0] = MIDI_NOTEOFF | c;
			qm->buf[1] = k;
			qm->buf[2] = 0;
			qm->size = 3;
			qm->reltime = self->memCI[c][k];
			self->memI[2] = (self->memI[2] + 1) % self->memI[0];
			if ((self->memI[2] + 1) % self->memI[0] == self->memI[1]) {
				self->memCI[c][k] += ceil(grid * samples_per_beat);
				break;
			}

			qm = &(self->memQ[self->memI[2]]);
			qm->buf[0] = MIDI_NOTEON | c;
			qm->buf[1] = k;
			qm->buf[2] = self->memCM[c][k];
			qm->size = 3;
			qm->reltime = self->memCI[c][k];
			self->memI[2] = (self->memI[2] + 1) % self->memI[0];
			if ((self->memI[2] + 1) % self->memI[0] == self->memI[1]) {
				self->memCI[c][k] += ceil(grid * samples_per_beat);
				break;
			}

			self->memCI[c][k] += ceil(grid * samples_per_beat);

			if (self->memCI[c][k] >= n_samples) {
				break;
			}
		}

		self->memCI[c][k] -= n_samples;
	}

	/* dequeue delayline */
	for (i=0; i < max_delay; ++i) {
		const int off = (i + roff) % max_delay;
		if (self->memQ[off].size > 0) {
			if (self->memQ[off].reltime < n_samples) {

				if (self->memQ[off].size == 3 && (self->memQ[off].buf[0] & 0xf0) == MIDI_NOTEON) {
					const uint8_t chn = self->memQ[off].buf[0] & 0x0f;
					const uint8_t key = self->memQ[off].buf[1] & 0x7f;
					self->memCS[chn][key]++;
					if (self->memCS[chn][key] > 1) { // send a note-off first
						uint8_t buf[3];
						buf[0] = MIDI_NOTEOFF | chn;
						buf[1] = key; buf[2] = 0;
						forge_midimessage(self, self->memQ[off].reltime, buf, 3);
					}
					forge_midimessage(self, self->memQ[off].reltime, self->memQ[off].buf, self->memQ[off].size);
				}
				else if (self->memQ[off].size == 3 && (self->memQ[off].buf[0] & 0xf0) == MIDI_NOTEOFF) {
					const uint8_t chn = self->memQ[off].buf[0] & 0x0f;
					const uint8_t key = self->memQ[off].buf[1] & 0x7f;
					if (self->memCS[chn][key] > 0) {
						self->memCS[chn][key]--;
						if (self->memCS[chn][key] == 0) {
							forge_midimessage(self, self->memQ[off].reltime, self->memQ[off].buf, self->memQ[off].size);
						}
					}
				} else {
					forge_midimessage(self, self->memQ[off].reltime, self->memQ[off].buf, self->memQ[off].size);
				}

				self->memQ[off].size = 0;
				if (!skipped) self->memI[1] = (self->memI[1] + 1) % max_delay;
			} else {
				self->memQ[off].reltime -= n_samples;
				skipped = 1;
			}
		} else if (!skipped) self->memI[1] = off;

		if (off == woff) break;
	}
}