root/sound/synth/emux/emux_effect.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. effect_set_byte
  2. effect_set_word
  3. effect_get_offset
  4. snd_emux_send_effect_oss
  5. snd_emux_send_effect
  6. snd_emux_setup_effect
  7. snd_emux_create_effect
  8. snd_emux_delete_effect
  9. snd_emux_clear_effect

   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 */

/* [<][>][^][v][top][bottom][index][help] */