blob: 2cc6f6f7906574f77bc471cfc7405085c98434e1 [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;
Takashi Iwai5e246b82008-08-08 17:12:47 +020069 if (snd_BUG_ON(!port || !chan))
70 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
72 emu = port->emu;
Takashi Iwai5e246b82008-08-08 17:12:47 +020073 if (snd_BUG_ON(!emu || !emu->ops.get_voice || !emu->ops.trigger))
74 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
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;
Takashi Iwai5e246b82008-08-08 17:12:47 +0200167 if (snd_BUG_ON(!port || !chan))
168 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169
170 emu = port->emu;
Takashi Iwai5e246b82008-08-08 17:12:47 +0200171 if (snd_BUG_ON(!emu || !emu->ops.release))
172 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
174 spin_lock_irqsave(&emu->voice_lock, flags);
175 for (ch = 0; ch < emu->max_voices; ch++) {
176 vp = &emu->voices[ch];
177 if (STATE_IS_PLAYING(vp->state) &&
178 vp->chan == chan && vp->key == note) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 vp->state = SNDRV_EMUX_ST_RELEASED;
180 if (vp->ontime == jiffies) {
181 /* if note-off is sent too shortly after
182 * note-on, emuX engine cannot produce the sound
183 * correctly. so we'll release this note
184 * a bit later via timer callback.
185 */
186 vp->state = SNDRV_EMUX_ST_PENDING;
187 if (! emu->timer_active) {
188 emu->tlist.expires = jiffies + 1;
189 add_timer(&emu->tlist);
190 emu->timer_active = 1;
191 }
192 } else
193 /* ok now release the note */
194 emu->ops.release(vp);
195 }
196 }
197 spin_unlock_irqrestore(&emu->voice_lock, flags);
198}
199
200/*
201 * timer callback
202 *
203 * release the pending note-offs
204 */
205void snd_emux_timer_callback(unsigned long data)
206{
Takashi Iwai03da3122005-11-17 14:24:47 +0100207 struct snd_emux *emu = (struct snd_emux *) data;
208 struct snd_emux_voice *vp;
Takashi Iwaib32425a2005-11-18 18:52:14 +0100209 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 int ch, do_again = 0;
211
Takashi Iwaib32425a2005-11-18 18:52:14 +0100212 spin_lock_irqsave(&emu->voice_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 for (ch = 0; ch < emu->max_voices; ch++) {
214 vp = &emu->voices[ch];
215 if (vp->state == SNDRV_EMUX_ST_PENDING) {
216 if (vp->ontime == jiffies)
217 do_again++; /* release this at the next interrupt */
218 else {
219 emu->ops.release(vp);
220 vp->state = SNDRV_EMUX_ST_RELEASED;
221 }
222 }
223 }
224 if (do_again) {
225 emu->tlist.expires = jiffies + 1;
226 add_timer(&emu->tlist);
227 emu->timer_active = 1;
228 } else
229 emu->timer_active = 0;
Takashi Iwaib32425a2005-11-18 18:52:14 +0100230 spin_unlock_irqrestore(&emu->voice_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231}
232
233/*
234 * key pressure change
235 */
236void
Takashi Iwai03da3122005-11-17 14:24:47 +0100237snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238{
239 int ch;
Takashi Iwai03da3122005-11-17 14:24:47 +0100240 struct snd_emux *emu;
241 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 unsigned long flags;
Takashi Iwai03da3122005-11-17 14:24:47 +0100243 struct snd_emux_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
245 port = p;
Takashi Iwai5e246b82008-08-08 17:12:47 +0200246 if (snd_BUG_ON(!port || !chan))
247 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249 emu = port->emu;
Takashi Iwai5e246b82008-08-08 17:12:47 +0200250 if (snd_BUG_ON(!emu || !emu->ops.update))
251 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
253 spin_lock_irqsave(&emu->voice_lock, flags);
254 for (ch = 0; ch < emu->max_voices; ch++) {
255 vp = &emu->voices[ch];
256 if (vp->state == SNDRV_EMUX_ST_ON &&
257 vp->chan == chan && vp->key == note) {
258 vp->velocity = vel;
259 update_voice(emu, vp, SNDRV_EMUX_UPDATE_VOLUME);
260 }
261 }
262 spin_unlock_irqrestore(&emu->voice_lock, flags);
263}
264
265
266/*
267 * Modulate the voices which belong to the channel
268 */
269void
Takashi Iwai03da3122005-11-17 14:24:47 +0100270snd_emux_update_channel(struct snd_emux_port *port, struct snd_midi_channel *chan, int update)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271{
Takashi Iwai03da3122005-11-17 14:24:47 +0100272 struct snd_emux *emu;
273 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 int i;
275 unsigned long flags;
276
277 if (! update)
278 return;
279
280 emu = port->emu;
Takashi Iwai5e246b82008-08-08 17:12:47 +0200281 if (snd_BUG_ON(!emu || !emu->ops.update))
282 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
284 spin_lock_irqsave(&emu->voice_lock, flags);
285 for (i = 0; i < emu->max_voices; i++) {
286 vp = &emu->voices[i];
287 if (vp->chan == chan)
288 update_voice(emu, vp, update);
289 }
290 spin_unlock_irqrestore(&emu->voice_lock, flags);
291}
292
293/*
294 * Modulate all the voices which belong to the port.
295 */
296void
Takashi Iwai03da3122005-11-17 14:24:47 +0100297snd_emux_update_port(struct snd_emux_port *port, int update)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298{
Takashi Iwai03da3122005-11-17 14:24:47 +0100299 struct snd_emux *emu;
300 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 int i;
302 unsigned long flags;
303
304 if (! update)
305 return;
306
307 emu = port->emu;
Takashi Iwai5e246b82008-08-08 17:12:47 +0200308 if (snd_BUG_ON(!emu || !emu->ops.update))
309 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310
311 spin_lock_irqsave(&emu->voice_lock, flags);
312 for (i = 0; i < emu->max_voices; i++) {
313 vp = &emu->voices[i];
314 if (vp->port == port)
315 update_voice(emu, vp, update);
316 }
317 spin_unlock_irqrestore(&emu->voice_lock, flags);
318}
319
320
321/*
Robert P. J. Day3a4fa0a2007-10-19 23:10:43 +0200322 * Deal with a controller type event. This includes all types of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 * control events, not just the midi controllers
324 */
325void
Takashi Iwai03da3122005-11-17 14:24:47 +0100326snd_emux_control(void *p, int type, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327{
Takashi Iwai03da3122005-11-17 14:24:47 +0100328 struct snd_emux_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
330 port = p;
Takashi Iwai5e246b82008-08-08 17:12:47 +0200331 if (snd_BUG_ON(!port || !chan))
332 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
334 switch (type) {
335 case MIDI_CTL_MSB_MAIN_VOLUME:
336 case MIDI_CTL_MSB_EXPRESSION:
337 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_VOLUME);
338 break;
339
340 case MIDI_CTL_MSB_PAN:
341 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PAN);
342 break;
343
344 case MIDI_CTL_SOFT_PEDAL:
345#ifdef SNDRV_EMUX_USE_RAW_EFFECT
346 /* FIXME: this is an emulation */
maximilian attemsbf911412008-05-09 13:43:09 +0200347 if (chan->control[type] >= 64)
348 snd_emux_send_effect(port, chan, EMUX_FX_CUTOFF, -160,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 EMUX_FX_FLAG_ADD);
maximilian attemsbf911412008-05-09 13:43:09 +0200350 else
351 snd_emux_send_effect(port, chan, EMUX_FX_CUTOFF, 0,
352 EMUX_FX_FLAG_OFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353#endif
354 break;
355
356 case MIDI_CTL_PITCHBEND:
357 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PITCH);
358 break;
359
360 case MIDI_CTL_MSB_MODWHEEL:
361 case MIDI_CTL_CHAN_PRESSURE:
362 snd_emux_update_channel(port, chan,
363 SNDRV_EMUX_UPDATE_FMMOD |
364 SNDRV_EMUX_UPDATE_FM2FRQ2);
365 break;
366
367 }
368
369 if (port->chset.midi_mode == SNDRV_MIDI_MODE_XG) {
370 snd_emux_xg_control(port, chan, type);
371 }
372}
373
374
375/*
376 * terminate note - if free flag is true, free the terminated voice
377 */
378static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100379terminate_note1(struct snd_emux *emu, int note, struct snd_midi_channel *chan, int free)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380{
381 int i;
Takashi Iwai03da3122005-11-17 14:24:47 +0100382 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 unsigned long flags;
384
385 spin_lock_irqsave(&emu->voice_lock, flags);
386 for (i = 0; i < emu->max_voices; i++) {
387 vp = &emu->voices[i];
388 if (STATE_IS_PLAYING(vp->state) && vp->chan == chan &&
389 vp->key == note)
390 terminate_voice(emu, vp, free);
391 }
392 spin_unlock_irqrestore(&emu->voice_lock, flags);
393}
394
395
396/*
397 * terminate note - exported for midi emulation
398 */
399void
Takashi Iwai03da3122005-11-17 14:24:47 +0100400snd_emux_terminate_note(void *p, int note, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401{
Takashi Iwai03da3122005-11-17 14:24:47 +0100402 struct snd_emux *emu;
403 struct snd_emux_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
405 port = p;
Takashi Iwai5e246b82008-08-08 17:12:47 +0200406 if (snd_BUG_ON(!port || !chan))
407 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
409 emu = port->emu;
Takashi Iwai5e246b82008-08-08 17:12:47 +0200410 if (snd_BUG_ON(!emu || !emu->ops.terminate))
411 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
413 terminate_note1(emu, note, chan, 1);
414}
415
416
417/*
418 * Terminate all the notes
419 */
420void
Takashi Iwai03da3122005-11-17 14:24:47 +0100421snd_emux_terminate_all(struct snd_emux *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422{
423 int i;
Takashi Iwai03da3122005-11-17 14:24:47 +0100424 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 unsigned long flags;
426
427 spin_lock_irqsave(&emu->voice_lock, flags);
428 for (i = 0; i < emu->max_voices; i++) {
429 vp = &emu->voices[i];
430 if (STATE_IS_PLAYING(vp->state))
431 terminate_voice(emu, vp, 0);
432 if (vp->state == SNDRV_EMUX_ST_OFF) {
433 if (emu->ops.free_voice)
434 emu->ops.free_voice(vp);
435 if (emu->ops.reset)
436 emu->ops.reset(emu, i);
437 }
438 vp->time = 0;
439 }
440 /* initialize allocation time */
441 emu->use_time = 0;
442 spin_unlock_irqrestore(&emu->voice_lock, flags);
443}
444
Takashi Iwai95ff17562006-04-28 15:13:40 +0200445EXPORT_SYMBOL(snd_emux_terminate_all);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
447/*
448 * Terminate all voices associated with the given port
449 */
450void
Takashi Iwai03da3122005-11-17 14:24:47 +0100451snd_emux_sounds_off_all(struct snd_emux_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452{
453 int i;
Takashi Iwai03da3122005-11-17 14:24:47 +0100454 struct snd_emux *emu;
455 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 unsigned long flags;
457
Takashi Iwai5e246b82008-08-08 17:12:47 +0200458 if (snd_BUG_ON(!port))
459 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 emu = port->emu;
Takashi Iwai5e246b82008-08-08 17:12:47 +0200461 if (snd_BUG_ON(!emu || !emu->ops.terminate))
462 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
464 spin_lock_irqsave(&emu->voice_lock, flags);
465 for (i = 0; i < emu->max_voices; i++) {
466 vp = &emu->voices[i];
467 if (STATE_IS_PLAYING(vp->state) &&
468 vp->port == port)
469 terminate_voice(emu, vp, 0);
470 if (vp->state == SNDRV_EMUX_ST_OFF) {
471 if (emu->ops.free_voice)
472 emu->ops.free_voice(vp);
473 if (emu->ops.reset)
474 emu->ops.reset(emu, i);
475 }
476 }
477 spin_unlock_irqrestore(&emu->voice_lock, flags);
478}
479
480
481/*
482 * Terminate all voices that have the same exclusive class. This
483 * is mainly for drums.
484 */
485static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100486exclusive_note_off(struct snd_emux *emu, struct snd_emux_port *port, int exclass)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487{
Takashi Iwai03da3122005-11-17 14:24:47 +0100488 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 int i;
490 unsigned long flags;
491
492 spin_lock_irqsave(&emu->voice_lock, flags);
493 for (i = 0; i < emu->max_voices; i++) {
494 vp = &emu->voices[i];
495 if (STATE_IS_PLAYING(vp->state) && vp->port == port &&
496 vp->reg.exclusiveClass == exclass) {
497 terminate_voice(emu, vp, 0);
498 }
499 }
500 spin_unlock_irqrestore(&emu->voice_lock, flags);
501}
502
503/*
504 * terminate a voice
505 * if free flag is true, call free_voice after termination
506 */
507static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100508terminate_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int free)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509{
510 emu->ops.terminate(vp);
511 vp->time = emu->use_time++;
512 vp->chan = NULL;
513 vp->port = NULL;
514 vp->zone = NULL;
515 vp->block = NULL;
516 vp->state = SNDRV_EMUX_ST_OFF;
517 if (free && emu->ops.free_voice)
518 emu->ops.free_voice(vp);
519}
520
521
522/*
523 * Modulate the voice
524 */
525static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100526update_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int update)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527{
528 if (!STATE_IS_PLAYING(vp->state))
529 return;
530
531 if (vp->chan == NULL || vp->port == NULL)
532 return;
533 if (update & SNDRV_EMUX_UPDATE_VOLUME)
534 calc_volume(vp);
535 if (update & SNDRV_EMUX_UPDATE_PITCH)
536 calc_pitch(vp);
537 if (update & SNDRV_EMUX_UPDATE_PAN) {
538 if (! calc_pan(vp) && (update == SNDRV_EMUX_UPDATE_PAN))
539 return;
540 }
541 emu->ops.update(vp, update);
542}
543
544
545#if 0 // not used
546/* table for volume target calculation */
547static unsigned short voltarget[16] = {
548 0xEAC0, 0xE0C8, 0xD740, 0xCE20, 0xC560, 0xBD08, 0xB500, 0xAD58,
549 0xA5F8, 0x9EF0, 0x9830, 0x91C0, 0x8B90, 0x85A8, 0x8000, 0x7A90
550};
551#endif
552
553#define LO_BYTE(v) ((v) & 0xff)
554#define HI_BYTE(v) (((v) >> 8) & 0xff)
555
556/*
557 * Sets up the voice structure by calculating some values that
558 * will be needed later.
559 */
560static void
Takashi Iwai03da3122005-11-17 14:24:47 +0100561setup_voice(struct snd_emux_voice *vp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562{
Takashi Iwai03da3122005-11-17 14:24:47 +0100563 struct soundfont_voice_parm *parm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 int pitch;
565
566 /* copy the original register values */
567 vp->reg = vp->zone->v;
568
569#ifdef SNDRV_EMUX_USE_RAW_EFFECT
570 snd_emux_setup_effect(vp);
571#endif
572
573 /* reset status */
574 vp->apan = -1;
575 vp->avol = -1;
576 vp->apitch = -1;
577
578 calc_volume(vp);
579 calc_pitch(vp);
580 calc_pan(vp);
581
582 parm = &vp->reg.parm;
583
584 /* compute filter target and correct modulation parameters */
585 if (LO_BYTE(parm->modatkhld) >= 0x80 && parm->moddelay >= 0x8000) {
586 parm->moddelay = 0xbfff;
587 pitch = (HI_BYTE(parm->pefe) << 4) + vp->apitch;
588 if (pitch > 0xffff)
589 pitch = 0xffff;
590 /* calculate filter target */
591 vp->ftarget = parm->cutoff + LO_BYTE(parm->pefe);
592 LIMITVALUE(vp->ftarget, 0, 255);
593 vp->ftarget <<= 8;
594 } else {
595 vp->ftarget = parm->cutoff;
596 vp->ftarget <<= 8;
597 pitch = vp->apitch;
598 }
599
600 /* compute pitch target */
601 if (pitch != 0xffff) {
602 vp->ptarget = 1 << (pitch >> 12);
603 if (pitch & 0x800) vp->ptarget += (vp->ptarget*0x102e)/0x2710;
604 if (pitch & 0x400) vp->ptarget += (vp->ptarget*0x764)/0x2710;
605 if (pitch & 0x200) vp->ptarget += (vp->ptarget*0x389)/0x2710;
606 vp->ptarget += (vp->ptarget >> 1);
607 if (vp->ptarget > 0xffff) vp->ptarget = 0xffff;
608 } else
609 vp->ptarget = 0xffff;
610
611 if (LO_BYTE(parm->modatkhld) >= 0x80) {
612 parm->modatkhld &= ~0xff;
613 parm->modatkhld |= 0x7f;
614 }
615
616 /* compute volume target and correct volume parameters */
617 vp->vtarget = 0;
618#if 0 /* FIXME: this leads to some clicks.. */
619 if (LO_BYTE(parm->volatkhld) >= 0x80 && parm->voldelay >= 0x8000) {
620 parm->voldelay = 0xbfff;
621 vp->vtarget = voltarget[vp->avol % 0x10] >> (vp->avol >> 4);
622 }
623#endif
624
625 if (LO_BYTE(parm->volatkhld) >= 0x80) {
626 parm->volatkhld &= ~0xff;
627 parm->volatkhld |= 0x7f;
628 }
629}
630
631/*
632 * calculate pitch parameter
633 */
634static unsigned char pan_volumes[256] = {
6350x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x14,0x17,0x1a,0x1d,0x20,0x22,0x25,0x28,0x2a,
6360x2d,0x30,0x32,0x35,0x37,0x3a,0x3c,0x3f,0x41,0x44,0x46,0x49,0x4b,0x4d,0x50,0x52,
6370x54,0x57,0x59,0x5b,0x5d,0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6f,0x71,0x73,0x75,
6380x77,0x79,0x7b,0x7c,0x7e,0x80,0x82,0x84,0x86,0x88,0x89,0x8b,0x8d,0x8f,0x90,0x92,
6390x94,0x96,0x97,0x99,0x9a,0x9c,0x9e,0x9f,0xa1,0xa2,0xa4,0xa5,0xa7,0xa8,0xaa,0xab,
6400xad,0xae,0xaf,0xb1,0xb2,0xb3,0xb5,0xb6,0xb7,0xb9,0xba,0xbb,0xbc,0xbe,0xbf,0xc0,
6410xc1,0xc2,0xc3,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,
6420xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdc,0xdd,0xde,0xdf,
6430xdf,0xe0,0xe1,0xe2,0xe2,0xe3,0xe4,0xe4,0xe5,0xe6,0xe6,0xe7,0xe8,0xe8,0xe9,0xe9,
6440xea,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf1,0xf1,0xf1,
6450xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,0xf7,
6460xf7,0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,
6470xfb,0xfb,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
6480xfd,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
6490xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
6500xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
651};
652
653static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100654calc_pan(struct snd_emux_voice *vp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655{
Takashi Iwai03da3122005-11-17 14:24:47 +0100656 struct snd_midi_channel *chan = vp->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 int pan;
658
659 /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */
660 if (vp->reg.fixpan > 0) /* 0-127 */
661 pan = 255 - (int)vp->reg.fixpan * 2;
662 else {
663 pan = chan->control[MIDI_CTL_MSB_PAN] - 64;
664 if (vp->reg.pan >= 0) /* 0-127 */
665 pan += vp->reg.pan - 64;
666 pan = 127 - (int)pan * 2;
667 }
668 LIMITVALUE(pan, 0, 255);
669
670 if (vp->emu->linear_panning) {
671 /* assuming linear volume */
672 if (pan != vp->apan) {
673 vp->apan = pan;
674 if (pan == 0)
675 vp->aaux = 0xff;
676 else
677 vp->aaux = (-pan) & 0xff;
678 return 1;
679 } else
680 return 0;
681 } else {
682 /* using volume table */
683 if (vp->apan != (int)pan_volumes[pan]) {
684 vp->apan = pan_volumes[pan];
685 vp->aaux = pan_volumes[255 - pan];
686 return 1;
687 }
688 return 0;
689 }
690}
691
692
693/*
694 * calculate volume attenuation
695 *
696 * Voice volume is controlled by volume attenuation parameter.
697 * So volume becomes maximum when avol is 0 (no attenuation), and
698 * minimum when 255 (-96dB or silence).
699 */
700
701/* tables for volume->attenuation calculation */
702static unsigned char voltab1[128] = {
703 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
704 0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22,
705 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
706 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14,
707 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10,
708 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d,
709 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b,
710 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,
711 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,
712 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,
713 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02,
714 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
715 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
716};
717
718static unsigned char voltab2[128] = {
719 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a,
720 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21,
721 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a,
722 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15,
723 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10,
724 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d,
725 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a,
726 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
727 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
728 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
729 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
730 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
731 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
732};
733
734static unsigned char expressiontab[128] = {
735 0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42,
736 0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30,
737 0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,
738 0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e,
739 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18,
740 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13,
741 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f,
742 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c,
743 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09,
744 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
745 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
746 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
747 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
748};
749
750/*
751 * Magic to calculate the volume (actually attenuation) from all the
752 * voice and channels parameters.
753 */
754static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100755calc_volume(struct snd_emux_voice *vp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756{
757 int vol;
758 int main_vol, expression_vol, master_vol;
Takashi Iwai03da3122005-11-17 14:24:47 +0100759 struct snd_midi_channel *chan = vp->chan;
760 struct snd_emux_port *port = vp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
762 expression_vol = chan->control[MIDI_CTL_MSB_EXPRESSION];
763 LIMITMAX(vp->velocity, 127);
764 LIMITVALUE(expression_vol, 0, 127);
765 if (port->port_mode == SNDRV_EMUX_PORT_MODE_OSS_SYNTH) {
766 /* 0 - 127 */
767 main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME];
768 vol = (vp->velocity * main_vol * expression_vol) / (127*127);
769 vol = vol * vp->reg.amplitude / 127;
770
771 LIMITVALUE(vol, 0, 127);
772
773 /* calc to attenuation */
774 vol = snd_sf_vol_table[vol];
775
776 } else {
777 main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME] * vp->reg.amplitude / 127;
778 LIMITVALUE(main_vol, 0, 127);
779
780 vol = voltab1[main_vol] + voltab2[vp->velocity];
781 vol = (vol * 8) / 3;
782 vol += vp->reg.attenuation;
783 vol += ((0x100 - vol) * expressiontab[expression_vol])/128;
784 }
785
786 master_vol = port->chset.gs_master_volume;
787 LIMITVALUE(master_vol, 0, 127);
788 vol += snd_sf_vol_table[master_vol];
789 vol += port->volume_atten;
790
791#ifdef SNDRV_EMUX_USE_RAW_EFFECT
792 if (chan->private) {
Takashi Iwai03da3122005-11-17 14:24:47 +0100793 struct snd_emux_effect_table *fx = chan->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 vol += fx->val[EMUX_FX_ATTEN];
795 }
796#endif
797
798 LIMITVALUE(vol, 0, 255);
799 if (vp->avol == vol)
800 return 0; /* value unchanged */
801
802 vp->avol = vol;
803 if (!SF_IS_DRUM_BANK(get_bank(port, chan))
804 && LO_BYTE(vp->reg.parm.volatkhld) < 0x7d) {
805 int atten;
806 if (vp->velocity < 70)
807 atten = 70;
808 else
809 atten = vp->velocity;
810 vp->acutoff = (atten * vp->reg.parm.cutoff + 0xa0) >> 7;
811 } else {
812 vp->acutoff = vp->reg.parm.cutoff;
813 }
814
815 return 1; /* value changed */
816}
817
818/*
819 * calculate pitch offset
820 *
821 * 0xE000 is no pitch offset at 44100Hz sample.
822 * Every 4096 is one octave.
823 */
824
825static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100826calc_pitch(struct snd_emux_voice *vp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827{
Takashi Iwai03da3122005-11-17 14:24:47 +0100828 struct snd_midi_channel *chan = vp->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 int offset;
830
831 /* calculate offset */
832 if (vp->reg.fixkey >= 0) {
833 offset = (vp->reg.fixkey - vp->reg.root) * 4096 / 12;
834 } else {
835 offset = (vp->note - vp->reg.root) * 4096 / 12;
836 }
837 offset = (offset * vp->reg.scaleTuning) / 100;
838 offset += vp->reg.tune * 4096 / 1200;
839 if (chan->midi_pitchbend != 0) {
840 /* (128 * 8192: 1 semitone) ==> (4096: 12 semitones) */
841 offset += chan->midi_pitchbend * chan->gm_rpn_pitch_bend_range / 3072;
842 }
843
844 /* tuning via RPN:
845 * coarse = -8192 to 8192 (100 cent per 128)
846 * fine = -8192 to 8192 (max=100cent)
847 */
848 /* 4096 = 1200 cents in emu8000 parameter */
849 offset += chan->gm_rpn_coarse_tuning * 4096 / (12 * 128);
850 offset += chan->gm_rpn_fine_tuning / 24;
851
852#ifdef SNDRV_EMUX_USE_RAW_EFFECT
853 /* add initial pitch correction */
854 if (chan->private) {
Takashi Iwai03da3122005-11-17 14:24:47 +0100855 struct snd_emux_effect_table *fx = chan->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 if (fx->flag[EMUX_FX_INIT_PITCH])
857 offset += fx->val[EMUX_FX_INIT_PITCH];
858 }
859#endif
860
861 /* 0xe000: root pitch */
862 offset += 0xe000 + vp->reg.rate_offset;
863 offset += vp->emu->pitch_shift;
864 LIMITVALUE(offset, 0, 0xffff);
865 if (offset == vp->apitch)
866 return 0; /* unchanged */
867 vp->apitch = offset;
868 return 1; /* value changed */
869}
870
871/*
872 * Get the bank number assigned to the channel
873 */
874static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100875get_bank(struct snd_emux_port *port, struct snd_midi_channel *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876{
877 int val;
878
879 switch (port->chset.midi_mode) {
880 case SNDRV_MIDI_MODE_XG:
881 val = chan->control[MIDI_CTL_MSB_BANK];
882 if (val == 127)
883 return 128; /* return drum bank */
884 return chan->control[MIDI_CTL_LSB_BANK];
885
886 case SNDRV_MIDI_MODE_GS:
887 if (chan->drum_channel)
888 return 128;
889 /* ignore LSB (bank map) */
890 return chan->control[MIDI_CTL_MSB_BANK];
891
892 default:
893 if (chan->drum_channel)
894 return 128;
895 return chan->control[MIDI_CTL_MSB_BANK];
896 }
897}
898
899
900/* Look for the zones matching with the given note and velocity.
901 * The resultant zones are stored on table.
902 */
903static int
Takashi Iwai03da3122005-11-17 14:24:47 +0100904get_zone(struct snd_emux *emu, struct snd_emux_port *port,
905 int *notep, int vel, struct snd_midi_channel *chan,
906 struct snd_sf_zone **table)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907{
908 int preset, bank, def_preset, def_bank;
909
910 bank = get_bank(port, chan);
911 preset = chan->midi_program;
912
913 if (SF_IS_DRUM_BANK(bank)) {
914 def_preset = port->ctrls[EMUX_MD_DEF_DRUM];
915 def_bank = bank;
916 } else {
917 def_preset = preset;
918 def_bank = port->ctrls[EMUX_MD_DEF_BANK];
919 }
920
921 return snd_soundfont_search_zone(emu->sflist, notep, vel, preset, bank,
922 def_preset, def_bank,
923 table, SNDRV_EMUX_MAX_MULTI_VOICES);
924}
925
926/*
927 */
928void
Takashi Iwai03da3122005-11-17 14:24:47 +0100929snd_emux_init_voices(struct snd_emux *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930{
Takashi Iwai03da3122005-11-17 14:24:47 +0100931 struct snd_emux_voice *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 int i;
933 unsigned long flags;
934
935 spin_lock_irqsave(&emu->voice_lock, flags);
936 for (i = 0; i < emu->max_voices; i++) {
937 vp = &emu->voices[i];
938 vp->ch = -1; /* not used */
939 vp->state = SNDRV_EMUX_ST_OFF;
940 vp->chan = NULL;
941 vp->port = NULL;
942 vp->time = 0;
943 vp->emu = emu;
944 vp->hw = emu->hw;
945 }
946 spin_unlock_irqrestore(&emu->voice_lock, flags);
947}
948
949/*
950 */
Takashi Iwai03da3122005-11-17 14:24:47 +0100951void snd_emux_lock_voice(struct snd_emux *emu, int voice)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952{
953 unsigned long flags;
954
955 spin_lock_irqsave(&emu->voice_lock, flags);
956 if (emu->voices[voice].state == SNDRV_EMUX_ST_OFF)
957 emu->voices[voice].state = SNDRV_EMUX_ST_LOCKED;
958 else
959 snd_printk("invalid voice for lock %d (state = %x)\n",
960 voice, emu->voices[voice].state);
961 spin_unlock_irqrestore(&emu->voice_lock, flags);
962}
963
Takashi Iwai95ff17562006-04-28 15:13:40 +0200964EXPORT_SYMBOL(snd_emux_lock_voice);
965
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966/*
967 */
Takashi Iwai03da3122005-11-17 14:24:47 +0100968void snd_emux_unlock_voice(struct snd_emux *emu, int voice)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969{
970 unsigned long flags;
971
972 spin_lock_irqsave(&emu->voice_lock, flags);
973 if (emu->voices[voice].state == SNDRV_EMUX_ST_LOCKED)
974 emu->voices[voice].state = SNDRV_EMUX_ST_OFF;
975 else
976 snd_printk("invalid voice for unlock %d (state = %x)\n",
977 voice, emu->voices[voice].state);
978 spin_unlock_irqrestore(&emu->voice_lock, flags);
979}
Takashi Iwai95ff17562006-04-28 15:13:40 +0200980
981EXPORT_SYMBOL(snd_emux_unlock_voice);