brintos

brintos / linux-shallow public Read only

0
0
Text · 9.1 KiB · 0d6b82a Raw
387 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  NRPN / SYSEX callbacks for Emu8k/Emu10k14 *5 *  Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>6 */7 8#include "emux_voice.h"9#include <sound/asoundef.h>10 11/*12 * conversion from NRPN/control parameters to Emu8000 raw parameters13 */14 15/* NRPN / CC -> Emu8000 parameter converter */16struct nrpn_conv_table {17	int control;18	int effect;19	int (*convert)(int val);20};21 22/* effect sensitivity */23 24#define FX_CUTOFF	025#define FX_RESONANCE	126#define FX_ATTACK	227#define FX_RELEASE	328#define FX_VIBRATE	429#define FX_VIBDEPTH	530#define FX_VIBDELAY	631#define FX_NUMS		732 33/*34 * convert NRPN/control values35 */36 37static int send_converted_effect(const struct nrpn_conv_table *table,38				 int num_tables,39				 struct snd_emux_port *port,40				 struct snd_midi_channel *chan,41				 int type, int val, int mode)42{43	int i, cval;44	for (i = 0; i < num_tables; i++) {45		if (table[i].control == type) {46			cval = table[i].convert(val);47			snd_emux_send_effect(port, chan, table[i].effect,48					     cval, mode);49			return 1;50		}51	}52	return 0;53}54 55#define DEF_FX_CUTOFF		17056#define DEF_FX_RESONANCE	657#define DEF_FX_ATTACK		5058#define DEF_FX_RELEASE		5059#define DEF_FX_VIBRATE		3060#define DEF_FX_VIBDEPTH		461#define DEF_FX_VIBDELAY		150062 63/* effect sensitivities for GS NRPN:64 *  adjusted for chaos 8MB soundfonts65 */66static const int gs_sense[] =67{68	DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,69	DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY70};71 72/* effect sensitivities for XG controls:73 * adjusted for chaos 8MB soundfonts74 */75static const int xg_sense[] =76{77	DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,78	DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY79};80 81 82/*83 * AWE32 NRPN effects84 */85 86static int fx_delay(int val);87static int fx_attack(int val);88static int fx_hold(int val);89static int fx_decay(int val);90static int fx_the_value(int val);91static int fx_twice_value(int val);92static int fx_conv_pitch(int val);93static int fx_conv_Q(int val);94 95/* function for each NRPN */		/* [range]  units */96#define fx_env1_delay	fx_delay	/* [0,5900] 4msec */97#define fx_env1_attack	fx_attack	/* [0,5940] 1msec */98#define fx_env1_hold	fx_hold		/* [0,8191] 1msec */99#define fx_env1_decay	fx_decay	/* [0,5940] 4msec */100#define fx_env1_release	fx_decay	/* [0,5940] 4msec */101#define fx_env1_sustain	fx_the_value	/* [0,127] 0.75dB */102#define fx_env1_pitch	fx_the_value	/* [-127,127] 9.375cents */103#define fx_env1_cutoff	fx_the_value	/* [-127,127] 56.25cents */104 105#define fx_env2_delay	fx_delay	/* [0,5900] 4msec */106#define fx_env2_attack	fx_attack	/* [0,5940] 1msec */107#define fx_env2_hold	fx_hold		/* [0,8191] 1msec */108#define fx_env2_decay	fx_decay	/* [0,5940] 4msec */109#define fx_env2_release	fx_decay	/* [0,5940] 4msec */110#define fx_env2_sustain	fx_the_value	/* [0,127] 0.75dB */111 112#define fx_lfo1_delay	fx_delay	/* [0,5900] 4msec */113#define fx_lfo1_freq	fx_twice_value	/* [0,127] 84mHz */114#define fx_lfo1_volume	fx_twice_value	/* [0,127] 0.1875dB */115#define fx_lfo1_pitch	fx_the_value	/* [-127,127] 9.375cents */116#define fx_lfo1_cutoff	fx_twice_value	/* [-64,63] 56.25cents */117 118#define fx_lfo2_delay	fx_delay	/* [0,5900] 4msec */119#define fx_lfo2_freq	fx_twice_value	/* [0,127] 84mHz */120#define fx_lfo2_pitch	fx_the_value	/* [-127,127] 9.375cents */121 122#define fx_init_pitch	fx_conv_pitch	/* [-8192,8192] cents */123#define fx_chorus	fx_the_value	/* [0,255] -- */124#define fx_reverb	fx_the_value	/* [0,255] -- */125#define fx_cutoff	fx_twice_value	/* [0,127] 62Hz */126#define fx_filterQ	fx_conv_Q	/* [0,127] -- */127 128static int fx_delay(int val)129{130	return (unsigned short)snd_sf_calc_parm_delay(val);131}132 133static int fx_attack(int val)134{135	return (unsigned short)snd_sf_calc_parm_attack(val);136}137 138static int fx_hold(int val)139{140	return (unsigned short)snd_sf_calc_parm_hold(val);141}142 143static int fx_decay(int val)144{145	return (unsigned short)snd_sf_calc_parm_decay(val);146}147 148static int fx_the_value(int val)149{150	return (unsigned short)(val & 0xff);151}152 153static int fx_twice_value(int val)154{155	return (unsigned short)((val * 2) & 0xff);156}157 158static int fx_conv_pitch(int val)159{160	return (short)(val * 4096 / 1200);161}162 163static int fx_conv_Q(int val)164{165	return (unsigned short)((val / 8) & 0xff);166}167 168 169static const struct nrpn_conv_table awe_effects[] =170{171	{ 0, EMUX_FX_LFO1_DELAY,	fx_lfo1_delay},172	{ 1, EMUX_FX_LFO1_FREQ,	fx_lfo1_freq},173	{ 2, EMUX_FX_LFO2_DELAY,	fx_lfo2_delay},174	{ 3, EMUX_FX_LFO2_FREQ,	fx_lfo2_freq},175 176	{ 4, EMUX_FX_ENV1_DELAY,	fx_env1_delay},177	{ 5, EMUX_FX_ENV1_ATTACK,fx_env1_attack},178	{ 6, EMUX_FX_ENV1_HOLD,	fx_env1_hold},179	{ 7, EMUX_FX_ENV1_DECAY,	fx_env1_decay},180	{ 8, EMUX_FX_ENV1_SUSTAIN,	fx_env1_sustain},181	{ 9, EMUX_FX_ENV1_RELEASE,	fx_env1_release},182 183	{10, EMUX_FX_ENV2_DELAY,	fx_env2_delay},184	{11, EMUX_FX_ENV2_ATTACK,	fx_env2_attack},185	{12, EMUX_FX_ENV2_HOLD,	fx_env2_hold},186	{13, EMUX_FX_ENV2_DECAY,	fx_env2_decay},187	{14, EMUX_FX_ENV2_SUSTAIN,	fx_env2_sustain},188	{15, EMUX_FX_ENV2_RELEASE,	fx_env2_release},189 190	{16, EMUX_FX_INIT_PITCH,	fx_init_pitch},191	{17, EMUX_FX_LFO1_PITCH,	fx_lfo1_pitch},192	{18, EMUX_FX_LFO2_PITCH,	fx_lfo2_pitch},193	{19, EMUX_FX_ENV1_PITCH,	fx_env1_pitch},194	{20, EMUX_FX_LFO1_VOLUME,	fx_lfo1_volume},195	{21, EMUX_FX_CUTOFF,		fx_cutoff},196	{22, EMUX_FX_FILTERQ,	fx_filterQ},197	{23, EMUX_FX_LFO1_CUTOFF,	fx_lfo1_cutoff},198	{24, EMUX_FX_ENV1_CUTOFF,	fx_env1_cutoff},199	{25, EMUX_FX_CHORUS,		fx_chorus},200	{26, EMUX_FX_REVERB,		fx_reverb},201};202 203 204/*205 * GS(SC88) NRPN effects; still experimental206 */207 208/* cutoff: quarter semitone step, max=255 */209static int gs_cutoff(int val)210{211	return (val - 64) * gs_sense[FX_CUTOFF] / 50;212}213 214/* resonance: 0 to 15(max) */215static int gs_filterQ(int val)216{217	return (val - 64) * gs_sense[FX_RESONANCE] / 50;218}219 220/* attack: */221static int gs_attack(int val)222{223	return -(val - 64) * gs_sense[FX_ATTACK] / 50;224}225 226/* decay: */227static int gs_decay(int val)228{229	return -(val - 64) * gs_sense[FX_RELEASE] / 50;230}231 232/* release: */233static int gs_release(int val)234{235	return -(val - 64) * gs_sense[FX_RELEASE] / 50;236}237 238/* vibrato freq: 0.042Hz step, max=255 */239static int gs_vib_rate(int val)240{241	return (val - 64) * gs_sense[FX_VIBRATE] / 50;242}243 244/* vibrato depth: max=127, 1 octave */245static int gs_vib_depth(int val)246{247	return (val - 64) * gs_sense[FX_VIBDEPTH] / 50;248}249 250/* vibrato delay: -0.725msec step */251static int gs_vib_delay(int val)252{253	return -(val - 64) * gs_sense[FX_VIBDELAY] / 50;254}255 256static const struct nrpn_conv_table gs_effects[] =257{258	{32, EMUX_FX_CUTOFF,	gs_cutoff},259	{33, EMUX_FX_FILTERQ,	gs_filterQ},260	{99, EMUX_FX_ENV2_ATTACK, gs_attack},261	{100, EMUX_FX_ENV2_DECAY, gs_decay},262	{102, EMUX_FX_ENV2_RELEASE, gs_release},263	{8, EMUX_FX_LFO1_FREQ, gs_vib_rate},264	{9, EMUX_FX_LFO1_VOLUME, gs_vib_depth},265	{10, EMUX_FX_LFO1_DELAY, gs_vib_delay},266};267 268 269/*270 * NRPN events271 */272void273snd_emux_nrpn(void *p, struct snd_midi_channel *chan,274	      struct snd_midi_channel_set *chset)275{276	struct snd_emux_port *port;277 278	port = p;279	if (snd_BUG_ON(!port || !chan))280		return;281 282	if (chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB] == 127 &&283	    chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB] <= 26) {284		int val;285		/* Win/DOS AWE32 specific NRPNs */286		/* both MSB/LSB necessary */287		val = (chan->control[MIDI_CTL_MSB_DATA_ENTRY] << 7) |288			chan->control[MIDI_CTL_LSB_DATA_ENTRY]; 289		val -= 8192;290		send_converted_effect291			(awe_effects, ARRAY_SIZE(awe_effects),292			 port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB],293			 val, EMUX_FX_FLAG_SET);294		return;295	}296 297	if (port->chset.midi_mode == SNDRV_MIDI_MODE_GS &&298	    chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB] == 1) {299		int val;300		/* GS specific NRPNs */301		/* only MSB is valid */302		val = chan->control[MIDI_CTL_MSB_DATA_ENTRY];303		send_converted_effect304			(gs_effects, ARRAY_SIZE(gs_effects),305			 port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB],306			 val, EMUX_FX_FLAG_ADD);307		return;308	}309}310 311 312/*313 * XG control effects; still experimental314 */315 316/* cutoff: quarter semitone step, max=255 */317static int xg_cutoff(int val)318{319	return (val - 64) * xg_sense[FX_CUTOFF] / 64;320}321 322/* resonance: 0(open) to 15(most nasal) */323static int xg_filterQ(int val)324{325	return (val - 64) * xg_sense[FX_RESONANCE] / 64;326}327 328/* attack: */329static int xg_attack(int val)330{331	return -(val - 64) * xg_sense[FX_ATTACK] / 64;332}333 334/* release: */335static int xg_release(int val)336{337	return -(val - 64) * xg_sense[FX_RELEASE] / 64;338}339 340static const struct nrpn_conv_table xg_effects[] =341{342	{71, EMUX_FX_CUTOFF,	xg_cutoff},343	{74, EMUX_FX_FILTERQ,	xg_filterQ},344	{72, EMUX_FX_ENV2_RELEASE, xg_release},345	{73, EMUX_FX_ENV2_ATTACK, xg_attack},346};347 348int349snd_emux_xg_control(struct snd_emux_port *port, struct snd_midi_channel *chan,350		    int param)351{352	if (param >= ARRAY_SIZE(chan->control))353		return -EINVAL;354 355	return send_converted_effect(xg_effects, ARRAY_SIZE(xg_effects),356				     port, chan, param,357				     chan->control[param],358				     EMUX_FX_FLAG_ADD);359}360 361/*362 * receive sysex363 */364void365snd_emux_sysex(void *p, unsigned char *buf, int len, int parsed,366	       struct snd_midi_channel_set *chset)367{368	struct snd_emux_port *port;369	struct snd_emux *emu;370 371	port = p;372	if (snd_BUG_ON(!port || !chset))373		return;374	emu = port->emu;375 376	switch (parsed) {377	case SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME:378		snd_emux_update_port(port, SNDRV_EMUX_UPDATE_VOLUME);379		break;380	default:381		if (emu->ops.sysex)382			emu->ops.sysex(emu, buf, len, parsed, chset);383		break;384	}385}386 387