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