linux/sound/synth/emux/emux_nrpn.c
<<
>>
Prefs
   1/*
   2 *  NRPN / SYSEX callbacks for Emu8k/Emu10k1
   3 *
   4 *  Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>
   5 *
   6 *   This program is free software; you can redistribute it and/or modify
   7 *   it under the terms of the GNU General Public License as published by
   8 *   the Free Software Foundation; either version 2 of the License, or
   9 *   (at your option) any later version.
  10 *
  11 *   This program is distributed in the hope that it will be useful,
  12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *   GNU General Public License for more details.
  15 *
  16 *   You should have received a copy of the GNU General Public License
  17 *   along with this program; if not, write to the Free Software
  18 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  19 *
  20 */
  21
  22#include "emux_voice.h"
  23#include <sound/asoundef.h>
  24
  25/*
  26 * conversion from NRPN/control parameters to Emu8000 raw parameters
  27 */
  28
  29/* NRPN / CC -> Emu8000 parameter converter */
  30struct nrpn_conv_table {
  31        int control;
  32        int effect;
  33        int (*convert)(int val);
  34};
  35
  36/* effect sensitivity */
  37
  38#define FX_CUTOFF       0
  39#define FX_RESONANCE    1
  40#define FX_ATTACK       2
  41#define FX_RELEASE      3
  42#define FX_VIBRATE      4
  43#define FX_VIBDEPTH     5
  44#define FX_VIBDELAY     6
  45#define FX_NUMS         7
  46
  47/*
  48 * convert NRPN/control values
  49 */
  50
  51static int send_converted_effect(struct nrpn_conv_table *table, int num_tables,
  52                                 struct snd_emux_port *port,
  53                                 struct snd_midi_channel *chan,
  54                                 int type, int val, int mode)
  55{
  56        int i, cval;
  57        for (i = 0; i < num_tables; i++) {
  58                if (table[i].control == type) {
  59                        cval = table[i].convert(val);
  60                        snd_emux_send_effect(port, chan, table[i].effect,
  61                                             cval, mode);
  62                        return 1;
  63                }
  64        }
  65        return 0;
  66}
  67
  68#define DEF_FX_CUTOFF           170
  69#define DEF_FX_RESONANCE        6
  70#define DEF_FX_ATTACK           50
  71#define DEF_FX_RELEASE          50
  72#define DEF_FX_VIBRATE          30
  73#define DEF_FX_VIBDEPTH         4
  74#define DEF_FX_VIBDELAY         1500
  75
  76/* effect sensitivities for GS NRPN:
  77 *  adjusted for chaos 8MB soundfonts
  78 */
  79static int gs_sense[] = 
  80{
  81        DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
  82        DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
  83};
  84
  85/* effect sensitivies for XG controls:
  86 * adjusted for chaos 8MB soundfonts
  87 */
  88static int xg_sense[] = 
  89{
  90        DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
  91        DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
  92};
  93
  94
  95/*
  96 * AWE32 NRPN effects
  97 */
  98
  99static int fx_delay(int val);
 100static int fx_attack(int val);
 101static int fx_hold(int val);
 102static int fx_decay(int val);
 103static int fx_the_value(int val);
 104static int fx_twice_value(int val);
 105static int fx_conv_pitch(int val);
 106static int fx_conv_Q(int val);
 107
 108/* function for each NRPN */            /* [range]  units */
 109#define fx_env1_delay   fx_delay        /* [0,5900] 4msec */
 110#define fx_env1_attack  fx_attack       /* [0,5940] 1msec */
 111#define fx_env1_hold    fx_hold         /* [0,8191] 1msec */
 112#define fx_env1_decay   fx_decay        /* [0,5940] 4msec */
 113#define fx_env1_release fx_decay        /* [0,5940] 4msec */
 114#define fx_env1_sustain fx_the_value    /* [0,127] 0.75dB */
 115#define fx_env1_pitch   fx_the_value    /* [-127,127] 9.375cents */
 116#define fx_env1_cutoff  fx_the_value    /* [-127,127] 56.25cents */
 117
 118#define fx_env2_delay   fx_delay        /* [0,5900] 4msec */
 119#define fx_env2_attack  fx_attack       /* [0,5940] 1msec */
 120#define fx_env2_hold    fx_hold         /* [0,8191] 1msec */
 121#define fx_env2_decay   fx_decay        /* [0,5940] 4msec */
 122#define fx_env2_release fx_decay        /* [0,5940] 4msec */
 123#define fx_env2_sustain fx_the_value    /* [0,127] 0.75dB */
 124
 125#define fx_lfo1_delay   fx_delay        /* [0,5900] 4msec */
 126#define fx_lfo1_freq    fx_twice_value  /* [0,127] 84mHz */
 127#define fx_lfo1_volume  fx_twice_value  /* [0,127] 0.1875dB */
 128#define fx_lfo1_pitch   fx_the_value    /* [-127,127] 9.375cents */
 129#define fx_lfo1_cutoff  fx_twice_value  /* [-64,63] 56.25cents */
 130
 131#define fx_lfo2_delay   fx_delay        /* [0,5900] 4msec */
 132#define fx_lfo2_freq    fx_twice_value  /* [0,127] 84mHz */
 133#define fx_lfo2_pitch   fx_the_value    /* [-127,127] 9.375cents */
 134
 135#define fx_init_pitch   fx_conv_pitch   /* [-8192,8192] cents */
 136#define fx_chorus       fx_the_value    /* [0,255] -- */
 137#define fx_reverb       fx_the_value    /* [0,255] -- */
 138#define fx_cutoff       fx_twice_value  /* [0,127] 62Hz */
 139#define fx_filterQ      fx_conv_Q       /* [0,127] -- */
 140
 141static int fx_delay(int val)
 142{
 143        return (unsigned short)snd_sf_calc_parm_delay(val);
 144}
 145
 146static int fx_attack(int val)
 147{
 148        return (unsigned short)snd_sf_calc_parm_attack(val);
 149}
 150
 151static int fx_hold(int val)
 152{
 153        return (unsigned short)snd_sf_calc_parm_hold(val);
 154}
 155
 156static int fx_decay(int val)
 157{
 158        return (unsigned short)snd_sf_calc_parm_decay(val);
 159}
 160
 161static int fx_the_value(int val)
 162{
 163        return (unsigned short)(val & 0xff);
 164}
 165
 166static int fx_twice_value(int val)
 167{
 168        return (unsigned short)((val * 2) & 0xff);
 169}
 170
 171static int fx_conv_pitch(int val)
 172{
 173        return (short)(val * 4096 / 1200);
 174}
 175
 176static int fx_conv_Q(int val)
 177{
 178        return (unsigned short)((val / 8) & 0xff);
 179}
 180
 181
 182static struct nrpn_conv_table awe_effects[] =
 183{
 184        { 0, EMUX_FX_LFO1_DELAY,        fx_lfo1_delay},
 185        { 1, EMUX_FX_LFO1_FREQ, fx_lfo1_freq},
 186        { 2, EMUX_FX_LFO2_DELAY,        fx_lfo2_delay},
 187        { 3, EMUX_FX_LFO2_FREQ, fx_lfo2_freq},
 188
 189        { 4, EMUX_FX_ENV1_DELAY,        fx_env1_delay},
 190        { 5, EMUX_FX_ENV1_ATTACK,fx_env1_attack},
 191        { 6, EMUX_FX_ENV1_HOLD, fx_env1_hold},
 192        { 7, EMUX_FX_ENV1_DECAY,        fx_env1_decay},
 193        { 8, EMUX_FX_ENV1_SUSTAIN,      fx_env1_sustain},
 194        { 9, EMUX_FX_ENV1_RELEASE,      fx_env1_release},
 195
 196        {10, EMUX_FX_ENV2_DELAY,        fx_env2_delay},
 197        {11, EMUX_FX_ENV2_ATTACK,       fx_env2_attack},
 198        {12, EMUX_FX_ENV2_HOLD, fx_env2_hold},
 199        {13, EMUX_FX_ENV2_DECAY,        fx_env2_decay},
 200        {14, EMUX_FX_ENV2_SUSTAIN,      fx_env2_sustain},
 201        {15, EMUX_FX_ENV2_RELEASE,      fx_env2_release},
 202
 203        {16, EMUX_FX_INIT_PITCH,        fx_init_pitch},
 204        {17, EMUX_FX_LFO1_PITCH,        fx_lfo1_pitch},
 205        {18, EMUX_FX_LFO2_PITCH,        fx_lfo2_pitch},
 206        {19, EMUX_FX_ENV1_PITCH,        fx_env1_pitch},
 207        {20, EMUX_FX_LFO1_VOLUME,       fx_lfo1_volume},
 208        {21, EMUX_FX_CUTOFF,            fx_cutoff},
 209        {22, EMUX_FX_FILTERQ,   fx_filterQ},
 210        {23, EMUX_FX_LFO1_CUTOFF,       fx_lfo1_cutoff},
 211        {24, EMUX_FX_ENV1_CUTOFF,       fx_env1_cutoff},
 212        {25, EMUX_FX_CHORUS,            fx_chorus},
 213        {26, EMUX_FX_REVERB,            fx_reverb},
 214};
 215
 216
 217/*
 218 * GS(SC88) NRPN effects; still experimental
 219 */
 220
 221/* cutoff: quarter semitone step, max=255 */
 222static int gs_cutoff(int val)
 223{
 224        return (val - 64) * gs_sense[FX_CUTOFF] / 50;
 225}
 226
 227/* resonance: 0 to 15(max) */
 228static int gs_filterQ(int val)
 229{
 230        return (val - 64) * gs_sense[FX_RESONANCE] / 50;
 231}
 232
 233/* attack: */
 234static int gs_attack(int val)
 235{
 236        return -(val - 64) * gs_sense[FX_ATTACK] / 50;
 237}
 238
 239/* decay: */
 240static int gs_decay(int val)
 241{
 242        return -(val - 64) * gs_sense[FX_RELEASE] / 50;
 243}
 244
 245/* release: */
 246static int gs_release(int val)
 247{
 248        return -(val - 64) * gs_sense[FX_RELEASE] / 50;
 249}
 250
 251/* vibrato freq: 0.042Hz step, max=255 */
 252static int gs_vib_rate(int val)
 253{
 254        return (val - 64) * gs_sense[FX_VIBRATE] / 50;
 255}
 256
 257/* vibrato depth: max=127, 1 octave */
 258static int gs_vib_depth(int val)
 259{
 260        return (val - 64) * gs_sense[FX_VIBDEPTH] / 50;
 261}
 262
 263/* vibrato delay: -0.725msec step */
 264static int gs_vib_delay(int val)
 265{
 266        return -(val - 64) * gs_sense[FX_VIBDELAY] / 50;
 267}
 268
 269static struct nrpn_conv_table gs_effects[] =
 270{
 271        {32, EMUX_FX_CUTOFF,    gs_cutoff},
 272        {33, EMUX_FX_FILTERQ,   gs_filterQ},
 273        {99, EMUX_FX_ENV2_ATTACK, gs_attack},
 274        {100, EMUX_FX_ENV2_DECAY, gs_decay},
 275        {102, EMUX_FX_ENV2_RELEASE, gs_release},
 276        {8, EMUX_FX_LFO1_FREQ, gs_vib_rate},
 277        {9, EMUX_FX_LFO1_VOLUME, gs_vib_depth},
 278        {10, EMUX_FX_LFO1_DELAY, gs_vib_delay},
 279};
 280
 281
 282/*
 283 * NRPN events
 284 */
 285void
 286snd_emux_nrpn(void *p, struct snd_midi_channel *chan,
 287              struct snd_midi_channel_set *chset)
 288{
 289        struct snd_emux_port *port;
 290
 291        port = p;
 292        if (snd_BUG_ON(!port || !chan))
 293                return;
 294
 295        if (chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB] == 127 &&
 296            chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB] <= 26) {
 297                int val;
 298                /* Win/DOS AWE32 specific NRPNs */
 299                /* both MSB/LSB necessary */
 300                val = (chan->control[MIDI_CTL_MSB_DATA_ENTRY] << 7) |
 301                        chan->control[MIDI_CTL_LSB_DATA_ENTRY]; 
 302                val -= 8192;
 303                send_converted_effect
 304                        (awe_effects, ARRAY_SIZE(awe_effects),
 305                         port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB],
 306                         val, EMUX_FX_FLAG_SET);
 307                return;
 308        }
 309
 310        if (port->chset.midi_mode == SNDRV_MIDI_MODE_GS &&
 311            chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB] == 1) {
 312                int val;
 313                /* GS specific NRPNs */
 314                /* only MSB is valid */
 315                val = chan->control[MIDI_CTL_MSB_DATA_ENTRY];
 316                send_converted_effect
 317                        (gs_effects, ARRAY_SIZE(gs_effects),
 318                         port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB],
 319                         val, EMUX_FX_FLAG_ADD);
 320                return;
 321        }
 322}
 323
 324
 325/*
 326 * XG control effects; still experimental
 327 */
 328
 329/* cutoff: quarter semitone step, max=255 */
 330static int xg_cutoff(int val)
 331{
 332        return (val - 64) * xg_sense[FX_CUTOFF] / 64;
 333}
 334
 335/* resonance: 0(open) to 15(most nasal) */
 336static int xg_filterQ(int val)
 337{
 338        return (val - 64) * xg_sense[FX_RESONANCE] / 64;
 339}
 340
 341/* attack: */
 342static int xg_attack(int val)
 343{
 344        return -(val - 64) * xg_sense[FX_ATTACK] / 64;
 345}
 346
 347/* release: */
 348static int xg_release(int val)
 349{
 350        return -(val - 64) * xg_sense[FX_RELEASE] / 64;
 351}
 352
 353static struct nrpn_conv_table xg_effects[] =
 354{
 355        {71, EMUX_FX_CUTOFF,    xg_cutoff},
 356        {74, EMUX_FX_FILTERQ,   xg_filterQ},
 357        {72, EMUX_FX_ENV2_RELEASE, xg_release},
 358        {73, EMUX_FX_ENV2_ATTACK, xg_attack},
 359};
 360
 361int
 362snd_emux_xg_control(struct snd_emux_port *port, struct snd_midi_channel *chan,
 363                    int param)
 364{
 365        return send_converted_effect(xg_effects, ARRAY_SIZE(xg_effects),
 366                                     port, chan, param,
 367                                     chan->control[param],
 368                                     EMUX_FX_FLAG_ADD);
 369}
 370
 371/*
 372 * receive sysex
 373 */
 374void
 375snd_emux_sysex(void *p, unsigned char *buf, int len, int parsed,
 376               struct snd_midi_channel_set *chset)
 377{
 378        struct snd_emux_port *port;
 379        struct snd_emux *emu;
 380
 381        port = p;
 382        if (snd_BUG_ON(!port || !chset))
 383                return;
 384        emu = port->emu;
 385
 386        switch (parsed) {
 387        case SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME:
 388                snd_emux_update_port(port, SNDRV_EMUX_UPDATE_VOLUME);
 389                break;
 390        default:
 391                if (emu->ops.sysex)
 392                        emu->ops.sysex(emu, buf, len, parsed, chset);
 393                break;
 394        }
 395}
 396
 397