970 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Midi synth routines for the Emu8k/Emu10k14 *5 * Copyright (C) 1999 Steve Ratcliffe6 * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>7 *8 * Contains code based on awe_wave.c by Takashi Iwai9 */10 11#include <linux/export.h>12#include "emux_voice.h"13#include <sound/asoundef.h>14 15/*16 * Prototypes17 */18 19/*20 * Ensure a value is between two points21 * macro evaluates its args more than once, so changed to upper-case.22 */23#define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0)24#define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0)25 26static int get_zone(struct snd_emux *emu, struct snd_emux_port *port,27 int *notep, int vel, struct snd_midi_channel *chan,28 struct snd_sf_zone **table);29static int get_bank(struct snd_emux_port *port, struct snd_midi_channel *chan);30static void terminate_note1(struct snd_emux *emu, int note,31 struct snd_midi_channel *chan, int free);32static void exclusive_note_off(struct snd_emux *emu, struct snd_emux_port *port,33 int exclass);34static void terminate_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int free);35static void update_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int update);36static void setup_voice(struct snd_emux_voice *vp);37static int calc_pan(struct snd_emux_voice *vp);38static int calc_volume(struct snd_emux_voice *vp);39static int calc_pitch(struct snd_emux_voice *vp);40 41 42/*43 * Start a note.44 */45void46snd_emux_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)47{48 struct snd_emux *emu;49 int i, key, nvoices;50 struct snd_emux_voice *vp;51 struct snd_sf_zone *table[SNDRV_EMUX_MAX_MULTI_VOICES];52 unsigned long flags;53 struct snd_emux_port *port;54 55 port = p;56 if (snd_BUG_ON(!port || !chan))57 return;58 59 emu = port->emu;60 if (snd_BUG_ON(!emu || !emu->ops.get_voice || !emu->ops.trigger))61 return;62 63 key = note; /* remember the original note */64 nvoices = get_zone(emu, port, ¬e, vel, chan, table);65 if (! nvoices)66 return;67 68 /* exclusive note off */69 for (i = 0; i < nvoices; i++) {70 struct snd_sf_zone *zp = table[i];71 if (zp && zp->v.exclusiveClass)72 exclusive_note_off(emu, port, zp->v.exclusiveClass);73 }74 75#if 0 // seems not necessary76 /* Turn off the same note on the same channel. */77 terminate_note1(emu, key, chan, 0);78#endif79 80 spin_lock_irqsave(&emu->voice_lock, flags);81 for (i = 0; i < nvoices; i++) {82 83 /* set up each voice parameter */84 /* at this stage, we don't trigger the voice yet. */85 86 if (table[i] == NULL)87 continue;88 89 vp = emu->ops.get_voice(emu, port);90 if (vp == NULL || vp->ch < 0)91 continue;92 if (STATE_IS_PLAYING(vp->state))93 emu->ops.terminate(vp);94 95 vp->time = emu->use_time++;96 vp->chan = chan;97 vp->port = port;98 vp->key = key;99 vp->note = note;100 vp->velocity = vel;101 vp->zone = table[i];102 if (vp->zone->sample)103 vp->block = vp->zone->sample->block;104 else105 vp->block = NULL;106 107 setup_voice(vp);108 109 vp->state = SNDRV_EMUX_ST_STANDBY;110 if (emu->ops.prepare) {111 vp->state = SNDRV_EMUX_ST_OFF;112 if (emu->ops.prepare(vp) >= 0)113 vp->state = SNDRV_EMUX_ST_STANDBY;114 }115 }116 117 /* start envelope now */118 for (i = 0; i < emu->max_voices; i++) {119 vp = &emu->voices[i];120 if (vp->state == SNDRV_EMUX_ST_STANDBY &&121 vp->chan == chan) {122 emu->ops.trigger(vp);123 vp->state = SNDRV_EMUX_ST_ON;124 vp->ontime = jiffies; /* remember the trigger timing */125 }126 }127 spin_unlock_irqrestore(&emu->voice_lock, flags);128 129#ifdef SNDRV_EMUX_USE_RAW_EFFECT130 if (port->port_mode == SNDRV_EMUX_PORT_MODE_OSS_SYNTH) {131 /* clear voice position for the next note on this channel */132 struct snd_emux_effect_table *fx = chan->private;133 if (fx) {134 fx->flag[EMUX_FX_SAMPLE_START] = 0;135 fx->flag[EMUX_FX_COARSE_SAMPLE_START] = 0;136 }137 }138#endif139}140 141/*142 * Release a note in response to a midi note off.143 */144void145snd_emux_note_off(void *p, int note, int vel, struct snd_midi_channel *chan)146{147 int ch;148 struct snd_emux *emu;149 struct snd_emux_voice *vp;150 unsigned long flags;151 struct snd_emux_port *port;152 153 port = p;154 if (snd_BUG_ON(!port || !chan))155 return;156 157 emu = port->emu;158 if (snd_BUG_ON(!emu || !emu->ops.release))159 return;160 161 spin_lock_irqsave(&emu->voice_lock, flags);162 for (ch = 0; ch < emu->max_voices; ch++) {163 vp = &emu->voices[ch];164 if (STATE_IS_PLAYING(vp->state) &&165 vp->chan == chan && vp->key == note) {166 vp->state = SNDRV_EMUX_ST_RELEASED;167 if (vp->ontime == jiffies) {168 /* if note-off is sent too shortly after169 * note-on, emuX engine cannot produce the sound170 * correctly. so we'll release this note171 * a bit later via timer callback.172 */173 vp->state = SNDRV_EMUX_ST_PENDING;174 if (! emu->timer_active) {175 mod_timer(&emu->tlist, jiffies + 1);176 emu->timer_active = 1;177 }178 } else179 /* ok now release the note */180 emu->ops.release(vp);181 }182 }183 spin_unlock_irqrestore(&emu->voice_lock, flags);184}185 186/*187 * timer callback188 *189 * release the pending note-offs190 */191void snd_emux_timer_callback(struct timer_list *t)192{193 struct snd_emux *emu = from_timer(emu, t, tlist);194 struct snd_emux_voice *vp;195 unsigned long flags;196 int ch, do_again = 0;197 198 spin_lock_irqsave(&emu->voice_lock, flags);199 for (ch = 0; ch < emu->max_voices; ch++) {200 vp = &emu->voices[ch];201 if (vp->state == SNDRV_EMUX_ST_PENDING) {202 if (vp->ontime == jiffies)203 do_again++; /* release this at the next interrupt */204 else {205 emu->ops.release(vp);206 vp->state = SNDRV_EMUX_ST_RELEASED;207 }208 }209 }210 if (do_again) {211 mod_timer(&emu->tlist, jiffies + 1);212 emu->timer_active = 1;213 } else214 emu->timer_active = 0;215 spin_unlock_irqrestore(&emu->voice_lock, flags);216}217 218/*219 * key pressure change220 */221void222snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan)223{224 int ch;225 struct snd_emux *emu;226 struct snd_emux_voice *vp;227 unsigned long flags;228 struct snd_emux_port *port;229 230 port = p;231 if (snd_BUG_ON(!port || !chan))232 return;233 234 emu = port->emu;235 if (snd_BUG_ON(!emu || !emu->ops.update))236 return;237 238 spin_lock_irqsave(&emu->voice_lock, flags);239 for (ch = 0; ch < emu->max_voices; ch++) {240 vp = &emu->voices[ch];241 if (vp->state == SNDRV_EMUX_ST_ON &&242 vp->chan == chan && vp->key == note) {243 vp->velocity = vel;244 update_voice(emu, vp, SNDRV_EMUX_UPDATE_VOLUME);245 }246 }247 spin_unlock_irqrestore(&emu->voice_lock, flags);248}249 250 251/*252 * Modulate the voices which belong to the channel253 */254void255snd_emux_update_channel(struct snd_emux_port *port, struct snd_midi_channel *chan, int update)256{257 struct snd_emux *emu;258 struct snd_emux_voice *vp;259 int i;260 unsigned long flags;261 262 if (! update)263 return;264 265 emu = port->emu;266 if (snd_BUG_ON(!emu || !emu->ops.update))267 return;268 269 spin_lock_irqsave(&emu->voice_lock, flags);270 for (i = 0; i < emu->max_voices; i++) {271 vp = &emu->voices[i];272 if (vp->chan == chan)273 update_voice(emu, vp, update);274 }275 spin_unlock_irqrestore(&emu->voice_lock, flags);276}277 278/*279 * Modulate all the voices which belong to the port.280 */281void282snd_emux_update_port(struct snd_emux_port *port, int update)283{284 struct snd_emux *emu; 285 struct snd_emux_voice *vp;286 int i;287 unsigned long flags;288 289 if (! update)290 return;291 292 emu = port->emu;293 if (snd_BUG_ON(!emu || !emu->ops.update))294 return;295 296 spin_lock_irqsave(&emu->voice_lock, flags);297 for (i = 0; i < emu->max_voices; i++) {298 vp = &emu->voices[i];299 if (vp->port == port)300 update_voice(emu, vp, update);301 }302 spin_unlock_irqrestore(&emu->voice_lock, flags);303}304 305 306/*307 * Deal with a controller type event. This includes all types of308 * control events, not just the midi controllers309 */310void311snd_emux_control(void *p, int type, struct snd_midi_channel *chan)312{313 struct snd_emux_port *port;314 315 port = p;316 if (snd_BUG_ON(!port || !chan))317 return;318 319 switch (type) {320 case MIDI_CTL_MSB_MAIN_VOLUME:321 case MIDI_CTL_MSB_EXPRESSION:322 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_VOLUME);323 break;324 325 case MIDI_CTL_MSB_PAN:326 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PAN);327 break;328 329 case MIDI_CTL_SOFT_PEDAL:330#ifdef SNDRV_EMUX_USE_RAW_EFFECT331 /* FIXME: this is an emulation */332 if (chan->control[type] >= 64)333 snd_emux_send_effect(port, chan, EMUX_FX_CUTOFF, -160,334 EMUX_FX_FLAG_ADD);335 else336 snd_emux_send_effect(port, chan, EMUX_FX_CUTOFF, 0,337 EMUX_FX_FLAG_OFF);338#endif339 break;340 341 case MIDI_CTL_PITCHBEND:342 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PITCH);343 break;344 345 case MIDI_CTL_MSB_MODWHEEL:346 case MIDI_CTL_CHAN_PRESSURE:347 snd_emux_update_channel(port, chan,348 SNDRV_EMUX_UPDATE_FMMOD |349 SNDRV_EMUX_UPDATE_FM2FRQ2);350 break;351 352 }353 354 if (port->chset.midi_mode == SNDRV_MIDI_MODE_XG) {355 snd_emux_xg_control(port, chan, type);356 }357}358 359 360/*361 * terminate note - if free flag is true, free the terminated voice362 */363static void364terminate_note1(struct snd_emux *emu, int note, struct snd_midi_channel *chan, int free)365{366 int i;367 struct snd_emux_voice *vp;368 unsigned long flags;369 370 spin_lock_irqsave(&emu->voice_lock, flags);371 for (i = 0; i < emu->max_voices; i++) {372 vp = &emu->voices[i];373 if (STATE_IS_PLAYING(vp->state) && vp->chan == chan &&374 vp->key == note)375 terminate_voice(emu, vp, free);376 }377 spin_unlock_irqrestore(&emu->voice_lock, flags);378}379 380 381/*382 * terminate note - exported for midi emulation383 */384void385snd_emux_terminate_note(void *p, int note, struct snd_midi_channel *chan)386{387 struct snd_emux *emu;388 struct snd_emux_port *port;389 390 port = p;391 if (snd_BUG_ON(!port || !chan))392 return;393 394 emu = port->emu;395 if (snd_BUG_ON(!emu || !emu->ops.terminate))396 return;397 398 terminate_note1(emu, note, chan, 1);399}400 401 402/*403 * Terminate all the notes404 */405void406snd_emux_terminate_all(struct snd_emux *emu)407{408 int i;409 struct snd_emux_voice *vp;410 unsigned long flags;411 412 spin_lock_irqsave(&emu->voice_lock, flags);413 for (i = 0; i < emu->max_voices; i++) {414 vp = &emu->voices[i];415 if (STATE_IS_PLAYING(vp->state))416 terminate_voice(emu, vp, 0);417 if (vp->state == SNDRV_EMUX_ST_OFF) {418 if (emu->ops.free_voice)419 emu->ops.free_voice(vp);420 if (emu->ops.reset)421 emu->ops.reset(emu, i);422 }423 vp->time = 0;424 }425 /* initialize allocation time */426 emu->use_time = 0;427 spin_unlock_irqrestore(&emu->voice_lock, flags);428}429 430EXPORT_SYMBOL(snd_emux_terminate_all);431 432/*433 * Terminate all voices associated with the given port434 */435void436snd_emux_sounds_off_all(struct snd_emux_port *port)437{438 int i;439 struct snd_emux *emu;440 struct snd_emux_voice *vp;441 unsigned long flags;442 443 if (snd_BUG_ON(!port))444 return;445 emu = port->emu;446 if (snd_BUG_ON(!emu || !emu->ops.terminate))447 return;448 449 spin_lock_irqsave(&emu->voice_lock, flags);450 for (i = 0; i < emu->max_voices; i++) {451 vp = &emu->voices[i];452 if (STATE_IS_PLAYING(vp->state) &&453 vp->port == port)454 terminate_voice(emu, vp, 0);455 if (vp->state == SNDRV_EMUX_ST_OFF) {456 if (emu->ops.free_voice)457 emu->ops.free_voice(vp);458 if (emu->ops.reset)459 emu->ops.reset(emu, i);460 }461 }462 spin_unlock_irqrestore(&emu->voice_lock, flags);463}464 465 466/*467 * Terminate all voices that have the same exclusive class. This468 * is mainly for drums.469 */470static void471exclusive_note_off(struct snd_emux *emu, struct snd_emux_port *port, int exclass)472{473 struct snd_emux_voice *vp;474 int i;475 unsigned long flags;476 477 spin_lock_irqsave(&emu->voice_lock, flags);478 for (i = 0; i < emu->max_voices; i++) {479 vp = &emu->voices[i];480 if (STATE_IS_PLAYING(vp->state) && vp->port == port &&481 vp->reg.exclusiveClass == exclass) {482 terminate_voice(emu, vp, 0);483 }484 }485 spin_unlock_irqrestore(&emu->voice_lock, flags);486}487 488/*489 * terminate a voice490 * if free flag is true, call free_voice after termination491 */492static void493terminate_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int free)494{495 emu->ops.terminate(vp);496 vp->time = emu->use_time++;497 vp->chan = NULL;498 vp->port = NULL;499 vp->zone = NULL;500 vp->block = NULL;501 vp->state = SNDRV_EMUX_ST_OFF;502 if (free && emu->ops.free_voice)503 emu->ops.free_voice(vp);504}505 506 507/*508 * Modulate the voice509 */510static void511update_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int update)512{513 if (!STATE_IS_PLAYING(vp->state))514 return;515 516 if (vp->chan == NULL || vp->port == NULL)517 return;518 if (update & SNDRV_EMUX_UPDATE_VOLUME)519 calc_volume(vp);520 if (update & SNDRV_EMUX_UPDATE_PITCH)521 calc_pitch(vp);522 if (update & SNDRV_EMUX_UPDATE_PAN) {523 if (! calc_pan(vp) && (update == SNDRV_EMUX_UPDATE_PAN))524 return;525 }526 emu->ops.update(vp, update);527}528 529 530#if 0 // not used531/* table for volume target calculation */532static const unsigned short voltarget[16] = {533 0xEAC0, 0xE0C8, 0xD740, 0xCE20, 0xC560, 0xBD08, 0xB500, 0xAD58,534 0xA5F8, 0x9EF0, 0x9830, 0x91C0, 0x8B90, 0x85A8, 0x8000, 0x7A90535};536#endif537 538#define LO_BYTE(v) ((v) & 0xff)539#define HI_BYTE(v) (((v) >> 8) & 0xff)540 541/*542 * Sets up the voice structure by calculating some values that543 * will be needed later.544 */545static void546setup_voice(struct snd_emux_voice *vp)547{548 struct soundfont_voice_parm *parm;549 int pitch;550 551 /* copy the original register values */552 vp->reg = vp->zone->v;553 554#ifdef SNDRV_EMUX_USE_RAW_EFFECT555 snd_emux_setup_effect(vp);556#endif557 558 /* reset status */559 vp->apan = -1;560 vp->avol = -1;561 vp->apitch = -1;562 563 calc_volume(vp);564 calc_pitch(vp);565 calc_pan(vp);566 567 parm = &vp->reg.parm;568 569 /* compute filter target and correct modulation parameters */570 if (LO_BYTE(parm->modatkhld) >= 0x80 && parm->moddelay >= 0x8000) {571 parm->moddelay = 0xbfff;572 pitch = (HI_BYTE(parm->pefe) << 4) + vp->apitch;573 if (pitch > 0xffff)574 pitch = 0xffff;575 /* calculate filter target */576 vp->ftarget = parm->cutoff + LO_BYTE(parm->pefe);577 LIMITVALUE(vp->ftarget, 0, 255);578 vp->ftarget <<= 8;579 } else {580 vp->ftarget = parm->cutoff;581 vp->ftarget <<= 8;582 pitch = vp->apitch;583 }584 585 /* compute pitch target */586 if (pitch != 0xffff) {587 vp->ptarget = 1 << (pitch >> 12);588 if (pitch & 0x800) vp->ptarget += (vp->ptarget*0x102e)/0x2710;589 if (pitch & 0x400) vp->ptarget += (vp->ptarget*0x764)/0x2710;590 if (pitch & 0x200) vp->ptarget += (vp->ptarget*0x389)/0x2710;591 vp->ptarget += (vp->ptarget >> 1);592 if (vp->ptarget > 0xffff) vp->ptarget = 0xffff;593 } else594 vp->ptarget = 0xffff;595 596 if (LO_BYTE(parm->modatkhld) >= 0x80) {597 parm->modatkhld &= ~0xff;598 parm->modatkhld |= 0x7f;599 }600 601 /* compute volume target and correct volume parameters */602 vp->vtarget = 0;603#if 0 /* FIXME: this leads to some clicks.. */604 if (LO_BYTE(parm->volatkhld) >= 0x80 && parm->voldelay >= 0x8000) {605 parm->voldelay = 0xbfff;606 vp->vtarget = voltarget[vp->avol % 0x10] >> (vp->avol >> 4);607 }608#endif609 610 if (LO_BYTE(parm->volatkhld) >= 0x80) {611 parm->volatkhld &= ~0xff;612 parm->volatkhld |= 0x7f;613 }614}615 616/*617 * calculate pitch parameter618 */619static const unsigned char pan_volumes[256] = {6200x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x14,0x17,0x1a,0x1d,0x20,0x22,0x25,0x28,0x2a,6210x2d,0x30,0x32,0x35,0x37,0x3a,0x3c,0x3f,0x41,0x44,0x46,0x49,0x4b,0x4d,0x50,0x52,6220x54,0x57,0x59,0x5b,0x5d,0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6f,0x71,0x73,0x75,6230x77,0x79,0x7b,0x7c,0x7e,0x80,0x82,0x84,0x86,0x88,0x89,0x8b,0x8d,0x8f,0x90,0x92,6240x94,0x96,0x97,0x99,0x9a,0x9c,0x9e,0x9f,0xa1,0xa2,0xa4,0xa5,0xa7,0xa8,0xaa,0xab,6250xad,0xae,0xaf,0xb1,0xb2,0xb3,0xb5,0xb6,0xb7,0xb9,0xba,0xbb,0xbc,0xbe,0xbf,0xc0,6260xc1,0xc2,0xc3,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,6270xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdc,0xdd,0xde,0xdf,6280xdf,0xe0,0xe1,0xe2,0xe2,0xe3,0xe4,0xe4,0xe5,0xe6,0xe6,0xe7,0xe8,0xe8,0xe9,0xe9,6290xea,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf1,0xf1,0xf1,6300xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,0xf7,6310xf7,0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,6320xfb,0xfb,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,6330xfd,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,6340xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,6350xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,636};637 638static int639calc_pan(struct snd_emux_voice *vp)640{641 struct snd_midi_channel *chan = vp->chan;642 int pan;643 644 /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */645 if (vp->reg.fixpan > 0) /* 0-127 */646 pan = 255 - (int)vp->reg.fixpan * 2;647 else {648 pan = chan->control[MIDI_CTL_MSB_PAN] - 64;649 if (vp->reg.pan >= 0) /* 0-127 */650 pan += vp->reg.pan - 64;651 pan = 127 - (int)pan * 2;652 }653 LIMITVALUE(pan, 0, 255);654 655 if (vp->emu->linear_panning) {656 /* assuming linear volume */657 if (pan != vp->apan) {658 vp->apan = pan;659 if (pan == 0)660 vp->aaux = 0xff;661 else662 vp->aaux = (-pan) & 0xff;663 return 1;664 } else665 return 0;666 } else {667 /* using volume table */668 if (vp->apan != (int)pan_volumes[pan]) {669 vp->apan = pan_volumes[pan];670 vp->aaux = pan_volumes[255 - pan];671 return 1;672 }673 return 0;674 }675}676 677 678/*679 * calculate volume attenuation680 *681 * Voice volume is controlled by volume attenuation parameter.682 * So volume becomes maximum when avol is 0 (no attenuation), and683 * minimum when 255 (-96dB or silence).684 */685 686/* tables for volume->attenuation calculation */687static const unsigned char voltab1[128] = {688 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,689 0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22,690 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,691 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14,692 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10,693 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d,694 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b,695 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,696 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,697 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,698 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02,699 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,700 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00701};702 703static const unsigned char voltab2[128] = {704 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a,705 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21,706 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a,707 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15,708 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10,709 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d,710 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a,711 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,712 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,713 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,714 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,715 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,716 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00717};718 719static const unsigned char expressiontab[128] = {720 0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42,721 0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30,722 0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,723 0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e,724 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18,725 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13,726 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f,727 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c,728 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09,729 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,730 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,731 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,732 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00733};734 735/*736 * Magic to calculate the volume (actually attenuation) from all the737 * voice and channels parameters.738 */739static int740calc_volume(struct snd_emux_voice *vp)741{742 int vol;743 int main_vol, expression_vol, master_vol;744 struct snd_midi_channel *chan = vp->chan;745 struct snd_emux_port *port = vp->port;746 747 expression_vol = chan->control[MIDI_CTL_MSB_EXPRESSION];748 LIMITMAX(vp->velocity, 127);749 LIMITVALUE(expression_vol, 0, 127);750 if (port->port_mode == SNDRV_EMUX_PORT_MODE_OSS_SYNTH) {751 /* 0 - 127 */752 main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME];753 vol = (vp->velocity * main_vol * expression_vol) / (127*127);754 vol = vol * vp->reg.amplitude / 127;755 756 LIMITVALUE(vol, 0, 127);757 758 /* calc to attenuation */759 vol = snd_sf_vol_table[vol];760 761 } else {762 main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME] * vp->reg.amplitude / 127;763 LIMITVALUE(main_vol, 0, 127);764 765 vol = voltab1[main_vol] + voltab2[vp->velocity];766 vol = (vol * 8) / 3;767 vol += vp->reg.attenuation;768 vol += ((0x100 - vol) * expressiontab[expression_vol])/128;769 }770 771 master_vol = port->chset.gs_master_volume;772 LIMITVALUE(master_vol, 0, 127);773 vol += snd_sf_vol_table[master_vol];774 vol += port->volume_atten;775 776#ifdef SNDRV_EMUX_USE_RAW_EFFECT777 if (chan->private) {778 struct snd_emux_effect_table *fx = chan->private;779 vol += fx->val[EMUX_FX_ATTEN];780 }781#endif782 783 LIMITVALUE(vol, 0, 255);784 if (vp->avol == vol)785 return 0; /* value unchanged */786 787 vp->avol = vol;788 if (!SF_IS_DRUM_BANK(get_bank(port, chan))789 && LO_BYTE(vp->reg.parm.volatkhld) < 0x7d) {790 int atten;791 if (vp->velocity < 70)792 atten = 70;793 else794 atten = vp->velocity;795 vp->acutoff = (atten * vp->reg.parm.cutoff + 0xa0) >> 7;796 } else {797 vp->acutoff = vp->reg.parm.cutoff;798 }799 800 return 1; /* value changed */801}802 803/*804 * calculate pitch offset805 *806 * 0xE000 is no pitch offset at 44100Hz sample.807 * Every 4096 is one octave.808 */809 810static int811calc_pitch(struct snd_emux_voice *vp)812{813 struct snd_midi_channel *chan = vp->chan;814 int offset;815 816 /* calculate offset */817 if (vp->reg.fixkey >= 0) {818 offset = (vp->reg.fixkey - vp->reg.root) * 4096 / 12;819 } else {820 offset = (vp->note - vp->reg.root) * 4096 / 12;821 }822 offset = (offset * vp->reg.scaleTuning) / 100;823 offset += vp->reg.tune * 4096 / 1200;824 if (chan->midi_pitchbend != 0) {825 /* (128 * 8192: 1 semitone) ==> (4096: 12 semitones) */826 offset += chan->midi_pitchbend * chan->gm_rpn_pitch_bend_range / 3072;827 }828 829 /* tuning via RPN:830 * coarse = -8192 to 8192 (100 cent per 128)831 * fine = -8192 to 8192 (max=100cent)832 */833 /* 4096 = 1200 cents in emu8000 parameter */834 offset += chan->gm_rpn_coarse_tuning * 4096 / (12 * 128);835 offset += chan->gm_rpn_fine_tuning / 24;836 837#ifdef SNDRV_EMUX_USE_RAW_EFFECT838 /* add initial pitch correction */839 if (chan->private) {840 struct snd_emux_effect_table *fx = chan->private;841 if (fx->flag[EMUX_FX_INIT_PITCH])842 offset += fx->val[EMUX_FX_INIT_PITCH];843 }844#endif845 846 /* 0xe000: root pitch */847 offset += 0xe000 + vp->reg.rate_offset;848 if (vp->emu->ops.get_pitch_shift)849 offset += vp->emu->ops.get_pitch_shift(vp->emu);850 LIMITVALUE(offset, 0, 0xffff);851 if (offset == vp->apitch)852 return 0; /* unchanged */853 vp->apitch = offset;854 return 1; /* value changed */855}856 857/*858 * Get the bank number assigned to the channel859 */860static int861get_bank(struct snd_emux_port *port, struct snd_midi_channel *chan)862{863 int val;864 865 switch (port->chset.midi_mode) {866 case SNDRV_MIDI_MODE_XG:867 val = chan->control[MIDI_CTL_MSB_BANK];868 if (val == 127)869 return 128; /* return drum bank */870 return chan->control[MIDI_CTL_LSB_BANK];871 872 case SNDRV_MIDI_MODE_GS:873 if (chan->drum_channel)874 return 128;875 /* ignore LSB (bank map) */876 return chan->control[MIDI_CTL_MSB_BANK];877 878 default:879 if (chan->drum_channel)880 return 128;881 return chan->control[MIDI_CTL_MSB_BANK];882 }883}884 885 886/* Look for the zones matching with the given note and velocity.887 * The resultant zones are stored on table.888 */889static int890get_zone(struct snd_emux *emu, struct snd_emux_port *port,891 int *notep, int vel, struct snd_midi_channel *chan,892 struct snd_sf_zone **table)893{894 int preset, bank, def_preset, def_bank;895 896 bank = get_bank(port, chan);897 preset = chan->midi_program;898 899 if (SF_IS_DRUM_BANK(bank)) {900 def_preset = port->ctrls[EMUX_MD_DEF_DRUM];901 def_bank = bank;902 } else {903 def_preset = preset;904 def_bank = port->ctrls[EMUX_MD_DEF_BANK];905 }906 907 return snd_soundfont_search_zone(emu->sflist, notep, vel, preset, bank,908 def_preset, def_bank,909 table, SNDRV_EMUX_MAX_MULTI_VOICES);910}911 912/*913 */914void915snd_emux_init_voices(struct snd_emux *emu)916{917 struct snd_emux_voice *vp;918 int i;919 unsigned long flags;920 921 spin_lock_irqsave(&emu->voice_lock, flags);922 for (i = 0; i < emu->max_voices; i++) {923 vp = &emu->voices[i];924 vp->ch = -1; /* not used */925 vp->state = SNDRV_EMUX_ST_OFF;926 vp->chan = NULL;927 vp->port = NULL;928 vp->time = 0;929 vp->emu = emu;930 vp->hw = emu->hw;931 }932 spin_unlock_irqrestore(&emu->voice_lock, flags);933}934 935/*936 */937void snd_emux_lock_voice(struct snd_emux *emu, int voice)938{939 unsigned long flags;940 941 spin_lock_irqsave(&emu->voice_lock, flags);942 if (emu->voices[voice].state == SNDRV_EMUX_ST_OFF)943 emu->voices[voice].state = SNDRV_EMUX_ST_LOCKED;944 else945 dev_warn(emu->card->dev,946 "invalid voice for lock %d (state = %x)\n",947 voice, emu->voices[voice].state);948 spin_unlock_irqrestore(&emu->voice_lock, flags);949}950 951EXPORT_SYMBOL(snd_emux_lock_voice);952 953/*954 */955void snd_emux_unlock_voice(struct snd_emux *emu, int voice)956{957 unsigned long flags;958 959 spin_lock_irqsave(&emu->voice_lock, flags);960 if (emu->voices[voice].state == SNDRV_EMUX_ST_LOCKED)961 emu->voices[voice].state = SNDRV_EMUX_ST_OFF;962 else963 dev_warn(emu->card->dev,964 "invalid voice for unlock %d (state = %x)\n",965 voice, emu->voices[voice].state);966 spin_unlock_irqrestore(&emu->voice_lock, flags);967}968 969EXPORT_SYMBOL(snd_emux_unlock_voice);970