blob: c387a83a655e02b8f0d3aa7a125a8275e7b81714 [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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 int ch, do_again = 0;
209
210 spin_lock(&emu->voice_lock);
211 for (ch = 0; ch < emu->max_voices; ch++) {
212 vp = &emu->voices[ch];
213 if (vp->state == SNDRV_EMUX_ST_PENDING) {
214 if (vp->ontime == jiffies)
215 do_again++; /* release this at the next interrupt */
216 else {
217 emu->ops.release(vp);
218 vp->state = SNDRV_EMUX_ST_RELEASED;
219 }
220 }
221 }
222 if (do_again) {
223 emu->tlist.expires = jiffies + 1;
224 add_timer(&emu->tlist);
225 emu->timer_active = 1;
226 } else
227 emu->timer_active = 0;
228 spin_unlock(&emu->voice_lock);
229}
230
231/*
232 * key pressure change
233 */
234void
Takashi Iwai03da3122005-11-17 14:24:47 +0100235snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236{
237 int ch;
Takashi Iwai03da3122005-11-17 14:24:47 +0100238 struct snd_emux *emu;
239 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 unsigned long flags;
Takashi Iwai03da3122005-11-17 14:24:47 +0100241 struct snd_emux_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
243 port = p;
244 snd_assert(port != NULL && chan != NULL, return);
245
246 emu = port->emu;
247 snd_assert(emu != NULL, return);
248 snd_assert(emu->ops.update != NULL, return);
249
250 spin_lock_irqsave(&emu->voice_lock, flags);
251 for (ch = 0; ch < emu->max_voices; ch++) {
252 vp = &emu->voices[ch];
253 if (vp->state == SNDRV_EMUX_ST_ON &&
254 vp->chan == chan && vp->key == note) {
255 vp->velocity = vel;
256 update_voice(emu, vp, SNDRV_EMUX_UPDATE_VOLUME);
257 }
258 }
259 spin_unlock_irqrestore(&emu->voice_lock, flags);
260}
261
262
263/*
264 * Modulate the voices which belong to the channel
265 */
266void
Takashi Iwai03da3122005-11-17 14:24:47 +0100267snd_emux_update_channel(struct snd_emux_port *port, struct snd_midi_channel *chan, int update)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268{
Takashi Iwai03da3122005-11-17 14:24:47 +0100269 struct snd_emux *emu;
270 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 int i;
272 unsigned long flags;
273
274 if (! update)
275 return;
276
277 emu = port->emu;
278 snd_assert(emu != NULL, return);
279 snd_assert(emu->ops.update != NULL, return);
280
281 spin_lock_irqsave(&emu->voice_lock, flags);
282 for (i = 0; i < emu->max_voices; i++) {
283 vp = &emu->voices[i];
284 if (vp->chan == chan)
285 update_voice(emu, vp, update);
286 }
287 spin_unlock_irqrestore(&emu->voice_lock, flags);
288}
289
290/*
291 * Modulate all the voices which belong to the port.
292 */
293void
Takashi Iwai03da3122005-11-17 14:24:47 +0100294snd_emux_update_port(struct snd_emux_port *port, int update)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295{
Takashi Iwai03da3122005-11-17 14:24:47 +0100296 struct snd_emux *emu;
297 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 int i;
299 unsigned long flags;
300
301 if (! update)
302 return;
303
304 emu = port->emu;
305 snd_assert(emu != NULL, return);
306 snd_assert(emu->ops.update != NULL, return);
307
308 spin_lock_irqsave(&emu->voice_lock, flags);
309 for (i = 0; i < emu->max_voices; i++) {
310 vp = &emu->voices[i];
311 if (vp->port == port)
312 update_voice(emu, vp, update);
313 }
314 spin_unlock_irqrestore(&emu->voice_lock, flags);
315}
316
317
318/*
319 * Deal with a controler type event. This includes all types of
320 * control events, not just the midi controllers
321 */
322void
Takashi Iwai03da3122005-11-17 14:24:47 +0100323snd_emux_control(void *p, int type, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324{
Takashi Iwai03da3122005-11-17 14:24:47 +0100325 struct snd_emux_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
327 port = p;
328 snd_assert(port != NULL && chan != NULL, return);
329
330 switch (type) {
331 case MIDI_CTL_MSB_MAIN_VOLUME:
332 case MIDI_CTL_MSB_EXPRESSION:
333 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_VOLUME);
334 break;
335
336 case MIDI_CTL_MSB_PAN:
337 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PAN);
338 break;
339
340 case MIDI_CTL_SOFT_PEDAL:
341#ifdef SNDRV_EMUX_USE_RAW_EFFECT
342 /* FIXME: this is an emulation */
343 snd_emux_send_effect(port, chan, EMUX_FX_CUTOFF, -160,
344 EMUX_FX_FLAG_ADD);
345#endif
346 break;
347
348 case MIDI_CTL_PITCHBEND:
349 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PITCH);
350 break;
351
352 case MIDI_CTL_MSB_MODWHEEL:
353 case MIDI_CTL_CHAN_PRESSURE:
354 snd_emux_update_channel(port, chan,
355 SNDRV_EMUX_UPDATE_FMMOD |
356 SNDRV_EMUX_UPDATE_FM2FRQ2);
357 break;
358
359 }
360
361 if (port->chset.midi_mode == SNDRV_MIDI_MODE_XG) {
362 snd_emux_xg_control(port, chan, type);
363 }
364}
365
366
367/*
368 * terminate note - if free flag is true, free the terminated voice
369 */
370static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100371terminate_note1(struct snd_emux *emu, int note, struct snd_midi_channel *chan, int free)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372{
373 int i;
Takashi Iwai03da3122005-11-17 14:24:47 +0100374 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 unsigned long flags;
376
377 spin_lock_irqsave(&emu->voice_lock, flags);
378 for (i = 0; i < emu->max_voices; i++) {
379 vp = &emu->voices[i];
380 if (STATE_IS_PLAYING(vp->state) && vp->chan == chan &&
381 vp->key == note)
382 terminate_voice(emu, vp, free);
383 }
384 spin_unlock_irqrestore(&emu->voice_lock, flags);
385}
386
387
388/*
389 * terminate note - exported for midi emulation
390 */
391void
Takashi Iwai03da3122005-11-17 14:24:47 +0100392snd_emux_terminate_note(void *p, int note, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393{
Takashi Iwai03da3122005-11-17 14:24:47 +0100394 struct snd_emux *emu;
395 struct snd_emux_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
397 port = p;
398 snd_assert(port != NULL && chan != NULL, return);
399
400 emu = port->emu;
401 snd_assert(emu != NULL, return);
402 snd_assert(emu->ops.terminate != NULL, return);
403
404 terminate_note1(emu, note, chan, 1);
405}
406
407
408/*
409 * Terminate all the notes
410 */
411void
Takashi Iwai03da3122005-11-17 14:24:47 +0100412snd_emux_terminate_all(struct snd_emux *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413{
414 int i;
Takashi Iwai03da3122005-11-17 14:24:47 +0100415 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 unsigned long flags;
417
418 spin_lock_irqsave(&emu->voice_lock, flags);
419 for (i = 0; i < emu->max_voices; i++) {
420 vp = &emu->voices[i];
421 if (STATE_IS_PLAYING(vp->state))
422 terminate_voice(emu, vp, 0);
423 if (vp->state == SNDRV_EMUX_ST_OFF) {
424 if (emu->ops.free_voice)
425 emu->ops.free_voice(vp);
426 if (emu->ops.reset)
427 emu->ops.reset(emu, i);
428 }
429 vp->time = 0;
430 }
431 /* initialize allocation time */
432 emu->use_time = 0;
433 spin_unlock_irqrestore(&emu->voice_lock, flags);
434}
435
436
437/*
438 * Terminate all voices associated with the given port
439 */
440void
Takashi Iwai03da3122005-11-17 14:24:47 +0100441snd_emux_sounds_off_all(struct snd_emux_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442{
443 int i;
Takashi Iwai03da3122005-11-17 14:24:47 +0100444 struct snd_emux *emu;
445 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 unsigned long flags;
447
448 snd_assert(port != NULL, return);
449 emu = port->emu;
450 snd_assert(emu != NULL, return);
451 snd_assert(emu->ops.terminate != NULL, return);
452
453 spin_lock_irqsave(&emu->voice_lock, flags);
454 for (i = 0; i < emu->max_voices; i++) {
455 vp = &emu->voices[i];
456 if (STATE_IS_PLAYING(vp->state) &&
457 vp->port == port)
458 terminate_voice(emu, vp, 0);
459 if (vp->state == SNDRV_EMUX_ST_OFF) {
460 if (emu->ops.free_voice)
461 emu->ops.free_voice(vp);
462 if (emu->ops.reset)
463 emu->ops.reset(emu, i);
464 }
465 }
466 spin_unlock_irqrestore(&emu->voice_lock, flags);
467}
468
469
470/*
471 * Terminate all voices that have the same exclusive class. This
472 * is mainly for drums.
473 */
474static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100475exclusive_note_off(struct snd_emux *emu, struct snd_emux_port *port, int exclass)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476{
Takashi Iwai03da3122005-11-17 14:24:47 +0100477 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 int i;
479 unsigned long flags;
480
481 spin_lock_irqsave(&emu->voice_lock, flags);
482 for (i = 0; i < emu->max_voices; i++) {
483 vp = &emu->voices[i];
484 if (STATE_IS_PLAYING(vp->state) && vp->port == port &&
485 vp->reg.exclusiveClass == exclass) {
486 terminate_voice(emu, vp, 0);
487 }
488 }
489 spin_unlock_irqrestore(&emu->voice_lock, flags);
490}
491
492/*
493 * terminate a voice
494 * if free flag is true, call free_voice after termination
495 */
496static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100497terminate_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int free)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498{
499 emu->ops.terminate(vp);
500 vp->time = emu->use_time++;
501 vp->chan = NULL;
502 vp->port = NULL;
503 vp->zone = NULL;
504 vp->block = NULL;
505 vp->state = SNDRV_EMUX_ST_OFF;
506 if (free && emu->ops.free_voice)
507 emu->ops.free_voice(vp);
508}
509
510
511/*
512 * Modulate the voice
513 */
514static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100515update_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int update)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516{
517 if (!STATE_IS_PLAYING(vp->state))
518 return;
519
520 if (vp->chan == NULL || vp->port == NULL)
521 return;
522 if (update & SNDRV_EMUX_UPDATE_VOLUME)
523 calc_volume(vp);
524 if (update & SNDRV_EMUX_UPDATE_PITCH)
525 calc_pitch(vp);
526 if (update & SNDRV_EMUX_UPDATE_PAN) {
527 if (! calc_pan(vp) && (update == SNDRV_EMUX_UPDATE_PAN))
528 return;
529 }
530 emu->ops.update(vp, update);
531}
532
533
534#if 0 // not used
535/* table for volume target calculation */
536static unsigned short voltarget[16] = {
537 0xEAC0, 0xE0C8, 0xD740, 0xCE20, 0xC560, 0xBD08, 0xB500, 0xAD58,
538 0xA5F8, 0x9EF0, 0x9830, 0x91C0, 0x8B90, 0x85A8, 0x8000, 0x7A90
539};
540#endif
541
542#define LO_BYTE(v) ((v) & 0xff)
543#define HI_BYTE(v) (((v) >> 8) & 0xff)
544
545/*
546 * Sets up the voice structure by calculating some values that
547 * will be needed later.
548 */
549static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100550setup_voice(struct snd_emux_voice *vp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551{
Takashi Iwai03da3122005-11-17 14:24:47 +0100552 struct soundfont_voice_parm *parm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 int pitch;
554
555 /* copy the original register values */
556 vp->reg = vp->zone->v;
557
558#ifdef SNDRV_EMUX_USE_RAW_EFFECT
559 snd_emux_setup_effect(vp);
560#endif
561
562 /* reset status */
563 vp->apan = -1;
564 vp->avol = -1;
565 vp->apitch = -1;
566
567 calc_volume(vp);
568 calc_pitch(vp);
569 calc_pan(vp);
570
571 parm = &vp->reg.parm;
572
573 /* compute filter target and correct modulation parameters */
574 if (LO_BYTE(parm->modatkhld) >= 0x80 && parm->moddelay >= 0x8000) {
575 parm->moddelay = 0xbfff;
576 pitch = (HI_BYTE(parm->pefe) << 4) + vp->apitch;
577 if (pitch > 0xffff)
578 pitch = 0xffff;
579 /* calculate filter target */
580 vp->ftarget = parm->cutoff + LO_BYTE(parm->pefe);
581 LIMITVALUE(vp->ftarget, 0, 255);
582 vp->ftarget <<= 8;
583 } else {
584 vp->ftarget = parm->cutoff;
585 vp->ftarget <<= 8;
586 pitch = vp->apitch;
587 }
588
589 /* compute pitch target */
590 if (pitch != 0xffff) {
591 vp->ptarget = 1 << (pitch >> 12);
592 if (pitch & 0x800) vp->ptarget += (vp->ptarget*0x102e)/0x2710;
593 if (pitch & 0x400) vp->ptarget += (vp->ptarget*0x764)/0x2710;
594 if (pitch & 0x200) vp->ptarget += (vp->ptarget*0x389)/0x2710;
595 vp->ptarget += (vp->ptarget >> 1);
596 if (vp->ptarget > 0xffff) vp->ptarget = 0xffff;
597 } else
598 vp->ptarget = 0xffff;
599
600 if (LO_BYTE(parm->modatkhld) >= 0x80) {
601 parm->modatkhld &= ~0xff;
602 parm->modatkhld |= 0x7f;
603 }
604
605 /* compute volume target and correct volume parameters */
606 vp->vtarget = 0;
607#if 0 /* FIXME: this leads to some clicks.. */
608 if (LO_BYTE(parm->volatkhld) >= 0x80 && parm->voldelay >= 0x8000) {
609 parm->voldelay = 0xbfff;
610 vp->vtarget = voltarget[vp->avol % 0x10] >> (vp->avol >> 4);
611 }
612#endif
613
614 if (LO_BYTE(parm->volatkhld) >= 0x80) {
615 parm->volatkhld &= ~0xff;
616 parm->volatkhld |= 0x7f;
617 }
618}
619
620/*
621 * calculate pitch parameter
622 */
623static unsigned char pan_volumes[256] = {
6240x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x14,0x17,0x1a,0x1d,0x20,0x22,0x25,0x28,0x2a,
6250x2d,0x30,0x32,0x35,0x37,0x3a,0x3c,0x3f,0x41,0x44,0x46,0x49,0x4b,0x4d,0x50,0x52,
6260x54,0x57,0x59,0x5b,0x5d,0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6f,0x71,0x73,0x75,
6270x77,0x79,0x7b,0x7c,0x7e,0x80,0x82,0x84,0x86,0x88,0x89,0x8b,0x8d,0x8f,0x90,0x92,
6280x94,0x96,0x97,0x99,0x9a,0x9c,0x9e,0x9f,0xa1,0xa2,0xa4,0xa5,0xa7,0xa8,0xaa,0xab,
6290xad,0xae,0xaf,0xb1,0xb2,0xb3,0xb5,0xb6,0xb7,0xb9,0xba,0xbb,0xbc,0xbe,0xbf,0xc0,
6300xc1,0xc2,0xc3,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,
6310xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdc,0xdd,0xde,0xdf,
6320xdf,0xe0,0xe1,0xe2,0xe2,0xe3,0xe4,0xe4,0xe5,0xe6,0xe6,0xe7,0xe8,0xe8,0xe9,0xe9,
6330xea,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf1,0xf1,0xf1,
6340xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,0xf7,
6350xf7,0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,
6360xfb,0xfb,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
6370xfd,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
6380xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
6390xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
640};
641
642static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100643calc_pan(struct snd_emux_voice *vp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644{
Takashi Iwai03da3122005-11-17 14:24:47 +0100645 struct snd_midi_channel *chan = vp->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 int pan;
647
648 /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */
649 if (vp->reg.fixpan > 0) /* 0-127 */
650 pan = 255 - (int)vp->reg.fixpan * 2;
651 else {
652 pan = chan->control[MIDI_CTL_MSB_PAN] - 64;
653 if (vp->reg.pan >= 0) /* 0-127 */
654 pan += vp->reg.pan - 64;
655 pan = 127 - (int)pan * 2;
656 }
657 LIMITVALUE(pan, 0, 255);
658
659 if (vp->emu->linear_panning) {
660 /* assuming linear volume */
661 if (pan != vp->apan) {
662 vp->apan = pan;
663 if (pan == 0)
664 vp->aaux = 0xff;
665 else
666 vp->aaux = (-pan) & 0xff;
667 return 1;
668 } else
669 return 0;
670 } else {
671 /* using volume table */
672 if (vp->apan != (int)pan_volumes[pan]) {
673 vp->apan = pan_volumes[pan];
674 vp->aaux = pan_volumes[255 - pan];
675 return 1;
676 }
677 return 0;
678 }
679}
680
681
682/*
683 * calculate volume attenuation
684 *
685 * Voice volume is controlled by volume attenuation parameter.
686 * So volume becomes maximum when avol is 0 (no attenuation), and
687 * minimum when 255 (-96dB or silence).
688 */
689
690/* tables for volume->attenuation calculation */
691static unsigned char voltab1[128] = {
692 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
693 0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22,
694 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
695 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14,
696 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10,
697 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d,
698 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b,
699 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,
700 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,
701 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,
702 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02,
703 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
704 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
705};
706
707static unsigned char voltab2[128] = {
708 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a,
709 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21,
710 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a,
711 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15,
712 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10,
713 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d,
714 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a,
715 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
716 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
717 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
718 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
719 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
720 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
721};
722
723static unsigned char expressiontab[128] = {
724 0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42,
725 0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30,
726 0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,
727 0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e,
728 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18,
729 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13,
730 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f,
731 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c,
732 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09,
733 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
734 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
735 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
736 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
737};
738
739/*
740 * Magic to calculate the volume (actually attenuation) from all the
741 * voice and channels parameters.
742 */
743static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100744calc_volume(struct snd_emux_voice *vp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745{
746 int vol;
747 int main_vol, expression_vol, master_vol;
Takashi Iwai03da3122005-11-17 14:24:47 +0100748 struct snd_midi_channel *chan = vp->chan;
749 struct snd_emux_port *port = vp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750
751 expression_vol = chan->control[MIDI_CTL_MSB_EXPRESSION];
752 LIMITMAX(vp->velocity, 127);
753 LIMITVALUE(expression_vol, 0, 127);
754 if (port->port_mode == SNDRV_EMUX_PORT_MODE_OSS_SYNTH) {
755 /* 0 - 127 */
756 main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME];
757 vol = (vp->velocity * main_vol * expression_vol) / (127*127);
758 vol = vol * vp->reg.amplitude / 127;
759
760 LIMITVALUE(vol, 0, 127);
761
762 /* calc to attenuation */
763 vol = snd_sf_vol_table[vol];
764
765 } else {
766 main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME] * vp->reg.amplitude / 127;
767 LIMITVALUE(main_vol, 0, 127);
768
769 vol = voltab1[main_vol] + voltab2[vp->velocity];
770 vol = (vol * 8) / 3;
771 vol += vp->reg.attenuation;
772 vol += ((0x100 - vol) * expressiontab[expression_vol])/128;
773 }
774
775 master_vol = port->chset.gs_master_volume;
776 LIMITVALUE(master_vol, 0, 127);
777 vol += snd_sf_vol_table[master_vol];
778 vol += port->volume_atten;
779
780#ifdef SNDRV_EMUX_USE_RAW_EFFECT
781 if (chan->private) {
Takashi Iwai03da3122005-11-17 14:24:47 +0100782 struct snd_emux_effect_table *fx = chan->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 vol += fx->val[EMUX_FX_ATTEN];
784 }
785#endif
786
787 LIMITVALUE(vol, 0, 255);
788 if (vp->avol == vol)
789 return 0; /* value unchanged */
790
791 vp->avol = vol;
792 if (!SF_IS_DRUM_BANK(get_bank(port, chan))
793 && LO_BYTE(vp->reg.parm.volatkhld) < 0x7d) {
794 int atten;
795 if (vp->velocity < 70)
796 atten = 70;
797 else
798 atten = vp->velocity;
799 vp->acutoff = (atten * vp->reg.parm.cutoff + 0xa0) >> 7;
800 } else {
801 vp->acutoff = vp->reg.parm.cutoff;
802 }
803
804 return 1; /* value changed */
805}
806
807/*
808 * calculate pitch offset
809 *
810 * 0xE000 is no pitch offset at 44100Hz sample.
811 * Every 4096 is one octave.
812 */
813
814static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100815calc_pitch(struct snd_emux_voice *vp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816{
Takashi Iwai03da3122005-11-17 14:24:47 +0100817 struct snd_midi_channel *chan = vp->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 int offset;
819
820 /* calculate offset */
821 if (vp->reg.fixkey >= 0) {
822 offset = (vp->reg.fixkey - vp->reg.root) * 4096 / 12;
823 } else {
824 offset = (vp->note - vp->reg.root) * 4096 / 12;
825 }
826 offset = (offset * vp->reg.scaleTuning) / 100;
827 offset += vp->reg.tune * 4096 / 1200;
828 if (chan->midi_pitchbend != 0) {
829 /* (128 * 8192: 1 semitone) ==> (4096: 12 semitones) */
830 offset += chan->midi_pitchbend * chan->gm_rpn_pitch_bend_range / 3072;
831 }
832
833 /* tuning via RPN:
834 * coarse = -8192 to 8192 (100 cent per 128)
835 * fine = -8192 to 8192 (max=100cent)
836 */
837 /* 4096 = 1200 cents in emu8000 parameter */
838 offset += chan->gm_rpn_coarse_tuning * 4096 / (12 * 128);
839 offset += chan->gm_rpn_fine_tuning / 24;
840
841#ifdef SNDRV_EMUX_USE_RAW_EFFECT
842 /* add initial pitch correction */
843 if (chan->private) {
Takashi Iwai03da3122005-11-17 14:24:47 +0100844 struct snd_emux_effect_table *fx = chan->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 if (fx->flag[EMUX_FX_INIT_PITCH])
846 offset += fx->val[EMUX_FX_INIT_PITCH];
847 }
848#endif
849
850 /* 0xe000: root pitch */
851 offset += 0xe000 + vp->reg.rate_offset;
852 offset += vp->emu->pitch_shift;
853 LIMITVALUE(offset, 0, 0xffff);
854 if (offset == vp->apitch)
855 return 0; /* unchanged */
856 vp->apitch = offset;
857 return 1; /* value changed */
858}
859
860/*
861 * Get the bank number assigned to the channel
862 */
863static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100864get_bank(struct snd_emux_port *port, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865{
866 int val;
867
868 switch (port->chset.midi_mode) {
869 case SNDRV_MIDI_MODE_XG:
870 val = chan->control[MIDI_CTL_MSB_BANK];
871 if (val == 127)
872 return 128; /* return drum bank */
873 return chan->control[MIDI_CTL_LSB_BANK];
874
875 case SNDRV_MIDI_MODE_GS:
876 if (chan->drum_channel)
877 return 128;
878 /* ignore LSB (bank map) */
879 return chan->control[MIDI_CTL_MSB_BANK];
880
881 default:
882 if (chan->drum_channel)
883 return 128;
884 return chan->control[MIDI_CTL_MSB_BANK];
885 }
886}
887
888
889/* Look for the zones matching with the given note and velocity.
890 * The resultant zones are stored on table.
891 */
892static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100893get_zone(struct snd_emux *emu, struct snd_emux_port *port,
894 int *notep, int vel, struct snd_midi_channel *chan,
895 struct snd_sf_zone **table)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896{
897 int preset, bank, def_preset, def_bank;
898
899 bank = get_bank(port, chan);
900 preset = chan->midi_program;
901
902 if (SF_IS_DRUM_BANK(bank)) {
903 def_preset = port->ctrls[EMUX_MD_DEF_DRUM];
904 def_bank = bank;
905 } else {
906 def_preset = preset;
907 def_bank = port->ctrls[EMUX_MD_DEF_BANK];
908 }
909
910 return snd_soundfont_search_zone(emu->sflist, notep, vel, preset, bank,
911 def_preset, def_bank,
912 table, SNDRV_EMUX_MAX_MULTI_VOICES);
913}
914
915/*
916 */
917void
Takashi Iwai03da3122005-11-17 14:24:47 +0100918snd_emux_init_voices(struct snd_emux *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919{
Takashi Iwai03da3122005-11-17 14:24:47 +0100920 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 int i;
922 unsigned long flags;
923
924 spin_lock_irqsave(&emu->voice_lock, flags);
925 for (i = 0; i < emu->max_voices; i++) {
926 vp = &emu->voices[i];
927 vp->ch = -1; /* not used */
928 vp->state = SNDRV_EMUX_ST_OFF;
929 vp->chan = NULL;
930 vp->port = NULL;
931 vp->time = 0;
932 vp->emu = emu;
933 vp->hw = emu->hw;
934 }
935 spin_unlock_irqrestore(&emu->voice_lock, flags);
936}
937
938/*
939 */
Takashi Iwai03da3122005-11-17 14:24:47 +0100940void snd_emux_lock_voice(struct snd_emux *emu, int voice)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941{
942 unsigned long flags;
943
944 spin_lock_irqsave(&emu->voice_lock, flags);
945 if (emu->voices[voice].state == SNDRV_EMUX_ST_OFF)
946 emu->voices[voice].state = SNDRV_EMUX_ST_LOCKED;
947 else
948 snd_printk("invalid voice for lock %d (state = %x)\n",
949 voice, emu->voices[voice].state);
950 spin_unlock_irqrestore(&emu->voice_lock, flags);
951}
952
953/*
954 */
Takashi Iwai03da3122005-11-17 14:24:47 +0100955void snd_emux_unlock_voice(struct snd_emux *emu, int voice)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956{
957 unsigned long flags;
958
959 spin_lock_irqsave(&emu->voice_lock, flags);
960 if (emu->voices[voice].state == SNDRV_EMUX_ST_LOCKED)
961 emu->voices[voice].state = SNDRV_EMUX_ST_OFF;
962 else
963 snd_printk("invalid voice for unlock %d (state = %x)\n",
964 voice, emu->voices[voice].state);
965 spin_unlock_irqrestore(&emu->voice_lock, flags);
966}