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 "emux_voice.h"
26 #include <sound/asoundef.h>
33 * Ensure a value is between two points
34 * macro evaluates its args more than once, so changed to upper-case.
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)
39 static int get_zone(snd_emux_t
*emu
, snd_emux_port_t
*port
, int *notep
, int vel
, snd_midi_channel_t
*chan
, snd_sf_zone_t
**table
);
40 static int get_bank(snd_emux_port_t
*port
, snd_midi_channel_t
*chan
);
41 static void terminate_note1(snd_emux_t
*emu
, int note
, snd_midi_channel_t
*chan
, int free
);
42 static void exclusive_note_off(snd_emux_t
*emu
, snd_emux_port_t
*port
, int exclass
);
43 static void terminate_voice(snd_emux_t
*emu
, snd_emux_voice_t
*vp
, int free
);
44 static void update_voice(snd_emux_t
*emu
, snd_emux_voice_t
*vp
, int update
);
45 static void setup_voice(snd_emux_voice_t
*vp
);
46 static int calc_pan(snd_emux_voice_t
*vp
);
47 static int calc_volume(snd_emux_voice_t
*vp
);
48 static int calc_pitch(snd_emux_voice_t
*vp
);
55 snd_emux_note_on(void *p
, int note
, int vel
, snd_midi_channel_t
*chan
)
60 snd_sf_zone_t
*table
[SNDRV_EMUX_MAX_MULTI_VOICES
];
62 snd_emux_port_t
*port
;
65 snd_assert(port
!= NULL
&& chan
!= NULL
, return);
68 snd_assert(emu
!= NULL
, return);
69 snd_assert(emu
->ops
.get_voice
!= NULL
, return);
70 snd_assert(emu
->ops
.trigger
!= NULL
, return);
72 key
= note
; /* remember the original note */
73 nvoices
= get_zone(emu
, port
, ¬e
, vel
, chan
, table
);
77 /* exclusive note off */
78 for (i
= 0; i
< nvoices
; i
++) {
79 snd_sf_zone_t
*zp
= table
[i
];
80 if (zp
&& zp
->v
.exclusiveClass
)
81 exclusive_note_off(emu
, port
, zp
->v
.exclusiveClass
);
84 #if 0 // seems not necessary
85 /* Turn off the same note on the same channel. */
86 terminate_note1(emu
, key
, chan
, 0);
89 spin_lock_irqsave(&emu
->voice_lock
, flags
);
90 for (i
= 0; i
< nvoices
; i
++) {
92 /* set up each voice parameter */
93 /* at this stage, we don't trigger the voice yet. */
98 vp
= emu
->ops
.get_voice(emu
, port
);
99 if (vp
== NULL
|| vp
->ch
< 0)
101 snd_assert(vp
->emu
!= NULL
&& vp
->hw
!= NULL
, return);
102 if (STATE_IS_PLAYING(vp
->state
))
103 emu
->ops
.terminate(vp
);
105 vp
->time
= emu
->use_time
++;
112 if (vp
->zone
->sample
)
113 vp
->block
= vp
->zone
->sample
->block
;
119 vp
->state
= SNDRV_EMUX_ST_STANDBY
;
120 if (emu
->ops
.prepare
) {
121 vp
->state
= SNDRV_EMUX_ST_OFF
;
122 if (emu
->ops
.prepare(vp
) >= 0)
123 vp
->state
= SNDRV_EMUX_ST_STANDBY
;
127 /* start envelope now */
128 for (i
= 0; i
< emu
->max_voices
; i
++) {
129 vp
= &emu
->voices
[i
];
130 if (vp
->state
== SNDRV_EMUX_ST_STANDBY
&&
132 emu
->ops
.trigger(vp
);
133 vp
->state
= SNDRV_EMUX_ST_ON
;
134 vp
->ontime
= jiffies
; /* remember the trigger timing */
137 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
139 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
140 if (port
->port_mode
== SNDRV_EMUX_PORT_MODE_OSS_SYNTH
) {
141 /* clear voice position for the next note on this channel */
142 snd_emux_effect_table_t
*fx
= chan
->private;
144 fx
->flag
[EMUX_FX_SAMPLE_START
] = 0;
145 fx
->flag
[EMUX_FX_COARSE_SAMPLE_START
] = 0;
152 * Release a note in response to a midi note off.
155 snd_emux_note_off(void *p
, int note
, int vel
, snd_midi_channel_t
*chan
)
159 snd_emux_voice_t
*vp
;
161 snd_emux_port_t
*port
;
164 snd_assert(port
!= NULL
&& chan
!= NULL
, return);
167 snd_assert(emu
!= NULL
, return);
168 snd_assert(emu
->ops
.release
!= NULL
, return);
170 spin_lock_irqsave(&emu
->voice_lock
, flags
);
171 for (ch
= 0; ch
< emu
->max_voices
; ch
++) {
172 vp
= &emu
->voices
[ch
];
173 if (STATE_IS_PLAYING(vp
->state
) &&
174 vp
->chan
== chan
&& vp
->key
== note
) {
175 vp
->time
= emu
->use_time
++;
176 vp
->state
= SNDRV_EMUX_ST_RELEASED
;
177 if (vp
->ontime
== jiffies
) {
178 /* if note-off is sent too shortly after
179 * note-on, emuX engine cannot produce the sound
180 * correctly. so we'll release this note
181 * a bit later via timer callback.
183 vp
->state
= SNDRV_EMUX_ST_PENDING
;
184 if (! emu
->timer_active
) {
185 emu
->tlist
.expires
= jiffies
+ 1;
186 add_timer(&emu
->tlist
);
187 emu
->timer_active
= 1;
190 /* ok now release the note */
191 emu
->ops
.release(vp
);
194 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
200 * release the pending note-offs
202 void snd_emux_timer_callback(unsigned long data
)
204 snd_emux_t
*emu
= (snd_emux_t
*) data
;
205 snd_emux_voice_t
*vp
;
206 int ch
, do_again
= 0;
208 spin_lock(&emu
->voice_lock
);
209 for (ch
= 0; ch
< emu
->max_voices
; ch
++) {
210 vp
= &emu
->voices
[ch
];
211 if (vp
->state
== SNDRV_EMUX_ST_PENDING
) {
212 if (vp
->ontime
== jiffies
)
213 do_again
++; /* release this at the next interrupt */
215 emu
->ops
.release(vp
);
216 vp
->state
= SNDRV_EMUX_ST_RELEASED
;
221 emu
->tlist
.expires
= jiffies
+ 1;
222 add_timer(&emu
->tlist
);
223 emu
->timer_active
= 1;
225 emu
->timer_active
= 0;
226 spin_unlock(&emu
->voice_lock
);
230 * key pressure change
233 snd_emux_key_press(void *p
, int note
, int vel
, snd_midi_channel_t
*chan
)
237 snd_emux_voice_t
*vp
;
239 snd_emux_port_t
*port
;
242 snd_assert(port
!= NULL
&& chan
!= NULL
, return);
245 snd_assert(emu
!= NULL
, return);
246 snd_assert(emu
->ops
.update
!= NULL
, return);
248 spin_lock_irqsave(&emu
->voice_lock
, flags
);
249 for (ch
= 0; ch
< emu
->max_voices
; ch
++) {
250 vp
= &emu
->voices
[ch
];
251 if (vp
->state
== SNDRV_EMUX_ST_ON
&&
252 vp
->chan
== chan
&& vp
->key
== note
) {
254 update_voice(emu
, vp
, SNDRV_EMUX_UPDATE_VOLUME
);
257 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
262 * Modulate the voices which belong to the channel
265 snd_emux_update_channel(snd_emux_port_t
*port
, snd_midi_channel_t
*chan
, int update
)
268 snd_emux_voice_t
*vp
;
276 snd_assert(emu
!= NULL
, return);
277 snd_assert(emu
->ops
.update
!= NULL
, return);
279 spin_lock_irqsave(&emu
->voice_lock
, flags
);
280 for (i
= 0; i
< emu
->max_voices
; i
++) {
281 vp
= &emu
->voices
[i
];
282 if (vp
->chan
== chan
)
283 update_voice(emu
, vp
, update
);
285 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
289 * Modulate all the voices which belong to the port.
292 snd_emux_update_port(snd_emux_port_t
*port
, int update
)
295 snd_emux_voice_t
*vp
;
303 snd_assert(emu
!= NULL
, return);
304 snd_assert(emu
->ops
.update
!= NULL
, return);
306 spin_lock_irqsave(&emu
->voice_lock
, flags
);
307 for (i
= 0; i
< emu
->max_voices
; i
++) {
308 vp
= &emu
->voices
[i
];
309 if (vp
->port
== port
)
310 update_voice(emu
, vp
, update
);
312 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
317 * Deal with a controler type event. This includes all types of
318 * control events, not just the midi controllers
321 snd_emux_control(void *p
, int type
, snd_midi_channel_t
*chan
)
323 snd_emux_port_t
*port
;
326 snd_assert(port
!= NULL
&& chan
!= NULL
, return);
329 case MIDI_CTL_MSB_MAIN_VOLUME
:
330 case MIDI_CTL_MSB_EXPRESSION
:
331 snd_emux_update_channel(port
, chan
, SNDRV_EMUX_UPDATE_VOLUME
);
334 case MIDI_CTL_MSB_PAN
:
335 snd_emux_update_channel(port
, chan
, SNDRV_EMUX_UPDATE_PAN
);
338 case MIDI_CTL_SOFT_PEDAL
:
339 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
340 /* FIXME: this is an emulation */
341 snd_emux_send_effect(port
, chan
, EMUX_FX_CUTOFF
, -160,
346 case MIDI_CTL_PITCHBEND
:
347 snd_emux_update_channel(port
, chan
, SNDRV_EMUX_UPDATE_PITCH
);
350 case MIDI_CTL_MSB_MODWHEEL
:
351 case MIDI_CTL_CHAN_PRESSURE
:
352 snd_emux_update_channel(port
, chan
,
353 SNDRV_EMUX_UPDATE_FMMOD
|
354 SNDRV_EMUX_UPDATE_FM2FRQ2
);
359 if (port
->chset
.midi_mode
== SNDRV_MIDI_MODE_XG
) {
360 snd_emux_xg_control(port
, chan
, type
);
366 * terminate note - if free flag is true, free the terminated voice
369 terminate_note1(snd_emux_t
*emu
, int note
, snd_midi_channel_t
*chan
, int free
)
372 snd_emux_voice_t
*vp
;
375 spin_lock_irqsave(&emu
->voice_lock
, flags
);
376 for (i
= 0; i
< emu
->max_voices
; i
++) {
377 vp
= &emu
->voices
[i
];
378 if (STATE_IS_PLAYING(vp
->state
) && vp
->chan
== chan
&&
380 terminate_voice(emu
, vp
, free
);
382 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
387 * terminate note - exported for midi emulation
390 snd_emux_terminate_note(void *p
, int note
, snd_midi_channel_t
*chan
)
393 snd_emux_port_t
*port
;
396 snd_assert(port
!= NULL
&& chan
!= NULL
, return);
399 snd_assert(emu
!= NULL
, return);
400 snd_assert(emu
->ops
.terminate
!= NULL
, return);
402 terminate_note1(emu
, note
, chan
, 1);
407 * Terminate all the notes
410 snd_emux_terminate_all(snd_emux_t
*emu
)
413 snd_emux_voice_t
*vp
;
416 spin_lock_irqsave(&emu
->voice_lock
, flags
);
417 for (i
= 0; i
< emu
->max_voices
; i
++) {
418 vp
= &emu
->voices
[i
];
419 if (STATE_IS_PLAYING(vp
->state
))
420 terminate_voice(emu
, vp
, 0);
421 if (vp
->state
== SNDRV_EMUX_ST_OFF
) {
422 if (emu
->ops
.free_voice
)
423 emu
->ops
.free_voice(vp
);
425 emu
->ops
.reset(emu
, i
);
429 /* initialize allocation time */
431 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
436 * Terminate all voices associated with the given port
439 snd_emux_sounds_off_all(snd_emux_port_t
*port
)
443 snd_emux_voice_t
*vp
;
446 snd_assert(port
!= NULL
, return);
448 snd_assert(emu
!= NULL
, return);
449 snd_assert(emu
->ops
.terminate
!= NULL
, return);
451 spin_lock_irqsave(&emu
->voice_lock
, flags
);
452 for (i
= 0; i
< emu
->max_voices
; i
++) {
453 vp
= &emu
->voices
[i
];
454 if (STATE_IS_PLAYING(vp
->state
) &&
456 terminate_voice(emu
, vp
, 0);
457 if (vp
->state
== SNDRV_EMUX_ST_OFF
) {
458 if (emu
->ops
.free_voice
)
459 emu
->ops
.free_voice(vp
);
461 emu
->ops
.reset(emu
, i
);
464 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
469 * Terminate all voices that have the same exclusive class. This
470 * is mainly for drums.
473 exclusive_note_off(snd_emux_t
*emu
, snd_emux_port_t
*port
, int exclass
)
475 snd_emux_voice_t
*vp
;
479 spin_lock_irqsave(&emu
->voice_lock
, flags
);
480 for (i
= 0; i
< emu
->max_voices
; i
++) {
481 vp
= &emu
->voices
[i
];
482 if (STATE_IS_PLAYING(vp
->state
) && vp
->port
== port
&&
483 vp
->reg
.exclusiveClass
== exclass
) {
484 terminate_voice(emu
, vp
, 0);
487 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
492 * if free flag is true, call free_voice after termination
495 terminate_voice(snd_emux_t
*emu
, snd_emux_voice_t
*vp
, int free
)
497 emu
->ops
.terminate(vp
);
498 vp
->time
= emu
->use_time
++;
503 vp
->state
= SNDRV_EMUX_ST_OFF
;
504 if (free
&& emu
->ops
.free_voice
)
505 emu
->ops
.free_voice(vp
);
513 update_voice(snd_emux_t
*emu
, snd_emux_voice_t
*vp
, int update
)
515 if (!STATE_IS_PLAYING(vp
->state
))
518 if (vp
->chan
== NULL
|| vp
->port
== NULL
)
520 if (update
& SNDRV_EMUX_UPDATE_VOLUME
)
522 if (update
& SNDRV_EMUX_UPDATE_PITCH
)
524 if (update
& SNDRV_EMUX_UPDATE_PAN
) {
525 if (! calc_pan(vp
) && (update
== SNDRV_EMUX_UPDATE_PAN
))
528 emu
->ops
.update(vp
, update
);
533 /* table for volume target calculation */
534 static unsigned short voltarget
[16] = {
535 0xEAC0, 0xE0C8, 0xD740, 0xCE20, 0xC560, 0xBD08, 0xB500, 0xAD58,
536 0xA5F8, 0x9EF0, 0x9830, 0x91C0, 0x8B90, 0x85A8, 0x8000, 0x7A90
540 #define LO_BYTE(v) ((v) & 0xff)
541 #define HI_BYTE(v) (((v) >> 8) & 0xff)
544 * Sets up the voice structure by calculating some values that
545 * will be needed later.
548 setup_voice(snd_emux_voice_t
*vp
)
550 soundfont_voice_parm_t
*parm
;
553 /* copy the original register values */
554 vp
->reg
= vp
->zone
->v
;
556 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
557 snd_emux_setup_effect(vp
);
569 parm
= &vp
->reg
.parm
;
571 /* compute filter target and correct modulation parameters */
572 if (LO_BYTE(parm
->modatkhld
) >= 0x80 && parm
->moddelay
>= 0x8000) {
573 parm
->moddelay
= 0xbfff;
574 pitch
= (HI_BYTE(parm
->pefe
) << 4) + vp
->apitch
;
577 /* calculate filter target */
578 vp
->ftarget
= parm
->cutoff
+ LO_BYTE(parm
->pefe
);
579 LIMITVALUE(vp
->ftarget
, 0, 255);
582 vp
->ftarget
= parm
->cutoff
;
587 /* compute pitch target */
588 if (pitch
!= 0xffff) {
589 vp
->ptarget
= 1 << (pitch
>> 12);
590 if (pitch
& 0x800) vp
->ptarget
+= (vp
->ptarget
*0x102e)/0x2710;
591 if (pitch
& 0x400) vp
->ptarget
+= (vp
->ptarget
*0x764)/0x2710;
592 if (pitch
& 0x200) vp
->ptarget
+= (vp
->ptarget
*0x389)/0x2710;
593 vp
->ptarget
+= (vp
->ptarget
>> 1);
594 if (vp
->ptarget
> 0xffff) vp
->ptarget
= 0xffff;
596 vp
->ptarget
= 0xffff;
598 if (LO_BYTE(parm
->modatkhld
) >= 0x80) {
599 parm
->modatkhld
&= ~0xff;
600 parm
->modatkhld
|= 0x7f;
603 /* compute volume target and correct volume parameters */
605 #if 0 /* FIXME: this leads to some clicks.. */
606 if (LO_BYTE(parm
->volatkhld
) >= 0x80 && parm
->voldelay
>= 0x8000) {
607 parm
->voldelay
= 0xbfff;
608 vp
->vtarget
= voltarget
[vp
->avol
% 0x10] >> (vp
->avol
>> 4);
612 if (LO_BYTE(parm
->volatkhld
) >= 0x80) {
613 parm
->volatkhld
&= ~0xff;
614 parm
->volatkhld
|= 0x7f;
619 * calculate pitch parameter
621 static unsigned char pan_volumes
[256] = {
622 0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x14,0x17,0x1a,0x1d,0x20,0x22,0x25,0x28,0x2a,
623 0x2d,0x30,0x32,0x35,0x37,0x3a,0x3c,0x3f,0x41,0x44,0x46,0x49,0x4b,0x4d,0x50,0x52,
624 0x54,0x57,0x59,0x5b,0x5d,0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6f,0x71,0x73,0x75,
625 0x77,0x79,0x7b,0x7c,0x7e,0x80,0x82,0x84,0x86,0x88,0x89,0x8b,0x8d,0x8f,0x90,0x92,
626 0x94,0x96,0x97,0x99,0x9a,0x9c,0x9e,0x9f,0xa1,0xa2,0xa4,0xa5,0xa7,0xa8,0xaa,0xab,
627 0xad,0xae,0xaf,0xb1,0xb2,0xb3,0xb5,0xb6,0xb7,0xb9,0xba,0xbb,0xbc,0xbe,0xbf,0xc0,
628 0xc1,0xc2,0xc3,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,
629 0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdc,0xdd,0xde,0xdf,
630 0xdf,0xe0,0xe1,0xe2,0xe2,0xe3,0xe4,0xe4,0xe5,0xe6,0xe6,0xe7,0xe8,0xe8,0xe9,0xe9,
631 0xea,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf1,0xf1,0xf1,
632 0xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,0xf7,
633 0xf7,0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,
634 0xfb,0xfb,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
635 0xfd,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
636 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
637 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
641 calc_pan(snd_emux_voice_t
*vp
)
643 snd_midi_channel_t
*chan
= vp
->chan
;
646 /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */
647 if (vp
->reg
.fixpan
> 0) /* 0-127 */
648 pan
= 255 - (int)vp
->reg
.fixpan
* 2;
650 pan
= chan
->control
[MIDI_CTL_MSB_PAN
] - 64;
651 if (vp
->reg
.pan
>= 0) /* 0-127 */
652 pan
+= vp
->reg
.pan
- 64;
653 pan
= 127 - (int)pan
* 2;
655 LIMITVALUE(pan
, 0, 255);
657 if (vp
->emu
->linear_panning
) {
658 /* assuming linear volume */
659 if (pan
!= vp
->apan
) {
664 vp
->aaux
= (-pan
) & 0xff;
669 /* using volume table */
670 if (vp
->apan
!= (int)pan_volumes
[pan
]) {
671 vp
->apan
= pan_volumes
[pan
];
672 vp
->aaux
= pan_volumes
[255 - pan
];
681 * calculate volume attenuation
683 * Voice volume is controlled by volume attenuation parameter.
684 * So volume becomes maximum when avol is 0 (no attenuation), and
685 * minimum when 255 (-96dB or silence).
688 /* tables for volume->attenuation calculation */
689 static unsigned char voltab1
[128] = {
690 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
691 0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22,
692 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
693 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14,
694 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10,
695 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d,
696 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b,
697 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,
698 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,
699 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,
700 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02,
701 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
702 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
705 static unsigned char voltab2
[128] = {
706 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a,
707 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21,
708 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a,
709 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15,
710 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10,
711 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d,
712 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a,
713 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
714 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
715 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
716 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
717 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
718 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
721 static unsigned char expressiontab
[128] = {
722 0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42,
723 0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30,
724 0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,
725 0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e,
726 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18,
727 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13,
728 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f,
729 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c,
730 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09,
731 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
732 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
733 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
734 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
738 * Magic to calculate the volume (actually attenuation) from all the
739 * voice and channels parameters.
742 calc_volume(snd_emux_voice_t
*vp
)
745 int main_vol
, expression_vol
, master_vol
;
746 snd_midi_channel_t
*chan
= vp
->chan
;
747 snd_emux_port_t
*port
= vp
->port
;
749 expression_vol
= chan
->control
[MIDI_CTL_MSB_EXPRESSION
];
750 LIMITMAX(vp
->velocity
, 127);
751 LIMITVALUE(expression_vol
, 0, 127);
752 if (port
->port_mode
== SNDRV_EMUX_PORT_MODE_OSS_SYNTH
) {
754 main_vol
= chan
->control
[MIDI_CTL_MSB_MAIN_VOLUME
];
755 vol
= (vp
->velocity
* main_vol
* expression_vol
) / (127*127);
756 vol
= vol
* vp
->reg
.amplitude
/ 127;
758 LIMITVALUE(vol
, 0, 127);
760 /* calc to attenuation */
761 vol
= snd_sf_vol_table
[vol
];
764 main_vol
= chan
->control
[MIDI_CTL_MSB_MAIN_VOLUME
] * vp
->reg
.amplitude
/ 127;
765 LIMITVALUE(main_vol
, 0, 127);
767 vol
= voltab1
[main_vol
] + voltab2
[vp
->velocity
];
769 vol
+= vp
->reg
.attenuation
;
770 vol
+= ((0x100 - vol
) * expressiontab
[expression_vol
])/128;
773 master_vol
= port
->chset
.gs_master_volume
;
774 LIMITVALUE(master_vol
, 0, 127);
775 vol
+= snd_sf_vol_table
[master_vol
];
776 vol
+= port
->volume_atten
;
778 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
780 snd_emux_effect_table_t
*fx
= chan
->private;
781 vol
+= fx
->val
[EMUX_FX_ATTEN
];
785 LIMITVALUE(vol
, 0, 255);
787 return 0; /* value unchanged */
790 if (!SF_IS_DRUM_BANK(get_bank(port
, chan
))
791 && LO_BYTE(vp
->reg
.parm
.volatkhld
) < 0x7d) {
793 if (vp
->velocity
< 70)
796 atten
= vp
->velocity
;
797 vp
->acutoff
= (atten
* vp
->reg
.parm
.cutoff
+ 0xa0) >> 7;
799 vp
->acutoff
= vp
->reg
.parm
.cutoff
;
802 return 1; /* value changed */
806 * calculate pitch offset
808 * 0xE000 is no pitch offset at 44100Hz sample.
809 * Every 4096 is one octave.
813 calc_pitch(snd_emux_voice_t
*vp
)
815 snd_midi_channel_t
*chan
= vp
->chan
;
818 /* calculate offset */
819 if (vp
->reg
.fixkey
>= 0) {
820 offset
= (vp
->reg
.fixkey
- vp
->reg
.root
) * 4096 / 12;
822 offset
= (vp
->note
- vp
->reg
.root
) * 4096 / 12;
824 offset
= (offset
* vp
->reg
.scaleTuning
) / 100;
825 offset
+= vp
->reg
.tune
* 4096 / 1200;
826 if (chan
->midi_pitchbend
!= 0) {
827 /* (128 * 8192: 1 semitone) ==> (4096: 12 semitones) */
828 offset
+= chan
->midi_pitchbend
* chan
->gm_rpn_pitch_bend_range
/ 3072;
832 * coarse = -8192 to 8192 (100 cent per 128)
833 * fine = -8192 to 8192 (max=100cent)
835 /* 4096 = 1200 cents in emu8000 parameter */
836 offset
+= chan
->gm_rpn_coarse_tuning
* 4096 / (12 * 128);
837 offset
+= chan
->gm_rpn_fine_tuning
/ 24;
839 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
840 /* add initial pitch correction */
842 snd_emux_effect_table_t
*fx
= chan
->private;
843 if (fx
->flag
[EMUX_FX_INIT_PITCH
])
844 offset
+= fx
->val
[EMUX_FX_INIT_PITCH
];
848 /* 0xe000: root pitch */
849 offset
+= 0xe000 + vp
->reg
.rate_offset
;
850 offset
+= vp
->emu
->pitch_shift
;
851 LIMITVALUE(offset
, 0, 0xffff);
852 if (offset
== vp
->apitch
)
853 return 0; /* unchanged */
855 return 1; /* value changed */
859 * Get the bank number assigned to the channel
862 get_bank(snd_emux_port_t
*port
, snd_midi_channel_t
*chan
)
866 switch (port
->chset
.midi_mode
) {
867 case SNDRV_MIDI_MODE_XG
:
868 val
= chan
->control
[MIDI_CTL_MSB_BANK
];
870 return 128; /* return drum bank */
871 return chan
->control
[MIDI_CTL_LSB_BANK
];
873 case SNDRV_MIDI_MODE_GS
:
874 if (chan
->drum_channel
)
876 /* ignore LSB (bank map) */
877 return chan
->control
[MIDI_CTL_MSB_BANK
];
880 if (chan
->drum_channel
)
882 return chan
->control
[MIDI_CTL_MSB_BANK
];
887 /* Look for the zones matching with the given note and velocity.
888 * The resultant zones are stored on table.
891 get_zone(snd_emux_t
*emu
, snd_emux_port_t
*port
,
892 int *notep
, int vel
, snd_midi_channel_t
*chan
, snd_sf_zone_t
**table
)
894 int preset
, bank
, def_preset
, def_bank
;
896 bank
= get_bank(port
, chan
);
897 preset
= chan
->midi_program
;
899 if (SF_IS_DRUM_BANK(bank
)) {
900 def_preset
= port
->ctrls
[EMUX_MD_DEF_DRUM
];
904 def_bank
= port
->ctrls
[EMUX_MD_DEF_BANK
];
907 return snd_soundfont_search_zone(emu
->sflist
, notep
, vel
, preset
, bank
,
908 def_preset
, def_bank
,
909 table
, SNDRV_EMUX_MAX_MULTI_VOICES
);
915 snd_emux_init_voices(snd_emux_t
*emu
)
917 snd_emux_voice_t
*vp
;
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
;
932 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
937 void snd_emux_lock_voice(snd_emux_t
*emu
, int voice
)
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
;
945 snd_printk("invalid voice for lock %d (state = %x)\n",
946 voice
, emu
->voices
[voice
].state
);
947 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);
952 void snd_emux_unlock_voice(snd_emux_t
*emu
, int voice
)
956 spin_lock_irqsave(&emu
->voice_lock
, flags
);
957 if (emu
->voices
[voice
].state
== SNDRV_EMUX_ST_LOCKED
)
958 emu
->voices
[voice
].state
= SNDRV_EMUX_ST_OFF
;
960 snd_printk("invalid voice for unlock %d (state = %x)\n",
961 voice
, emu
->voices
[voice
].state
);
962 spin_unlock_irqrestore(&emu
->voice_lock
, flags
);