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