2 * Midi synth routines for the Emu8k/Emu10k1
4 * Copyright (C) 1999 Steve Ratcliffe
5 * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>
7 * Contains code based on awe_wave.c by Takashi Iwai
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.
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.
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
25 #include <linux/export.h>
26 #include "emux_voice.h"
27 #include <sound/asoundef.h>
34 * Ensure a value is between two points
35 * macro evaluates its args more than once, so changed to upper-case.
37 #define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0)
38 #define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0)
40 static int get_zone(struct snd_emux
*emu
, struct snd_emux_port
*port
,
41 int *notep
, int vel
, struct snd_midi_channel
*chan
,
42 struct snd_sf_zone
**table
);
43 static int get_bank(struct snd_emux_port
*port
, struct snd_midi_channel
*chan
);
44 static void terminate_note1(struct snd_emux
*emu
, int note
,
45 struct snd_midi_channel
*chan
, int free
);
46 static void exclusive_note_off(struct snd_emux
*emu
, struct snd_emux_port
*port
,
48 static void terminate_voice(struct snd_emux
*emu
, struct snd_emux_voice
*vp
, int free
);
49 static void update_voice(struct snd_emux
*emu
, struct snd_emux_voice
*vp
, int update
);
50 static void setup_voice(struct snd_emux_voice
*vp
);
51 static int calc_pan(struct snd_emux_voice
*vp
);
52 static int calc_volume(struct snd_emux_voice
*vp
);
53 static int calc_pitch(struct snd_emux_voice
*vp
);
60 snd_emux_note_on(void *p
, int note
, int vel
, struct snd_midi_channel
*chan
)
64 struct snd_emux_voice
*vp
;
65 struct snd_sf_zone
*table
[SNDRV_EMUX_MAX_MULTI_VOICES
];
67 struct snd_emux_port
*port
;
70 if (snd_BUG_ON(!port
|| !chan
))
74 if (snd_BUG_ON(!emu
|| !emu
->ops
.get_voice
|| !emu
->ops
.trigger
))
77 key
= note
; /* remember the original note */
78 nvoices
= get_zone(emu
, port
, ¬e
, vel
, chan
, table
);
82 /* exclusive note off */
83 for (i
= 0; i
< nvoices
; i
++) {
84 struct snd_sf_zone
*zp
= table
[i
];
85 if (zp
&& zp
->v
.exclusiveClass
)
86 exclusive_note_off(emu
, port
, zp
->v
.exclusiveClass
);
89 #if 0 // seems not necessary
90 /* Turn off the same note on the same channel. */
91 terminate_note1(emu
, key
, chan
, 0);
94 spin_lock_irqsave(&emu
->voice_lock
, flags
);
95 for (i
= 0; i
< nvoices
; i
++) {
97 /* set up each voice parameter */
98 /* at this stage, we don't trigger the voice yet. */
100 if (table
[i
] == NULL
)
103 vp
= emu
->ops
.get_voice(emu
, port
);
104 if (vp
== NULL
|| vp
->ch
< 0)
106 if (STATE_IS_PLAYING(vp
->state
))
107 emu
->ops
.terminate(vp
);
109 vp
->time
= emu
->use_time
++;
116 if (vp
->zone
->sample
)
117 vp
->block
= vp
->zone
->sample
->block
;
123 vp
->state
= SNDRV_EMUX_ST_STANDBY
;
124 if (emu
->ops
.prepare
) {
125 vp
->state
= SNDRV_EMUX_ST_OFF
;
126 if (emu
->ops
.prepare(vp
) >= 0)
127 vp
->state
= SNDRV_EMUX_ST_STANDBY
;
131 /* start envelope now */
132 for (i
= 0; i
< emu
->max_voices
; i
++) {
133 vp
= &emu
->voices
[i
];
134 if (vp
->state
== SNDRV_EMUX_ST_STANDBY
&&
136 emu
->ops
.trigger(vp
);
137 vp
->state
= SNDRV_EMUX_ST_ON
;
138 vp
->ontime
= jiffies
; /* remember the trigger timing */
141 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
143 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
144 if (port
->port_mode
== SNDRV_EMUX_PORT_MODE_OSS_SYNTH
) {
145 /* clear voice position for the next note on this channel */
146 struct snd_emux_effect_table
*fx
= chan
->private;
148 fx
->flag
[EMUX_FX_SAMPLE_START
] = 0;
149 fx
->flag
[EMUX_FX_COARSE_SAMPLE_START
] = 0;
156 * Release a note in response to a midi note off.
159 snd_emux_note_off(void *p
, int note
, int vel
, struct snd_midi_channel
*chan
)
162 struct snd_emux
*emu
;
163 struct snd_emux_voice
*vp
;
165 struct snd_emux_port
*port
;
168 if (snd_BUG_ON(!port
|| !chan
))
172 if (snd_BUG_ON(!emu
|| !emu
->ops
.release
))
175 spin_lock_irqsave(&emu
->voice_lock
, flags
);
176 for (ch
= 0; ch
< emu
->max_voices
; ch
++) {
177 vp
= &emu
->voices
[ch
];
178 if (STATE_IS_PLAYING(vp
->state
) &&
179 vp
->chan
== chan
&& vp
->key
== note
) {
180 vp
->state
= SNDRV_EMUX_ST_RELEASED
;
181 if (vp
->ontime
== jiffies
) {
182 /* if note-off is sent too shortly after
183 * note-on, emuX engine cannot produce the sound
184 * correctly. so we'll release this note
185 * a bit later via timer callback.
187 vp
->state
= SNDRV_EMUX_ST_PENDING
;
188 if (! emu
->timer_active
) {
189 emu
->tlist
.expires
= jiffies
+ 1;
190 add_timer(&emu
->tlist
);
191 emu
->timer_active
= 1;
194 /* ok now release the note */
195 emu
->ops
.release(vp
);
198 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
204 * release the pending note-offs
206 void snd_emux_timer_callback(unsigned long data
)
208 struct snd_emux
*emu
= (struct snd_emux
*) data
;
209 struct snd_emux_voice
*vp
;
211 int ch
, do_again
= 0;
213 spin_lock_irqsave(&emu
->voice_lock
, flags
);
214 for (ch
= 0; ch
< emu
->max_voices
; ch
++) {
215 vp
= &emu
->voices
[ch
];
216 if (vp
->state
== SNDRV_EMUX_ST_PENDING
) {
217 if (vp
->ontime
== jiffies
)
218 do_again
++; /* release this at the next interrupt */
220 emu
->ops
.release(vp
);
221 vp
->state
= SNDRV_EMUX_ST_RELEASED
;
226 emu
->tlist
.expires
= jiffies
+ 1;
227 add_timer(&emu
->tlist
);
228 emu
->timer_active
= 1;
230 emu
->timer_active
= 0;
231 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
235 * key pressure change
238 snd_emux_key_press(void *p
, int note
, int vel
, struct snd_midi_channel
*chan
)
241 struct snd_emux
*emu
;
242 struct snd_emux_voice
*vp
;
244 struct snd_emux_port
*port
;
247 if (snd_BUG_ON(!port
|| !chan
))
251 if (snd_BUG_ON(!emu
|| !emu
->ops
.update
))
254 spin_lock_irqsave(&emu
->voice_lock
, flags
);
255 for (ch
= 0; ch
< emu
->max_voices
; ch
++) {
256 vp
= &emu
->voices
[ch
];
257 if (vp
->state
== SNDRV_EMUX_ST_ON
&&
258 vp
->chan
== chan
&& vp
->key
== note
) {
260 update_voice(emu
, vp
, SNDRV_EMUX_UPDATE_VOLUME
);
263 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
268 * Modulate the voices which belong to the channel
271 snd_emux_update_channel(struct snd_emux_port
*port
, struct snd_midi_channel
*chan
, int update
)
273 struct snd_emux
*emu
;
274 struct snd_emux_voice
*vp
;
282 if (snd_BUG_ON(!emu
|| !emu
->ops
.update
))
285 spin_lock_irqsave(&emu
->voice_lock
, flags
);
286 for (i
= 0; i
< emu
->max_voices
; i
++) {
287 vp
= &emu
->voices
[i
];
288 if (vp
->chan
== chan
)
289 update_voice(emu
, vp
, update
);
291 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
295 * Modulate all the voices which belong to the port.
298 snd_emux_update_port(struct snd_emux_port
*port
, int update
)
300 struct snd_emux
*emu
;
301 struct snd_emux_voice
*vp
;
309 if (snd_BUG_ON(!emu
|| !emu
->ops
.update
))
312 spin_lock_irqsave(&emu
->voice_lock
, flags
);
313 for (i
= 0; i
< emu
->max_voices
; i
++) {
314 vp
= &emu
->voices
[i
];
315 if (vp
->port
== port
)
316 update_voice(emu
, vp
, update
);
318 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
323 * Deal with a controller type event. This includes all types of
324 * control events, not just the midi controllers
327 snd_emux_control(void *p
, int type
, struct snd_midi_channel
*chan
)
329 struct snd_emux_port
*port
;
332 if (snd_BUG_ON(!port
|| !chan
))
336 case MIDI_CTL_MSB_MAIN_VOLUME
:
337 case MIDI_CTL_MSB_EXPRESSION
:
338 snd_emux_update_channel(port
, chan
, SNDRV_EMUX_UPDATE_VOLUME
);
341 case MIDI_CTL_MSB_PAN
:
342 snd_emux_update_channel(port
, chan
, SNDRV_EMUX_UPDATE_PAN
);
345 case MIDI_CTL_SOFT_PEDAL
:
346 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
347 /* FIXME: this is an emulation */
348 if (chan
->control
[type
] >= 64)
349 snd_emux_send_effect(port
, chan
, EMUX_FX_CUTOFF
, -160,
352 snd_emux_send_effect(port
, chan
, EMUX_FX_CUTOFF
, 0,
357 case MIDI_CTL_PITCHBEND
:
358 snd_emux_update_channel(port
, chan
, SNDRV_EMUX_UPDATE_PITCH
);
361 case MIDI_CTL_MSB_MODWHEEL
:
362 case MIDI_CTL_CHAN_PRESSURE
:
363 snd_emux_update_channel(port
, chan
,
364 SNDRV_EMUX_UPDATE_FMMOD
|
365 SNDRV_EMUX_UPDATE_FM2FRQ2
);
370 if (port
->chset
.midi_mode
== SNDRV_MIDI_MODE_XG
) {
371 snd_emux_xg_control(port
, chan
, type
);
377 * terminate note - if free flag is true, free the terminated voice
380 terminate_note1(struct snd_emux
*emu
, int note
, struct snd_midi_channel
*chan
, int free
)
383 struct snd_emux_voice
*vp
;
386 spin_lock_irqsave(&emu
->voice_lock
, flags
);
387 for (i
= 0; i
< emu
->max_voices
; i
++) {
388 vp
= &emu
->voices
[i
];
389 if (STATE_IS_PLAYING(vp
->state
) && vp
->chan
== chan
&&
391 terminate_voice(emu
, vp
, free
);
393 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
398 * terminate note - exported for midi emulation
401 snd_emux_terminate_note(void *p
, int note
, struct snd_midi_channel
*chan
)
403 struct snd_emux
*emu
;
404 struct snd_emux_port
*port
;
407 if (snd_BUG_ON(!port
|| !chan
))
411 if (snd_BUG_ON(!emu
|| !emu
->ops
.terminate
))
414 terminate_note1(emu
, note
, chan
, 1);
419 * Terminate all the notes
422 snd_emux_terminate_all(struct snd_emux
*emu
)
425 struct snd_emux_voice
*vp
;
428 spin_lock_irqsave(&emu
->voice_lock
, flags
);
429 for (i
= 0; i
< emu
->max_voices
; i
++) {
430 vp
= &emu
->voices
[i
];
431 if (STATE_IS_PLAYING(vp
->state
))
432 terminate_voice(emu
, vp
, 0);
433 if (vp
->state
== SNDRV_EMUX_ST_OFF
) {
434 if (emu
->ops
.free_voice
)
435 emu
->ops
.free_voice(vp
);
437 emu
->ops
.reset(emu
, i
);
441 /* initialize allocation time */
443 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
446 EXPORT_SYMBOL(snd_emux_terminate_all
);
449 * Terminate all voices associated with the given port
452 snd_emux_sounds_off_all(struct snd_emux_port
*port
)
455 struct snd_emux
*emu
;
456 struct snd_emux_voice
*vp
;
459 if (snd_BUG_ON(!port
))
462 if (snd_BUG_ON(!emu
|| !emu
->ops
.terminate
))
465 spin_lock_irqsave(&emu
->voice_lock
, flags
);
466 for (i
= 0; i
< emu
->max_voices
; i
++) {
467 vp
= &emu
->voices
[i
];
468 if (STATE_IS_PLAYING(vp
->state
) &&
470 terminate_voice(emu
, vp
, 0);
471 if (vp
->state
== SNDRV_EMUX_ST_OFF
) {
472 if (emu
->ops
.free_voice
)
473 emu
->ops
.free_voice(vp
);
475 emu
->ops
.reset(emu
, i
);
478 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
483 * Terminate all voices that have the same exclusive class. This
484 * is mainly for drums.
487 exclusive_note_off(struct snd_emux
*emu
, struct snd_emux_port
*port
, int exclass
)
489 struct snd_emux_voice
*vp
;
493 spin_lock_irqsave(&emu
->voice_lock
, flags
);
494 for (i
= 0; i
< emu
->max_voices
; i
++) {
495 vp
= &emu
->voices
[i
];
496 if (STATE_IS_PLAYING(vp
->state
) && vp
->port
== port
&&
497 vp
->reg
.exclusiveClass
== exclass
) {
498 terminate_voice(emu
, vp
, 0);
501 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
506 * if free flag is true, call free_voice after termination
509 terminate_voice(struct snd_emux
*emu
, struct snd_emux_voice
*vp
, int free
)
511 emu
->ops
.terminate(vp
);
512 vp
->time
= emu
->use_time
++;
517 vp
->state
= SNDRV_EMUX_ST_OFF
;
518 if (free
&& emu
->ops
.free_voice
)
519 emu
->ops
.free_voice(vp
);
527 update_voice(struct snd_emux
*emu
, struct snd_emux_voice
*vp
, int update
)
529 if (!STATE_IS_PLAYING(vp
->state
))
532 if (vp
->chan
== NULL
|| vp
->port
== NULL
)
534 if (update
& SNDRV_EMUX_UPDATE_VOLUME
)
536 if (update
& SNDRV_EMUX_UPDATE_PITCH
)
538 if (update
& SNDRV_EMUX_UPDATE_PAN
) {
539 if (! calc_pan(vp
) && (update
== SNDRV_EMUX_UPDATE_PAN
))
542 emu
->ops
.update(vp
, update
);
547 /* table for volume target calculation */
548 static unsigned short voltarget
[16] = {
549 0xEAC0, 0xE0C8, 0xD740, 0xCE20, 0xC560, 0xBD08, 0xB500, 0xAD58,
550 0xA5F8, 0x9EF0, 0x9830, 0x91C0, 0x8B90, 0x85A8, 0x8000, 0x7A90
554 #define LO_BYTE(v) ((v) & 0xff)
555 #define HI_BYTE(v) (((v) >> 8) & 0xff)
558 * Sets up the voice structure by calculating some values that
559 * will be needed later.
562 setup_voice(struct snd_emux_voice
*vp
)
564 struct soundfont_voice_parm
*parm
;
567 /* copy the original register values */
568 vp
->reg
= vp
->zone
->v
;
570 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
571 snd_emux_setup_effect(vp
);
583 parm
= &vp
->reg
.parm
;
585 /* compute filter target and correct modulation parameters */
586 if (LO_BYTE(parm
->modatkhld
) >= 0x80 && parm
->moddelay
>= 0x8000) {
587 parm
->moddelay
= 0xbfff;
588 pitch
= (HI_BYTE(parm
->pefe
) << 4) + vp
->apitch
;
591 /* calculate filter target */
592 vp
->ftarget
= parm
->cutoff
+ LO_BYTE(parm
->pefe
);
593 LIMITVALUE(vp
->ftarget
, 0, 255);
596 vp
->ftarget
= parm
->cutoff
;
601 /* compute pitch target */
602 if (pitch
!= 0xffff) {
603 vp
->ptarget
= 1 << (pitch
>> 12);
604 if (pitch
& 0x800) vp
->ptarget
+= (vp
->ptarget
*0x102e)/0x2710;
605 if (pitch
& 0x400) vp
->ptarget
+= (vp
->ptarget
*0x764)/0x2710;
606 if (pitch
& 0x200) vp
->ptarget
+= (vp
->ptarget
*0x389)/0x2710;
607 vp
->ptarget
+= (vp
->ptarget
>> 1);
608 if (vp
->ptarget
> 0xffff) vp
->ptarget
= 0xffff;
610 vp
->ptarget
= 0xffff;
612 if (LO_BYTE(parm
->modatkhld
) >= 0x80) {
613 parm
->modatkhld
&= ~0xff;
614 parm
->modatkhld
|= 0x7f;
617 /* compute volume target and correct volume parameters */
619 #if 0 /* FIXME: this leads to some clicks.. */
620 if (LO_BYTE(parm
->volatkhld
) >= 0x80 && parm
->voldelay
>= 0x8000) {
621 parm
->voldelay
= 0xbfff;
622 vp
->vtarget
= voltarget
[vp
->avol
% 0x10] >> (vp
->avol
>> 4);
626 if (LO_BYTE(parm
->volatkhld
) >= 0x80) {
627 parm
->volatkhld
&= ~0xff;
628 parm
->volatkhld
|= 0x7f;
633 * calculate pitch parameter
635 static unsigned char pan_volumes
[256] = {
636 0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x14,0x17,0x1a,0x1d,0x20,0x22,0x25,0x28,0x2a,
637 0x2d,0x30,0x32,0x35,0x37,0x3a,0x3c,0x3f,0x41,0x44,0x46,0x49,0x4b,0x4d,0x50,0x52,
638 0x54,0x57,0x59,0x5b,0x5d,0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6f,0x71,0x73,0x75,
639 0x77,0x79,0x7b,0x7c,0x7e,0x80,0x82,0x84,0x86,0x88,0x89,0x8b,0x8d,0x8f,0x90,0x92,
640 0x94,0x96,0x97,0x99,0x9a,0x9c,0x9e,0x9f,0xa1,0xa2,0xa4,0xa5,0xa7,0xa8,0xaa,0xab,
641 0xad,0xae,0xaf,0xb1,0xb2,0xb3,0xb5,0xb6,0xb7,0xb9,0xba,0xbb,0xbc,0xbe,0xbf,0xc0,
642 0xc1,0xc2,0xc3,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,
643 0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdc,0xdd,0xde,0xdf,
644 0xdf,0xe0,0xe1,0xe2,0xe2,0xe3,0xe4,0xe4,0xe5,0xe6,0xe6,0xe7,0xe8,0xe8,0xe9,0xe9,
645 0xea,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf1,0xf1,0xf1,
646 0xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,0xf7,
647 0xf7,0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,
648 0xfb,0xfb,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
649 0xfd,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
650 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
651 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
655 calc_pan(struct snd_emux_voice
*vp
)
657 struct snd_midi_channel
*chan
= vp
->chan
;
660 /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */
661 if (vp
->reg
.fixpan
> 0) /* 0-127 */
662 pan
= 255 - (int)vp
->reg
.fixpan
* 2;
664 pan
= chan
->control
[MIDI_CTL_MSB_PAN
] - 64;
665 if (vp
->reg
.pan
>= 0) /* 0-127 */
666 pan
+= vp
->reg
.pan
- 64;
667 pan
= 127 - (int)pan
* 2;
669 LIMITVALUE(pan
, 0, 255);
671 if (vp
->emu
->linear_panning
) {
672 /* assuming linear volume */
673 if (pan
!= vp
->apan
) {
678 vp
->aaux
= (-pan
) & 0xff;
683 /* using volume table */
684 if (vp
->apan
!= (int)pan_volumes
[pan
]) {
685 vp
->apan
= pan_volumes
[pan
];
686 vp
->aaux
= pan_volumes
[255 - pan
];
695 * calculate volume attenuation
697 * Voice volume is controlled by volume attenuation parameter.
698 * So volume becomes maximum when avol is 0 (no attenuation), and
699 * minimum when 255 (-96dB or silence).
702 /* tables for volume->attenuation calculation */
703 static unsigned char voltab1
[128] = {
704 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
705 0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22,
706 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
707 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14,
708 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10,
709 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d,
710 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b,
711 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,
712 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,
713 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,
714 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02,
715 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
716 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
719 static unsigned char voltab2
[128] = {
720 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a,
721 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21,
722 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a,
723 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15,
724 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10,
725 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d,
726 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a,
727 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
728 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
729 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
730 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
731 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
732 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
735 static unsigned char expressiontab
[128] = {
736 0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42,
737 0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30,
738 0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,
739 0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e,
740 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18,
741 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13,
742 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f,
743 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c,
744 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09,
745 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
746 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
747 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
748 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
752 * Magic to calculate the volume (actually attenuation) from all the
753 * voice and channels parameters.
756 calc_volume(struct snd_emux_voice
*vp
)
759 int main_vol
, expression_vol
, master_vol
;
760 struct snd_midi_channel
*chan
= vp
->chan
;
761 struct snd_emux_port
*port
= vp
->port
;
763 expression_vol
= chan
->control
[MIDI_CTL_MSB_EXPRESSION
];
764 LIMITMAX(vp
->velocity
, 127);
765 LIMITVALUE(expression_vol
, 0, 127);
766 if (port
->port_mode
== SNDRV_EMUX_PORT_MODE_OSS_SYNTH
) {
768 main_vol
= chan
->control
[MIDI_CTL_MSB_MAIN_VOLUME
];
769 vol
= (vp
->velocity
* main_vol
* expression_vol
) / (127*127);
770 vol
= vol
* vp
->reg
.amplitude
/ 127;
772 LIMITVALUE(vol
, 0, 127);
774 /* calc to attenuation */
775 vol
= snd_sf_vol_table
[vol
];
778 main_vol
= chan
->control
[MIDI_CTL_MSB_MAIN_VOLUME
] * vp
->reg
.amplitude
/ 127;
779 LIMITVALUE(main_vol
, 0, 127);
781 vol
= voltab1
[main_vol
] + voltab2
[vp
->velocity
];
783 vol
+= vp
->reg
.attenuation
;
784 vol
+= ((0x100 - vol
) * expressiontab
[expression_vol
])/128;
787 master_vol
= port
->chset
.gs_master_volume
;
788 LIMITVALUE(master_vol
, 0, 127);
789 vol
+= snd_sf_vol_table
[master_vol
];
790 vol
+= port
->volume_atten
;
792 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
794 struct snd_emux_effect_table
*fx
= chan
->private;
795 vol
+= fx
->val
[EMUX_FX_ATTEN
];
799 LIMITVALUE(vol
, 0, 255);
801 return 0; /* value unchanged */
804 if (!SF_IS_DRUM_BANK(get_bank(port
, chan
))
805 && LO_BYTE(vp
->reg
.parm
.volatkhld
) < 0x7d) {
807 if (vp
->velocity
< 70)
810 atten
= vp
->velocity
;
811 vp
->acutoff
= (atten
* vp
->reg
.parm
.cutoff
+ 0xa0) >> 7;
813 vp
->acutoff
= vp
->reg
.parm
.cutoff
;
816 return 1; /* value changed */
820 * calculate pitch offset
822 * 0xE000 is no pitch offset at 44100Hz sample.
823 * Every 4096 is one octave.
827 calc_pitch(struct snd_emux_voice
*vp
)
829 struct snd_midi_channel
*chan
= vp
->chan
;
832 /* calculate offset */
833 if (vp
->reg
.fixkey
>= 0) {
834 offset
= (vp
->reg
.fixkey
- vp
->reg
.root
) * 4096 / 12;
836 offset
= (vp
->note
- vp
->reg
.root
) * 4096 / 12;
838 offset
= (offset
* vp
->reg
.scaleTuning
) / 100;
839 offset
+= vp
->reg
.tune
* 4096 / 1200;
840 if (chan
->midi_pitchbend
!= 0) {
841 /* (128 * 8192: 1 semitone) ==> (4096: 12 semitones) */
842 offset
+= chan
->midi_pitchbend
* chan
->gm_rpn_pitch_bend_range
/ 3072;
846 * coarse = -8192 to 8192 (100 cent per 128)
847 * fine = -8192 to 8192 (max=100cent)
849 /* 4096 = 1200 cents in emu8000 parameter */
850 offset
+= chan
->gm_rpn_coarse_tuning
* 4096 / (12 * 128);
851 offset
+= chan
->gm_rpn_fine_tuning
/ 24;
853 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
854 /* add initial pitch correction */
856 struct snd_emux_effect_table
*fx
= chan
->private;
857 if (fx
->flag
[EMUX_FX_INIT_PITCH
])
858 offset
+= fx
->val
[EMUX_FX_INIT_PITCH
];
862 /* 0xe000: root pitch */
863 offset
+= 0xe000 + vp
->reg
.rate_offset
;
864 offset
+= vp
->emu
->pitch_shift
;
865 LIMITVALUE(offset
, 0, 0xffff);
866 if (offset
== vp
->apitch
)
867 return 0; /* unchanged */
869 return 1; /* value changed */
873 * Get the bank number assigned to the channel
876 get_bank(struct snd_emux_port
*port
, struct snd_midi_channel
*chan
)
880 switch (port
->chset
.midi_mode
) {
881 case SNDRV_MIDI_MODE_XG
:
882 val
= chan
->control
[MIDI_CTL_MSB_BANK
];
884 return 128; /* return drum bank */
885 return chan
->control
[MIDI_CTL_LSB_BANK
];
887 case SNDRV_MIDI_MODE_GS
:
888 if (chan
->drum_channel
)
890 /* ignore LSB (bank map) */
891 return chan
->control
[MIDI_CTL_MSB_BANK
];
894 if (chan
->drum_channel
)
896 return chan
->control
[MIDI_CTL_MSB_BANK
];
901 /* Look for the zones matching with the given note and velocity.
902 * The resultant zones are stored on table.
905 get_zone(struct snd_emux
*emu
, struct snd_emux_port
*port
,
906 int *notep
, int vel
, struct snd_midi_channel
*chan
,
907 struct snd_sf_zone
**table
)
909 int preset
, bank
, def_preset
, def_bank
;
911 bank
= get_bank(port
, chan
);
912 preset
= chan
->midi_program
;
914 if (SF_IS_DRUM_BANK(bank
)) {
915 def_preset
= port
->ctrls
[EMUX_MD_DEF_DRUM
];
919 def_bank
= port
->ctrls
[EMUX_MD_DEF_BANK
];
922 return snd_soundfont_search_zone(emu
->sflist
, notep
, vel
, preset
, bank
,
923 def_preset
, def_bank
,
924 table
, SNDRV_EMUX_MAX_MULTI_VOICES
);
930 snd_emux_init_voices(struct snd_emux
*emu
)
932 struct snd_emux_voice
*vp
;
936 spin_lock_irqsave(&emu
->voice_lock
, flags
);
937 for (i
= 0; i
< emu
->max_voices
; i
++) {
938 vp
= &emu
->voices
[i
];
939 vp
->ch
= -1; /* not used */
940 vp
->state
= SNDRV_EMUX_ST_OFF
;
947 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
952 void snd_emux_lock_voice(struct snd_emux
*emu
, int voice
)
956 spin_lock_irqsave(&emu
->voice_lock
, flags
);
957 if (emu
->voices
[voice
].state
== SNDRV_EMUX_ST_OFF
)
958 emu
->voices
[voice
].state
= SNDRV_EMUX_ST_LOCKED
;
960 snd_printk(KERN_WARNING
961 "invalid voice for lock %d (state = %x)\n",
962 voice
, emu
->voices
[voice
].state
);
963 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
966 EXPORT_SYMBOL(snd_emux_lock_voice
);
970 void snd_emux_unlock_voice(struct snd_emux
*emu
, int voice
)
974 spin_lock_irqsave(&emu
->voice_lock
, flags
);
975 if (emu
->voices
[voice
].state
== SNDRV_EMUX_ST_LOCKED
)
976 emu
->voices
[voice
].state
= SNDRV_EMUX_ST_OFF
;
978 snd_printk(KERN_WARNING
979 "invalid voice for unlock %d (state = %x)\n",
980 voice
, emu
->voices
[voice
].state
);
981 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
984 EXPORT_SYMBOL(snd_emux_unlock_voice
);