blob: 24705d15ebd80e89b58e9c7c66885e2729490f2c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Takashi Iwai03da3122005-11-17 14:24:47 +010039static 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
54
55/*
56 * Start a note.
57 */
58void
Takashi Iwai03da3122005-11-17 14:24:47 +010059snd_emux_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060{
Takashi Iwai03da3122005-11-17 14:24:47 +010061 struct snd_emux *emu;
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 int i, key, nvoices;
Takashi Iwai03da3122005-11-17 14:24:47 +010063 struct snd_emux_voice *vp;
64 struct snd_sf_zone *table[SNDRV_EMUX_MAX_MULTI_VOICES];
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 unsigned long flags;
Takashi Iwai03da3122005-11-17 14:24:47 +010066 struct snd_emux_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
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++) {
Takashi Iwai03da3122005-11-17 14:24:47 +010083 struct snd_sf_zone *zp = table[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 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 */
Takashi Iwai03da3122005-11-17 14:24:47 +0100145 struct snd_emux_effect_table *fx = chan->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 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
Takashi Iwai03da3122005-11-17 14:24:47 +0100158snd_emux_note_off(void *p, int note, int vel, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159{
160 int ch;
Takashi Iwai03da3122005-11-17 14:24:47 +0100161 struct snd_emux *emu;
162 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 unsigned long flags;
Takashi Iwai03da3122005-11-17 14:24:47 +0100164 struct snd_emux_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165
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) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 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{
Takashi Iwai03da3122005-11-17 14:24:47 +0100206 struct snd_emux *emu = (struct snd_emux *) data;
207 struct snd_emux_voice *vp;
Takashi Iwaib32425a2005-11-18 18:52:14 +0100208 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 int ch, do_again = 0;
210
Takashi Iwaib32425a2005-11-18 18:52:14 +0100211 spin_lock_irqsave(&emu->voice_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 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;
Takashi Iwaib32425a2005-11-18 18:52:14 +0100229 spin_unlock_irqrestore(&emu->voice_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230}
231
232/*
233 * key pressure change
234 */
235void
Takashi Iwai03da3122005-11-17 14:24:47 +0100236snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237{
238 int ch;
Takashi Iwai03da3122005-11-17 14:24:47 +0100239 struct snd_emux *emu;
240 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 unsigned long flags;
Takashi Iwai03da3122005-11-17 14:24:47 +0100242 struct snd_emux_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243
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
Takashi Iwai03da3122005-11-17 14:24:47 +0100268snd_emux_update_channel(struct snd_emux_port *port, struct snd_midi_channel *chan, int update)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269{
Takashi Iwai03da3122005-11-17 14:24:47 +0100270 struct snd_emux *emu;
271 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 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
Takashi Iwai03da3122005-11-17 14:24:47 +0100295snd_emux_update_port(struct snd_emux_port *port, int update)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296{
Takashi Iwai03da3122005-11-17 14:24:47 +0100297 struct snd_emux *emu;
298 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 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
Takashi Iwai03da3122005-11-17 14:24:47 +0100324snd_emux_control(void *p, int type, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325{
Takashi Iwai03da3122005-11-17 14:24:47 +0100326 struct snd_emux_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
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
Takashi Iwai03da3122005-11-17 14:24:47 +0100372terminate_note1(struct snd_emux *emu, int note, struct snd_midi_channel *chan, int free)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
374 int i;
Takashi Iwai03da3122005-11-17 14:24:47 +0100375 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 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
Takashi Iwai03da3122005-11-17 14:24:47 +0100393snd_emux_terminate_note(void *p, int note, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394{
Takashi Iwai03da3122005-11-17 14:24:47 +0100395 struct snd_emux *emu;
396 struct snd_emux_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
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
Takashi Iwai03da3122005-11-17 14:24:47 +0100413snd_emux_terminate_all(struct snd_emux *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414{
415 int i;
Takashi Iwai03da3122005-11-17 14:24:47 +0100416 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 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
437
438/*
439 * Terminate all voices associated with the given port
440 */
441void
Takashi Iwai03da3122005-11-17 14:24:47 +0100442snd_emux_sounds_off_all(struct snd_emux_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443{
444 int i;
Takashi Iwai03da3122005-11-17 14:24:47 +0100445 struct snd_emux *emu;
446 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 unsigned long flags;
448
449 snd_assert(port != NULL, return);
450 emu = port->emu;
451 snd_assert(emu != NULL, return);
452 snd_assert(emu->ops.terminate != NULL, return);
453
454 spin_lock_irqsave(&emu->voice_lock, flags);
455 for (i = 0; i < emu->max_voices; i++) {
456 vp = &emu->voices[i];
457 if (STATE_IS_PLAYING(vp->state) &&
458 vp->port == port)
459 terminate_voice(emu, vp, 0);
460 if (vp->state == SNDRV_EMUX_ST_OFF) {
461 if (emu->ops.free_voice)
462 emu->ops.free_voice(vp);
463 if (emu->ops.reset)
464 emu->ops.reset(emu, i);
465 }
466 }
467 spin_unlock_irqrestore(&emu->voice_lock, flags);
468}
469
470
471/*
472 * Terminate all voices that have the same exclusive class. This
473 * is mainly for drums.
474 */
475static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100476exclusive_note_off(struct snd_emux *emu, struct snd_emux_port *port, int exclass)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477{
Takashi Iwai03da3122005-11-17 14:24:47 +0100478 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 int i;
480 unsigned long flags;
481
482 spin_lock_irqsave(&emu->voice_lock, flags);
483 for (i = 0; i < emu->max_voices; i++) {
484 vp = &emu->voices[i];
485 if (STATE_IS_PLAYING(vp->state) && vp->port == port &&
486 vp->reg.exclusiveClass == exclass) {
487 terminate_voice(emu, vp, 0);
488 }
489 }
490 spin_unlock_irqrestore(&emu->voice_lock, flags);
491}
492
493/*
494 * terminate a voice
495 * if free flag is true, call free_voice after termination
496 */
497static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100498terminate_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int free)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499{
500 emu->ops.terminate(vp);
501 vp->time = emu->use_time++;
502 vp->chan = NULL;
503 vp->port = NULL;
504 vp->zone = NULL;
505 vp->block = NULL;
506 vp->state = SNDRV_EMUX_ST_OFF;
507 if (free && emu->ops.free_voice)
508 emu->ops.free_voice(vp);
509}
510
511
512/*
513 * Modulate the voice
514 */
515static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100516update_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int update)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517{
518 if (!STATE_IS_PLAYING(vp->state))
519 return;
520
521 if (vp->chan == NULL || vp->port == NULL)
522 return;
523 if (update & SNDRV_EMUX_UPDATE_VOLUME)
524 calc_volume(vp);
525 if (update & SNDRV_EMUX_UPDATE_PITCH)
526 calc_pitch(vp);
527 if (update & SNDRV_EMUX_UPDATE_PAN) {
528 if (! calc_pan(vp) && (update == SNDRV_EMUX_UPDATE_PAN))
529 return;
530 }
531 emu->ops.update(vp, update);
532}
533
534
535#if 0 // not used
536/* table for volume target calculation */
537static unsigned short voltarget[16] = {
538 0xEAC0, 0xE0C8, 0xD740, 0xCE20, 0xC560, 0xBD08, 0xB500, 0xAD58,
539 0xA5F8, 0x9EF0, 0x9830, 0x91C0, 0x8B90, 0x85A8, 0x8000, 0x7A90
540};
541#endif
542
543#define LO_BYTE(v) ((v) & 0xff)
544#define HI_BYTE(v) (((v) >> 8) & 0xff)
545
546/*
547 * Sets up the voice structure by calculating some values that
548 * will be needed later.
549 */
550static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100551setup_voice(struct snd_emux_voice *vp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552{
Takashi Iwai03da3122005-11-17 14:24:47 +0100553 struct soundfont_voice_parm *parm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 int pitch;
555
556 /* copy the original register values */
557 vp->reg = vp->zone->v;
558
559#ifdef SNDRV_EMUX_USE_RAW_EFFECT
560 snd_emux_setup_effect(vp);
561#endif
562
563 /* reset status */
564 vp->apan = -1;
565 vp->avol = -1;
566 vp->apitch = -1;
567
568 calc_volume(vp);
569 calc_pitch(vp);
570 calc_pan(vp);
571
572 parm = &vp->reg.parm;
573
574 /* compute filter target and correct modulation parameters */
575 if (LO_BYTE(parm->modatkhld) >= 0x80 && parm->moddelay >= 0x8000) {
576 parm->moddelay = 0xbfff;
577 pitch = (HI_BYTE(parm->pefe) << 4) + vp->apitch;
578 if (pitch > 0xffff)
579 pitch = 0xffff;
580 /* calculate filter target */
581 vp->ftarget = parm->cutoff + LO_BYTE(parm->pefe);
582 LIMITVALUE(vp->ftarget, 0, 255);
583 vp->ftarget <<= 8;
584 } else {
585 vp->ftarget = parm->cutoff;
586 vp->ftarget <<= 8;
587 pitch = vp->apitch;
588 }
589
590 /* compute pitch target */
591 if (pitch != 0xffff) {
592 vp->ptarget = 1 << (pitch >> 12);
593 if (pitch & 0x800) vp->ptarget += (vp->ptarget*0x102e)/0x2710;
594 if (pitch & 0x400) vp->ptarget += (vp->ptarget*0x764)/0x2710;
595 if (pitch & 0x200) vp->ptarget += (vp->ptarget*0x389)/0x2710;
596 vp->ptarget += (vp->ptarget >> 1);
597 if (vp->ptarget > 0xffff) vp->ptarget = 0xffff;
598 } else
599 vp->ptarget = 0xffff;
600
601 if (LO_BYTE(parm->modatkhld) >= 0x80) {
602 parm->modatkhld &= ~0xff;
603 parm->modatkhld |= 0x7f;
604 }
605
606 /* compute volume target and correct volume parameters */
607 vp->vtarget = 0;
608#if 0 /* FIXME: this leads to some clicks.. */
609 if (LO_BYTE(parm->volatkhld) >= 0x80 && parm->voldelay >= 0x8000) {
610 parm->voldelay = 0xbfff;
611 vp->vtarget = voltarget[vp->avol % 0x10] >> (vp->avol >> 4);
612 }
613#endif
614
615 if (LO_BYTE(parm->volatkhld) >= 0x80) {
616 parm->volatkhld &= ~0xff;
617 parm->volatkhld |= 0x7f;
618 }
619}
620
621/*
622 * calculate pitch parameter
623 */
624static unsigned char pan_volumes[256] = {
6250x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x14,0x17,0x1a,0x1d,0x20,0x22,0x25,0x28,0x2a,
6260x2d,0x30,0x32,0x35,0x37,0x3a,0x3c,0x3f,0x41,0x44,0x46,0x49,0x4b,0x4d,0x50,0x52,
6270x54,0x57,0x59,0x5b,0x5d,0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6f,0x71,0x73,0x75,
6280x77,0x79,0x7b,0x7c,0x7e,0x80,0x82,0x84,0x86,0x88,0x89,0x8b,0x8d,0x8f,0x90,0x92,
6290x94,0x96,0x97,0x99,0x9a,0x9c,0x9e,0x9f,0xa1,0xa2,0xa4,0xa5,0xa7,0xa8,0xaa,0xab,
6300xad,0xae,0xaf,0xb1,0xb2,0xb3,0xb5,0xb6,0xb7,0xb9,0xba,0xbb,0xbc,0xbe,0xbf,0xc0,
6310xc1,0xc2,0xc3,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,
6320xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdc,0xdd,0xde,0xdf,
6330xdf,0xe0,0xe1,0xe2,0xe2,0xe3,0xe4,0xe4,0xe5,0xe6,0xe6,0xe7,0xe8,0xe8,0xe9,0xe9,
6340xea,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf1,0xf1,0xf1,
6350xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,0xf7,
6360xf7,0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,
6370xfb,0xfb,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
6380xfd,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
6390xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
6400xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
641};
642
643static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100644calc_pan(struct snd_emux_voice *vp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
Takashi Iwai03da3122005-11-17 14:24:47 +0100646 struct snd_midi_channel *chan = vp->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 int pan;
648
649 /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */
650 if (vp->reg.fixpan > 0) /* 0-127 */
651 pan = 255 - (int)vp->reg.fixpan * 2;
652 else {
653 pan = chan->control[MIDI_CTL_MSB_PAN] - 64;
654 if (vp->reg.pan >= 0) /* 0-127 */
655 pan += vp->reg.pan - 64;
656 pan = 127 - (int)pan * 2;
657 }
658 LIMITVALUE(pan, 0, 255);
659
660 if (vp->emu->linear_panning) {
661 /* assuming linear volume */
662 if (pan != vp->apan) {
663 vp->apan = pan;
664 if (pan == 0)
665 vp->aaux = 0xff;
666 else
667 vp->aaux = (-pan) & 0xff;
668 return 1;
669 } else
670 return 0;
671 } else {
672 /* using volume table */
673 if (vp->apan != (int)pan_volumes[pan]) {
674 vp->apan = pan_volumes[pan];
675 vp->aaux = pan_volumes[255 - pan];
676 return 1;
677 }
678 return 0;
679 }
680}
681
682
683/*
684 * calculate volume attenuation
685 *
686 * Voice volume is controlled by volume attenuation parameter.
687 * So volume becomes maximum when avol is 0 (no attenuation), and
688 * minimum when 255 (-96dB or silence).
689 */
690
691/* tables for volume->attenuation calculation */
692static unsigned char voltab1[128] = {
693 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
694 0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22,
695 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
696 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14,
697 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10,
698 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d,
699 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b,
700 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,
701 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,
702 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,
703 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02,
704 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
705 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
706};
707
708static unsigned char voltab2[128] = {
709 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a,
710 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21,
711 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a,
712 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15,
713 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10,
714 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d,
715 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a,
716 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
717 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
718 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
719 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
720 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
721 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
722};
723
724static unsigned char expressiontab[128] = {
725 0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42,
726 0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30,
727 0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,
728 0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e,
729 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18,
730 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13,
731 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f,
732 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c,
733 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09,
734 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
735 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
736 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
737 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
738};
739
740/*
741 * Magic to calculate the volume (actually attenuation) from all the
742 * voice and channels parameters.
743 */
744static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100745calc_volume(struct snd_emux_voice *vp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746{
747 int vol;
748 int main_vol, expression_vol, master_vol;
Takashi Iwai03da3122005-11-17 14:24:47 +0100749 struct snd_midi_channel *chan = vp->chan;
750 struct snd_emux_port *port = vp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
752 expression_vol = chan->control[MIDI_CTL_MSB_EXPRESSION];
753 LIMITMAX(vp->velocity, 127);
754 LIMITVALUE(expression_vol, 0, 127);
755 if (port->port_mode == SNDRV_EMUX_PORT_MODE_OSS_SYNTH) {
756 /* 0 - 127 */
757 main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME];
758 vol = (vp->velocity * main_vol * expression_vol) / (127*127);
759 vol = vol * vp->reg.amplitude / 127;
760
761 LIMITVALUE(vol, 0, 127);
762
763 /* calc to attenuation */
764 vol = snd_sf_vol_table[vol];
765
766 } else {
767 main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME] * vp->reg.amplitude / 127;
768 LIMITVALUE(main_vol, 0, 127);
769
770 vol = voltab1[main_vol] + voltab2[vp->velocity];
771 vol = (vol * 8) / 3;
772 vol += vp->reg.attenuation;
773 vol += ((0x100 - vol) * expressiontab[expression_vol])/128;
774 }
775
776 master_vol = port->chset.gs_master_volume;
777 LIMITVALUE(master_vol, 0, 127);
778 vol += snd_sf_vol_table[master_vol];
779 vol += port->volume_atten;
780
781#ifdef SNDRV_EMUX_USE_RAW_EFFECT
782 if (chan->private) {
Takashi Iwai03da3122005-11-17 14:24:47 +0100783 struct snd_emux_effect_table *fx = chan->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 vol += fx->val[EMUX_FX_ATTEN];
785 }
786#endif
787
788 LIMITVALUE(vol, 0, 255);
789 if (vp->avol == vol)
790 return 0; /* value unchanged */
791
792 vp->avol = vol;
793 if (!SF_IS_DRUM_BANK(get_bank(port, chan))
794 && LO_BYTE(vp->reg.parm.volatkhld) < 0x7d) {
795 int atten;
796 if (vp->velocity < 70)
797 atten = 70;
798 else
799 atten = vp->velocity;
800 vp->acutoff = (atten * vp->reg.parm.cutoff + 0xa0) >> 7;
801 } else {
802 vp->acutoff = vp->reg.parm.cutoff;
803 }
804
805 return 1; /* value changed */
806}
807
808/*
809 * calculate pitch offset
810 *
811 * 0xE000 is no pitch offset at 44100Hz sample.
812 * Every 4096 is one octave.
813 */
814
815static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100816calc_pitch(struct snd_emux_voice *vp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817{
Takashi Iwai03da3122005-11-17 14:24:47 +0100818 struct snd_midi_channel *chan = vp->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 int offset;
820
821 /* calculate offset */
822 if (vp->reg.fixkey >= 0) {
823 offset = (vp->reg.fixkey - vp->reg.root) * 4096 / 12;
824 } else {
825 offset = (vp->note - vp->reg.root) * 4096 / 12;
826 }
827 offset = (offset * vp->reg.scaleTuning) / 100;
828 offset += vp->reg.tune * 4096 / 1200;
829 if (chan->midi_pitchbend != 0) {
830 /* (128 * 8192: 1 semitone) ==> (4096: 12 semitones) */
831 offset += chan->midi_pitchbend * chan->gm_rpn_pitch_bend_range / 3072;
832 }
833
834 /* tuning via RPN:
835 * coarse = -8192 to 8192 (100 cent per 128)
836 * fine = -8192 to 8192 (max=100cent)
837 */
838 /* 4096 = 1200 cents in emu8000 parameter */
839 offset += chan->gm_rpn_coarse_tuning * 4096 / (12 * 128);
840 offset += chan->gm_rpn_fine_tuning / 24;
841
842#ifdef SNDRV_EMUX_USE_RAW_EFFECT
843 /* add initial pitch correction */
844 if (chan->private) {
Takashi Iwai03da3122005-11-17 14:24:47 +0100845 struct snd_emux_effect_table *fx = chan->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 if (fx->flag[EMUX_FX_INIT_PITCH])
847 offset += fx->val[EMUX_FX_INIT_PITCH];
848 }
849#endif
850
851 /* 0xe000: root pitch */
852 offset += 0xe000 + vp->reg.rate_offset;
853 offset += vp->emu->pitch_shift;
854 LIMITVALUE(offset, 0, 0xffff);
855 if (offset == vp->apitch)
856 return 0; /* unchanged */
857 vp->apitch = offset;
858 return 1; /* value changed */
859}
860
861/*
862 * Get the bank number assigned to the channel
863 */
864static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100865get_bank(struct snd_emux_port *port, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866{
867 int val;
868
869 switch (port->chset.midi_mode) {
870 case SNDRV_MIDI_MODE_XG:
871 val = chan->control[MIDI_CTL_MSB_BANK];
872 if (val == 127)
873 return 128; /* return drum bank */
874 return chan->control[MIDI_CTL_LSB_BANK];
875
876 case SNDRV_MIDI_MODE_GS:
877 if (chan->drum_channel)
878 return 128;
879 /* ignore LSB (bank map) */
880 return chan->control[MIDI_CTL_MSB_BANK];
881
882 default:
883 if (chan->drum_channel)
884 return 128;
885 return chan->control[MIDI_CTL_MSB_BANK];
886 }
887}
888
889
890/* Look for the zones matching with the given note and velocity.
891 * The resultant zones are stored on table.
892 */
893static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100894get_zone(struct snd_emux *emu, struct snd_emux_port *port,
895 int *notep, int vel, struct snd_midi_channel *chan,
896 struct snd_sf_zone **table)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897{
898 int preset, bank, def_preset, def_bank;
899
900 bank = get_bank(port, chan);
901 preset = chan->midi_program;
902
903 if (SF_IS_DRUM_BANK(bank)) {
904 def_preset = port->ctrls[EMUX_MD_DEF_DRUM];
905 def_bank = bank;
906 } else {
907 def_preset = preset;
908 def_bank = port->ctrls[EMUX_MD_DEF_BANK];
909 }
910
911 return snd_soundfont_search_zone(emu->sflist, notep, vel, preset, bank,
912 def_preset, def_bank,
913 table, SNDRV_EMUX_MAX_MULTI_VOICES);
914}
915
916/*
917 */
918void
Takashi Iwai03da3122005-11-17 14:24:47 +0100919snd_emux_init_voices(struct snd_emux *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920{
Takashi Iwai03da3122005-11-17 14:24:47 +0100921 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 int i;
923 unsigned long flags;
924
925 spin_lock_irqsave(&emu->voice_lock, flags);
926 for (i = 0; i < emu->max_voices; i++) {
927 vp = &emu->voices[i];
928 vp->ch = -1; /* not used */
929 vp->state = SNDRV_EMUX_ST_OFF;
930 vp->chan = NULL;
931 vp->port = NULL;
932 vp->time = 0;
933 vp->emu = emu;
934 vp->hw = emu->hw;
935 }
936 spin_unlock_irqrestore(&emu->voice_lock, flags);
937}
938
939/*
940 */
Takashi Iwai03da3122005-11-17 14:24:47 +0100941void snd_emux_lock_voice(struct snd_emux *emu, int voice)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942{
943 unsigned long flags;
944
945 spin_lock_irqsave(&emu->voice_lock, flags);
946 if (emu->voices[voice].state == SNDRV_EMUX_ST_OFF)
947 emu->voices[voice].state = SNDRV_EMUX_ST_LOCKED;
948 else
949 snd_printk("invalid voice for lock %d (state = %x)\n",
950 voice, emu->voices[voice].state);
951 spin_unlock_irqrestore(&emu->voice_lock, flags);
952}
953
954/*
955 */
Takashi Iwai03da3122005-11-17 14:24:47 +0100956void snd_emux_unlock_voice(struct snd_emux *emu, int voice)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957{
958 unsigned long flags;
959
960 spin_lock_irqsave(&emu->voice_lock, flags);
961 if (emu->voices[voice].state == SNDRV_EMUX_ST_LOCKED)
962 emu->voices[voice].state = SNDRV_EMUX_ST_OFF;
963 else
964 snd_printk("invalid voice for unlock %d (state = %x)\n",
965 voice, emu->voices[voice].state);
966 spin_unlock_irqrestore(&emu->voice_lock, flags);
967}