1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Midi synth routines for the Emu8k/Emu10k1 4 * 5 * Copyright (C) 1999 Steve Ratcliffe 6 * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de> 7 * 8 * Contains code based on awe_wave.c by Takashi Iwai 9 */ 10 11 #include "emux_voice.h" 12 #include <linux/slab.h> 13 14 #ifdef SNDRV_EMUX_USE_RAW_EFFECT 15 /* 16 * effects table 17 */ 18 19 #define xoffsetof(type,tag) ((long)(&((type)NULL)->tag) - (long)(NULL)) 20 21 #define parm_offset(tag) xoffsetof(struct soundfont_voice_parm *, tag) 22 23 #define PARM_IS_BYTE (1 << 0) 24 #define PARM_IS_WORD (1 << 1) 25 #define PARM_IS_ALIGNED (3 << 2) 26 #define PARM_IS_ALIGN_HI (1 << 2) 27 #define PARM_IS_ALIGN_LO (2 << 2) 28 #define PARM_IS_SIGNED (1 << 4) 29 30 #define PARM_WORD (PARM_IS_WORD) 31 #define PARM_BYTE_LO (PARM_IS_BYTE|PARM_IS_ALIGN_LO) 32 #define PARM_BYTE_HI (PARM_IS_BYTE|PARM_IS_ALIGN_HI) 33 #define PARM_BYTE (PARM_IS_BYTE) 34 #define PARM_SIGN_LO (PARM_IS_BYTE|PARM_IS_ALIGN_LO|PARM_IS_SIGNED) 35 #define PARM_SIGN_HI (PARM_IS_BYTE|PARM_IS_ALIGN_HI|PARM_IS_SIGNED) 36 37 static struct emux_parm_defs { 38 int type; /* byte or word */ 39 int low, high; /* value range */ 40 long offset; /* offset in parameter record (-1 = not written) */ 41 int update; /* flgas for real-time update */ 42 } parm_defs[EMUX_NUM_EFFECTS] = { 43 {PARM_WORD, 0, 0x8000, parm_offset(moddelay), 0}, /* env1 delay */ 44 {PARM_BYTE_LO, 1, 0x80, parm_offset(modatkhld), 0}, /* env1 attack */ 45 {PARM_BYTE_HI, 0, 0x7e, parm_offset(modatkhld), 0}, /* env1 hold */ 46 {PARM_BYTE_LO, 1, 0x7f, parm_offset(moddcysus), 0}, /* env1 decay */ 47 {PARM_BYTE_LO, 1, 0x7f, parm_offset(modrelease), 0}, /* env1 release */ 48 {PARM_BYTE_HI, 0, 0x7f, parm_offset(moddcysus), 0}, /* env1 sustain */ 49 {PARM_BYTE_HI, 0, 0xff, parm_offset(pefe), 0}, /* env1 pitch */ 50 {PARM_BYTE_LO, 0, 0xff, parm_offset(pefe), 0}, /* env1 fc */ 51 52 {PARM_WORD, 0, 0x8000, parm_offset(voldelay), 0}, /* env2 delay */ 53 {PARM_BYTE_LO, 1, 0x80, parm_offset(volatkhld), 0}, /* env2 attack */ 54 {PARM_BYTE_HI, 0, 0x7e, parm_offset(volatkhld), 0}, /* env2 hold */ 55 {PARM_BYTE_LO, 1, 0x7f, parm_offset(voldcysus), 0}, /* env2 decay */ 56 {PARM_BYTE_LO, 1, 0x7f, parm_offset(volrelease), 0}, /* env2 release */ 57 {PARM_BYTE_HI, 0, 0x7f, parm_offset(voldcysus), 0}, /* env2 sustain */ 58 59 {PARM_WORD, 0, 0x8000, parm_offset(lfo1delay), 0}, /* lfo1 delay */ 60 {PARM_BYTE_LO, 0, 0xff, parm_offset(tremfrq), SNDRV_EMUX_UPDATE_TREMFREQ}, /* lfo1 freq */ 61 {PARM_SIGN_HI, -128, 127, parm_offset(tremfrq), SNDRV_EMUX_UPDATE_TREMFREQ}, /* lfo1 vol */ 62 {PARM_SIGN_HI, -128, 127, parm_offset(fmmod), SNDRV_EMUX_UPDATE_FMMOD}, /* lfo1 pitch */ 63 {PARM_BYTE_LO, 0, 0xff, parm_offset(fmmod), SNDRV_EMUX_UPDATE_FMMOD}, /* lfo1 cutoff */ 64 65 {PARM_WORD, 0, 0x8000, parm_offset(lfo2delay), 0}, /* lfo2 delay */ 66 {PARM_BYTE_LO, 0, 0xff, parm_offset(fm2frq2), SNDRV_EMUX_UPDATE_FM2FRQ2}, /* lfo2 freq */ 67 {PARM_SIGN_HI, -128, 127, parm_offset(fm2frq2), SNDRV_EMUX_UPDATE_FM2FRQ2}, /* lfo2 pitch */ 68 69 {PARM_WORD, 0, 0xffff, -1, SNDRV_EMUX_UPDATE_PITCH}, /* initial pitch */ 70 {PARM_BYTE, 0, 0xff, parm_offset(chorus), 0}, /* chorus */ 71 {PARM_BYTE, 0, 0xff, parm_offset(reverb), 0}, /* reverb */ 72 {PARM_BYTE, 0, 0xff, parm_offset(cutoff), SNDRV_EMUX_UPDATE_VOLUME}, /* cutoff */ 73 {PARM_BYTE, 0, 15, parm_offset(filterQ), SNDRV_EMUX_UPDATE_Q}, /* resonance */ 74 75 {PARM_WORD, 0, 0xffff, -1, 0}, /* sample start */ 76 {PARM_WORD, 0, 0xffff, -1, 0}, /* loop start */ 77 {PARM_WORD, 0, 0xffff, -1, 0}, /* loop end */ 78 {PARM_WORD, 0, 0xffff, -1, 0}, /* coarse sample start */ 79 {PARM_WORD, 0, 0xffff, -1, 0}, /* coarse loop start */ 80 {PARM_WORD, 0, 0xffff, -1, 0}, /* coarse loop end */ 81 {PARM_BYTE, 0, 0xff, -1, SNDRV_EMUX_UPDATE_VOLUME}, /* initial attenuation */ 82 }; 83 84 /* set byte effect value */ 85 static void 86 effect_set_byte(unsigned char *valp, struct snd_midi_channel *chan, int type) 87 { 88 short effect; 89 struct snd_emux_effect_table *fx = chan->private; 90 91 effect = fx->val[type]; 92 if (fx->flag[type] == EMUX_FX_FLAG_ADD) { 93 if (parm_defs[type].type & PARM_IS_SIGNED) 94 effect += *(char*)valp; 95 else 96 effect += *valp; 97 } 98 if (effect < parm_defs[type].low) 99 effect = parm_defs[type].low; 100 else if (effect > parm_defs[type].high) 101 effect = parm_defs[type].high; 102 *valp = (unsigned char)effect; 103 } 104 105 /* set word effect value */ 106 static void 107 effect_set_word(unsigned short *valp, struct snd_midi_channel *chan, int type) 108 { 109 int effect; 110 struct snd_emux_effect_table *fx = chan->private; 111 112 effect = *(unsigned short*)&fx->val[type]; 113 if (fx->flag[type] == EMUX_FX_FLAG_ADD) 114 effect += *valp; 115 if (effect < parm_defs[type].low) 116 effect = parm_defs[type].low; 117 else if (effect > parm_defs[type].high) 118 effect = parm_defs[type].high; 119 *valp = (unsigned short)effect; 120 } 121 122 /* address offset */ 123 static int 124 effect_get_offset(struct snd_midi_channel *chan, int lo, int hi, int mode) 125 { 126 int addr = 0; 127 struct snd_emux_effect_table *fx = chan->private; 128 129 if (fx->flag[hi]) 130 addr = (short)fx->val[hi]; 131 addr = addr << 15; 132 if (fx->flag[lo]) 133 addr += (short)fx->val[lo]; 134 if (!(mode & SNDRV_SFNT_SAMPLE_8BITS)) 135 addr /= 2; 136 return addr; 137 } 138 139 #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) 140 /* change effects - for OSS sequencer compatibility */ 141 void 142 snd_emux_send_effect_oss(struct snd_emux_port *port, 143 struct snd_midi_channel *chan, int type, int val) 144 { 145 int mode; 146 147 if (type & 0x40) 148 mode = EMUX_FX_FLAG_OFF; 149 else if (type & 0x80) 150 mode = EMUX_FX_FLAG_ADD; 151 else 152 mode = EMUX_FX_FLAG_SET; 153 type &= 0x3f; 154 155 snd_emux_send_effect(port, chan, type, val, mode); 156 } 157 #endif 158 159 /* Modify the effect value. 160 * if update is necessary, call emu8000_control 161 */ 162 void 163 snd_emux_send_effect(struct snd_emux_port *port, struct snd_midi_channel *chan, 164 int type, int val, int mode) 165 { 166 int i; 167 int offset; 168 unsigned char *srcp, *origp; 169 struct snd_emux *emu; 170 struct snd_emux_effect_table *fx; 171 unsigned long flags; 172 173 emu = port->emu; 174 fx = chan->private; 175 if (emu == NULL || fx == NULL) 176 return; 177 if (type < 0 || type >= EMUX_NUM_EFFECTS) 178 return; 179 180 fx->val[type] = val; 181 fx->flag[type] = mode; 182 183 /* do we need to modify the register in realtime ? */ 184 if (! parm_defs[type].update || (offset = parm_defs[type].offset) < 0) 185 return; 186 187 #ifdef SNDRV_LITTLE_ENDIAN 188 if (parm_defs[type].type & PARM_IS_ALIGN_HI) 189 offset++; 190 #else 191 if (parm_defs[type].type & PARM_IS_ALIGN_LO) 192 offset++; 193 #endif 194 /* modify the register values */ 195 spin_lock_irqsave(&emu->voice_lock, flags); 196 for (i = 0; i < emu->max_voices; i++) { 197 struct snd_emux_voice *vp = &emu->voices[i]; 198 if (!STATE_IS_PLAYING(vp->state) || vp->chan != chan) 199 continue; 200 srcp = (unsigned char*)&vp->reg.parm + offset; 201 origp = (unsigned char*)&vp->zone->v.parm + offset; 202 if (parm_defs[i].type & PARM_IS_BYTE) { 203 *srcp = *origp; 204 effect_set_byte(srcp, chan, type); 205 } else { 206 *(unsigned short*)srcp = *(unsigned short*)origp; 207 effect_set_word((unsigned short*)srcp, chan, type); 208 } 209 } 210 spin_unlock_irqrestore(&emu->voice_lock, flags); 211 212 /* activate them */ 213 snd_emux_update_channel(port, chan, parm_defs[type].update); 214 } 215 216 217 /* copy wavetable registers to voice table */ 218 void 219 snd_emux_setup_effect(struct snd_emux_voice *vp) 220 { 221 struct snd_midi_channel *chan = vp->chan; 222 struct snd_emux_effect_table *fx; 223 unsigned char *srcp; 224 int i; 225 226 if (! (fx = chan->private)) 227 return; 228 229 /* modify the register values via effect table */ 230 for (i = 0; i < EMUX_FX_END; i++) { 231 int offset; 232 if (! fx->flag[i] || (offset = parm_defs[i].offset) < 0) 233 continue; 234 #ifdef SNDRV_LITTLE_ENDIAN 235 if (parm_defs[i].type & PARM_IS_ALIGN_HI) 236 offset++; 237 #else 238 if (parm_defs[i].type & PARM_IS_ALIGN_LO) 239 offset++; 240 #endif 241 srcp = (unsigned char*)&vp->reg.parm + offset; 242 if (parm_defs[i].type & PARM_IS_BYTE) 243 effect_set_byte(srcp, chan, i); 244 else 245 effect_set_word((unsigned short*)srcp, chan, i); 246 } 247 248 /* correct sample and loop points */ 249 vp->reg.start += effect_get_offset(chan, EMUX_FX_SAMPLE_START, 250 EMUX_FX_COARSE_SAMPLE_START, 251 vp->reg.sample_mode); 252 253 vp->reg.loopstart += effect_get_offset(chan, EMUX_FX_LOOP_START, 254 EMUX_FX_COARSE_LOOP_START, 255 vp->reg.sample_mode); 256 257 vp->reg.loopend += effect_get_offset(chan, EMUX_FX_LOOP_END, 258 EMUX_FX_COARSE_LOOP_END, 259 vp->reg.sample_mode); 260 } 261 262 /* 263 * effect table 264 */ 265 void 266 snd_emux_create_effect(struct snd_emux_port *p) 267 { 268 int i; 269 p->effect = kcalloc(p->chset.max_channels, 270 sizeof(struct snd_emux_effect_table), GFP_KERNEL); 271 if (p->effect) { 272 for (i = 0; i < p->chset.max_channels; i++) 273 p->chset.channels[i].private = p->effect + i; 274 } else { 275 for (i = 0; i < p->chset.max_channels; i++) 276 p->chset.channels[i].private = NULL; 277 } 278 } 279 280 void 281 snd_emux_delete_effect(struct snd_emux_port *p) 282 { 283 kfree(p->effect); 284 p->effect = NULL; 285 } 286 287 void 288 snd_emux_clear_effect(struct snd_emux_port *p) 289 { 290 if (p->effect) { 291 memset(p->effect, 0, sizeof(struct snd_emux_effect_table) * 292 p->chset.max_channels); 293 } 294 } 295 296 #endif /* SNDRV_EMUX_USE_RAW_EFFECT */ 297