~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/synth/emux/emux_synth.c

Version: ~ [ linux-5.3 ] ~ [ linux-5.2.15 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.73 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.144 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.193 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.193 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.73 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  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 <linux/export.h>
 26 #include "emux_voice.h"
 27 #include <sound/asoundef.h>
 28 
 29 /*
 30  * Prototypes
 31  */
 32 
 33 /*
 34  * Ensure a value is between two points
 35  * macro evaluates its args more than once, so changed to upper-case.
 36  */
 37 #define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0)
 38 #define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0)
 39 
 40 static int get_zone(struct snd_emux *emu, struct snd_emux_port *port,
 41                     int *notep, int vel, struct snd_midi_channel *chan,
 42                     struct snd_sf_zone **table);
 43 static int get_bank(struct snd_emux_port *port, struct snd_midi_channel *chan);
 44 static void terminate_note1(struct snd_emux *emu, int note,
 45                             struct snd_midi_channel *chan, int free);
 46 static void exclusive_note_off(struct snd_emux *emu, struct snd_emux_port *port,
 47                                int exclass);
 48 static void terminate_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int free);
 49 static void update_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int update);
 50 static void setup_voice(struct snd_emux_voice *vp);
 51 static int calc_pan(struct snd_emux_voice *vp);
 52 static int calc_volume(struct snd_emux_voice *vp);
 53 static int calc_pitch(struct snd_emux_voice *vp);
 54 
 55 
 56 /*
 57  * Start a note.
 58  */
 59 void
 60 snd_emux_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)
 61 {
 62         struct snd_emux *emu;
 63         int i, key, nvoices;
 64         struct snd_emux_voice *vp;
 65         struct snd_sf_zone *table[SNDRV_EMUX_MAX_MULTI_VOICES];
 66         unsigned long flags;
 67         struct snd_emux_port *port;
 68 
 69         port = p;
 70         if (snd_BUG_ON(!port || !chan))
 71                 return;
 72 
 73         emu = port->emu;
 74         if (snd_BUG_ON(!emu || !emu->ops.get_voice || !emu->ops.trigger))
 75                 return;
 76 
 77         key = note; /* remember the original note */
 78         nvoices = get_zone(emu, port, &note, vel, chan, table);
 79         if (! nvoices)
 80                 return;
 81 
 82         /* exclusive note off */
 83         for (i = 0; i < nvoices; i++) {
 84                 struct snd_sf_zone *zp = table[i];
 85                 if (zp && zp->v.exclusiveClass)
 86                         exclusive_note_off(emu, port, zp->v.exclusiveClass);
 87         }
 88 
 89 #if 0 // seems not necessary
 90         /* Turn off the same note on the same channel. */
 91         terminate_note1(emu, key, chan, 0);
 92 #endif
 93 
 94         spin_lock_irqsave(&emu->voice_lock, flags);
 95         for (i = 0; i < nvoices; i++) {
 96 
 97                 /* set up each voice parameter */
 98                 /* at this stage, we don't trigger the voice yet. */
 99 
100                 if (table[i] == NULL)
101                         continue;
102 
103                 vp = emu->ops.get_voice(emu, port);
104                 if (vp == NULL || vp->ch < 0)
105                         continue;
106                 if (STATE_IS_PLAYING(vp->state))
107                         emu->ops.terminate(vp);
108 
109                 vp->time = emu->use_time++;
110                 vp->chan = chan;
111                 vp->port = port;
112                 vp->key = key;
113                 vp->note = note;
114                 vp->velocity = vel;
115                 vp->zone = table[i];
116                 if (vp->zone->sample)
117                         vp->block = vp->zone->sample->block;
118                 else
119                         vp->block = NULL;
120 
121                 setup_voice(vp);
122 
123                 vp->state = SNDRV_EMUX_ST_STANDBY;
124                 if (emu->ops.prepare) {
125                         vp->state = SNDRV_EMUX_ST_OFF;
126                         if (emu->ops.prepare(vp) >= 0)
127                                 vp->state = SNDRV_EMUX_ST_STANDBY;
128                 }
129         }
130 
131         /* start envelope now */
132         for (i = 0; i < emu->max_voices; i++) {
133                 vp = &emu->voices[i];
134                 if (vp->state == SNDRV_EMUX_ST_STANDBY &&
135                     vp->chan == chan) {
136                         emu->ops.trigger(vp);
137                         vp->state = SNDRV_EMUX_ST_ON;
138                         vp->ontime = jiffies; /* remember the trigger timing */
139                 }
140         }
141         spin_unlock_irqrestore(&emu->voice_lock, flags);
142 
143 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
144         if (port->port_mode == SNDRV_EMUX_PORT_MODE_OSS_SYNTH) {
145                 /* clear voice position for the next note on this channel */
146                 struct snd_emux_effect_table *fx = chan->private;
147                 if (fx) {
148                         fx->flag[EMUX_FX_SAMPLE_START] = 0;
149                         fx->flag[EMUX_FX_COARSE_SAMPLE_START] = 0;
150                 }
151         }
152 #endif
153 }
154 
155 /*
156  * Release a note in response to a midi note off.
157  */
158 void
159 snd_emux_note_off(void *p, int note, int vel, struct snd_midi_channel *chan)
160 {
161         int ch;
162         struct snd_emux *emu;
163         struct snd_emux_voice *vp;
164         unsigned long flags;
165         struct snd_emux_port *port;
166 
167         port = p;
168         if (snd_BUG_ON(!port || !chan))
169                 return;
170 
171         emu = port->emu;
172         if (snd_BUG_ON(!emu || !emu->ops.release))
173                 return;
174 
175         spin_lock_irqsave(&emu->voice_lock, flags);
176         for (ch = 0; ch < emu->max_voices; ch++) {
177                 vp = &emu->voices[ch];
178                 if (STATE_IS_PLAYING(vp->state) &&
179                     vp->chan == chan && vp->key == note) {
180                         vp->state = SNDRV_EMUX_ST_RELEASED;
181                         if (vp->ontime == jiffies) {
182                                 /* if note-off is sent too shortly after
183                                  * note-on, emuX engine cannot produce the sound
184                                  * correctly.  so we'll release this note
185                                  * a bit later via timer callback.
186                                  */
187                                 vp->state = SNDRV_EMUX_ST_PENDING;
188                                 if (! emu->timer_active) {
189                                         mod_timer(&emu->tlist, jiffies + 1);
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  */
205 void snd_emux_timer_callback(unsigned long data)
206 {
207         struct snd_emux *emu = (struct snd_emux *) data;
208         struct snd_emux_voice *vp;
209         unsigned long flags;
210         int ch, do_again = 0;
211 
212         spin_lock_irqsave(&emu->voice_lock, flags);
213         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                 mod_timer(&emu->tlist, jiffies + 1);
226                 emu->timer_active = 1;
227         } else
228                 emu->timer_active = 0;
229         spin_unlock_irqrestore(&emu->voice_lock, flags);
230 }
231 
232 /*
233  * key pressure change
234  */
235 void
236 snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan)
237 {
238         int ch;
239         struct snd_emux *emu;
240         struct snd_emux_voice *vp;
241         unsigned long flags;
242         struct snd_emux_port *port;
243 
244         port = p;
245         if (snd_BUG_ON(!port || !chan))
246                 return;
247 
248         emu = port->emu;
249         if (snd_BUG_ON(!emu || !emu->ops.update))
250                 return;
251 
252         spin_lock_irqsave(&emu->voice_lock, flags);
253         for (ch = 0; ch < emu->max_voices; ch++) {
254                 vp = &emu->voices[ch];
255                 if (vp->state == SNDRV_EMUX_ST_ON &&
256                     vp->chan == chan && vp->key == note) {
257                         vp->velocity = vel;
258                         update_voice(emu, vp, SNDRV_EMUX_UPDATE_VOLUME);
259                 }
260         }
261         spin_unlock_irqrestore(&emu->voice_lock, flags);
262 }
263 
264 
265 /*
266  * Modulate the voices which belong to the channel
267  */
268 void
269 snd_emux_update_channel(struct snd_emux_port *port, struct snd_midi_channel *chan, int update)
270 {
271         struct snd_emux *emu;
272         struct snd_emux_voice *vp;
273         int i;
274         unsigned long flags;
275 
276         if (! update)
277                 return;
278 
279         emu = port->emu;
280         if (snd_BUG_ON(!emu || !emu->ops.update))
281                 return;
282 
283         spin_lock_irqsave(&emu->voice_lock, flags);
284         for (i = 0; i < emu->max_voices; i++) {
285                 vp = &emu->voices[i];
286                 if (vp->chan == chan)
287                         update_voice(emu, vp, update);
288         }
289         spin_unlock_irqrestore(&emu->voice_lock, flags);
290 }
291 
292 /*
293  * Modulate all the voices which belong to the port.
294  */
295 void
296 snd_emux_update_port(struct snd_emux_port *port, int update)
297 {
298         struct snd_emux *emu; 
299         struct snd_emux_voice *vp;
300         int i;
301         unsigned long flags;
302 
303         if (! update)
304                 return;
305 
306         emu = port->emu;
307         if (snd_BUG_ON(!emu || !emu->ops.update))
308                 return;
309 
310         spin_lock_irqsave(&emu->voice_lock, flags);
311         for (i = 0; i < emu->max_voices; i++) {
312                 vp = &emu->voices[i];
313                 if (vp->port == port)
314                         update_voice(emu, vp, update);
315         }
316         spin_unlock_irqrestore(&emu->voice_lock, flags);
317 }
318 
319 
320 /*
321  * Deal with a controller type event.  This includes all types of
322  * control events, not just the midi controllers
323  */
324 void
325 snd_emux_control(void *p, int type, struct snd_midi_channel *chan)
326 {
327         struct snd_emux_port *port;
328 
329         port = p;
330         if (snd_BUG_ON(!port || !chan))
331                 return;
332 
333         switch (type) {
334         case MIDI_CTL_MSB_MAIN_VOLUME:
335         case MIDI_CTL_MSB_EXPRESSION:
336                 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_VOLUME);
337                 break;
338                 
339         case MIDI_CTL_MSB_PAN:
340                 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PAN);
341                 break;
342 
343         case MIDI_CTL_SOFT_PEDAL:
344 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
345                 /* FIXME: this is an emulation */
346                 if (chan->control[type] >= 64)
347                         snd_emux_send_effect(port, chan, EMUX_FX_CUTOFF, -160,
348                                      EMUX_FX_FLAG_ADD);
349                 else
350                         snd_emux_send_effect(port, chan, EMUX_FX_CUTOFF, 0,
351                                      EMUX_FX_FLAG_OFF);
352 #endif
353                 break;
354 
355         case MIDI_CTL_PITCHBEND:
356                 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PITCH);
357                 break;
358 
359         case MIDI_CTL_MSB_MODWHEEL:
360         case MIDI_CTL_CHAN_PRESSURE:
361                 snd_emux_update_channel(port, chan,
362                                         SNDRV_EMUX_UPDATE_FMMOD |
363                                         SNDRV_EMUX_UPDATE_FM2FRQ2);
364                 break;
365 
366         }
367 
368         if (port->chset.midi_mode == SNDRV_MIDI_MODE_XG) {
369                 snd_emux_xg_control(port, chan, type);
370         }
371 }
372 
373 
374 /*
375  * terminate note - if free flag is true, free the terminated voice
376  */
377 static void
378 terminate_note1(struct snd_emux *emu, int note, struct snd_midi_channel *chan, int free)
379 {
380         int  i;
381         struct snd_emux_voice *vp;
382         unsigned long flags;
383 
384         spin_lock_irqsave(&emu->voice_lock, flags);
385         for (i = 0; i < emu->max_voices; i++) {
386                 vp = &emu->voices[i];
387                 if (STATE_IS_PLAYING(vp->state) && vp->chan == chan &&
388                     vp->key == note)
389                         terminate_voice(emu, vp, free);
390         }
391         spin_unlock_irqrestore(&emu->voice_lock, flags);
392 }
393 
394 
395 /*
396  * terminate note - exported for midi emulation
397  */
398 void
399 snd_emux_terminate_note(void *p, int note, struct snd_midi_channel *chan)
400 {
401         struct snd_emux *emu;
402         struct snd_emux_port *port;
403 
404         port = p;
405         if (snd_BUG_ON(!port || !chan))
406                 return;
407 
408         emu = port->emu;
409         if (snd_BUG_ON(!emu || !emu->ops.terminate))
410                 return;
411 
412         terminate_note1(emu, note, chan, 1);
413 }
414 
415 
416 /*
417  * Terminate all the notes
418  */
419 void
420 snd_emux_terminate_all(struct snd_emux *emu)
421 {
422         int i;
423         struct snd_emux_voice *vp;
424         unsigned long flags;
425 
426         spin_lock_irqsave(&emu->voice_lock, flags);
427         for (i = 0; i < emu->max_voices; i++) {
428                 vp = &emu->voices[i];
429                 if (STATE_IS_PLAYING(vp->state))
430                         terminate_voice(emu, vp, 0);
431                 if (vp->state == SNDRV_EMUX_ST_OFF) {
432                         if (emu->ops.free_voice)
433                                 emu->ops.free_voice(vp);
434                         if (emu->ops.reset)
435                                 emu->ops.reset(emu, i);
436                 }
437                 vp->time = 0;
438         }
439         /* initialize allocation time */
440         emu->use_time = 0;
441         spin_unlock_irqrestore(&emu->voice_lock, flags);
442 }
443 
444 EXPORT_SYMBOL(snd_emux_terminate_all);
445 
446 /*
447  * Terminate all voices associated with the given port
448  */
449 void
450 snd_emux_sounds_off_all(struct snd_emux_port *port)
451 {
452         int i;
453         struct snd_emux *emu;
454         struct snd_emux_voice *vp;
455         unsigned long flags;
456 
457         if (snd_BUG_ON(!port))
458                 return;
459         emu = port->emu;
460         if (snd_BUG_ON(!emu || !emu->ops.terminate))
461                 return;
462 
463         spin_lock_irqsave(&emu->voice_lock, flags);
464         for (i = 0; i < emu->max_voices; i++) {
465                 vp = &emu->voices[i];
466                 if (STATE_IS_PLAYING(vp->state) &&
467                     vp->port == port)
468                         terminate_voice(emu, vp, 0);
469                 if (vp->state == SNDRV_EMUX_ST_OFF) {
470                         if (emu->ops.free_voice)
471                                 emu->ops.free_voice(vp);
472                         if (emu->ops.reset)
473                                 emu->ops.reset(emu, i);
474                 }
475         }
476         spin_unlock_irqrestore(&emu->voice_lock, flags);
477 }
478 
479 
480 /*
481  * Terminate all voices that have the same exclusive class.  This
482  * is mainly for drums.
483  */
484 static void
485 exclusive_note_off(struct snd_emux *emu, struct snd_emux_port *port, int exclass)
486 {
487         struct snd_emux_voice *vp;
488         int  i;
489         unsigned long flags;
490 
491         spin_lock_irqsave(&emu->voice_lock, flags);
492         for (i = 0; i < emu->max_voices; i++) {
493                 vp = &emu->voices[i];
494                 if (STATE_IS_PLAYING(vp->state) && vp->port == port &&
495                     vp->reg.exclusiveClass == exclass) {
496                         terminate_voice(emu, vp, 0);
497                 }
498         }
499         spin_unlock_irqrestore(&emu->voice_lock, flags);
500 }
501 
502 /*
503  * terminate a voice
504  * if free flag is true, call free_voice after termination
505  */
506 static void
507 terminate_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int free)
508 {
509         emu->ops.terminate(vp);
510         vp->time = emu->use_time++;
511         vp->chan = NULL;
512         vp->port = NULL;
513         vp->zone = NULL;
514         vp->block = NULL;
515         vp->state = SNDRV_EMUX_ST_OFF;
516         if (free && emu->ops.free_voice)
517                 emu->ops.free_voice(vp);
518 }
519 
520 
521 /*
522  * Modulate the voice
523  */
524 static void
525 update_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int update)
526 {
527         if (!STATE_IS_PLAYING(vp->state))
528                 return;
529 
530         if (vp->chan == NULL || vp->port == NULL)
531                 return;
532         if (update & SNDRV_EMUX_UPDATE_VOLUME)
533                 calc_volume(vp);
534         if (update & SNDRV_EMUX_UPDATE_PITCH)
535                 calc_pitch(vp);
536         if (update & SNDRV_EMUX_UPDATE_PAN) {
537                 if (! calc_pan(vp) && (update == SNDRV_EMUX_UPDATE_PAN))
538                         return;
539         }
540         emu->ops.update(vp, update);
541 }
542 
543 
544 #if 0 // not used
545 /* table for volume target calculation */
546 static unsigned short voltarget[16] = { 
547         0xEAC0, 0xE0C8, 0xD740, 0xCE20, 0xC560, 0xBD08, 0xB500, 0xAD58,
548         0xA5F8, 0x9EF0, 0x9830, 0x91C0, 0x8B90, 0x85A8, 0x8000, 0x7A90
549 };
550 #endif
551 
552 #define LO_BYTE(v)      ((v) & 0xff)
553 #define HI_BYTE(v)      (((v) >> 8) & 0xff)
554 
555 /*
556  * Sets up the voice structure by calculating some values that
557  * will be needed later.
558  */
559 static void
560 setup_voice(struct snd_emux_voice *vp)
561 {
562         struct soundfont_voice_parm *parm;
563         int pitch;
564 
565         /* copy the original register values */
566         vp->reg = vp->zone->v;
567 
568 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
569         snd_emux_setup_effect(vp);
570 #endif
571 
572         /* reset status */
573         vp->apan = -1;
574         vp->avol = -1;
575         vp->apitch = -1;
576 
577         calc_volume(vp);
578         calc_pitch(vp);
579         calc_pan(vp);
580 
581         parm = &vp->reg.parm;
582 
583         /* compute filter target and correct modulation parameters */
584         if (LO_BYTE(parm->modatkhld) >= 0x80 && parm->moddelay >= 0x8000) {
585                 parm->moddelay = 0xbfff;
586                 pitch = (HI_BYTE(parm->pefe) << 4) + vp->apitch;
587                 if (pitch > 0xffff)
588                         pitch = 0xffff;
589                 /* calculate filter target */
590                 vp->ftarget = parm->cutoff + LO_BYTE(parm->pefe);
591                 LIMITVALUE(vp->ftarget, 0, 255);
592                 vp->ftarget <<= 8;
593         } else {
594                 vp->ftarget = parm->cutoff;
595                 vp->ftarget <<= 8;
596                 pitch = vp->apitch;
597         }
598 
599         /* compute pitch target */
600         if (pitch != 0xffff) {
601                 vp->ptarget = 1 << (pitch >> 12);
602                 if (pitch & 0x800) vp->ptarget += (vp->ptarget*0x102e)/0x2710;
603                 if (pitch & 0x400) vp->ptarget += (vp->ptarget*0x764)/0x2710;
604                 if (pitch & 0x200) vp->ptarget += (vp->ptarget*0x389)/0x2710;
605                 vp->ptarget += (vp->ptarget >> 1);
606                 if (vp->ptarget > 0xffff) vp->ptarget = 0xffff;
607         } else
608                 vp->ptarget = 0xffff;
609 
610         if (LO_BYTE(parm->modatkhld) >= 0x80) {
611                 parm->modatkhld &= ~0xff;
612                 parm->modatkhld |= 0x7f;
613         }
614 
615         /* compute volume target and correct volume parameters */
616         vp->vtarget = 0;
617 #if 0 /* FIXME: this leads to some clicks.. */
618         if (LO_BYTE(parm->volatkhld) >= 0x80 && parm->voldelay >= 0x8000) {
619                 parm->voldelay = 0xbfff;
620                 vp->vtarget = voltarget[vp->avol % 0x10] >> (vp->avol >> 4);
621         }
622 #endif
623 
624         if (LO_BYTE(parm->volatkhld) >= 0x80) {
625                 parm->volatkhld &= ~0xff;
626                 parm->volatkhld |= 0x7f;
627         }
628 }
629 
630 /*
631  * calculate pitch parameter
632  */
633 static unsigned char pan_volumes[256] = {
634 0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x14,0x17,0x1a,0x1d,0x20,0x22,0x25,0x28,0x2a,
635 0x2d,0x30,0x32,0x35,0x37,0x3a,0x3c,0x3f,0x41,0x44,0x46,0x49,0x4b,0x4d,0x50,0x52,
636 0x54,0x57,0x59,0x5b,0x5d,0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6f,0x71,0x73,0x75,
637 0x77,0x79,0x7b,0x7c,0x7e,0x80,0x82,0x84,0x86,0x88,0x89,0x8b,0x8d,0x8f,0x90,0x92,
638 0x94,0x96,0x97,0x99,0x9a,0x9c,0x9e,0x9f,0xa1,0xa2,0xa4,0xa5,0xa7,0xa8,0xaa,0xab,
639 0xad,0xae,0xaf,0xb1,0xb2,0xb3,0xb5,0xb6,0xb7,0xb9,0xba,0xbb,0xbc,0xbe,0xbf,0xc0,
640 0xc1,0xc2,0xc3,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,
641 0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdc,0xdd,0xde,0xdf,
642 0xdf,0xe0,0xe1,0xe2,0xe2,0xe3,0xe4,0xe4,0xe5,0xe6,0xe6,0xe7,0xe8,0xe8,0xe9,0xe9,
643 0xea,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf1,0xf1,0xf1,
644 0xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,0xf7,
645 0xf7,0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,
646 0xfb,0xfb,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
647 0xfd,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
648 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
649 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
650 };
651 
652 static int
653 calc_pan(struct snd_emux_voice *vp)
654 {
655         struct snd_midi_channel *chan = vp->chan;
656         int pan;
657 
658         /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */
659         if (vp->reg.fixpan > 0) /* 0-127 */
660                 pan = 255 - (int)vp->reg.fixpan * 2;
661         else {
662                 pan = chan->control[MIDI_CTL_MSB_PAN] - 64;
663                 if (vp->reg.pan >= 0) /* 0-127 */
664                         pan += vp->reg.pan - 64;
665                 pan = 127 - (int)pan * 2;
666         }
667         LIMITVALUE(pan, 0, 255);
668 
669         if (vp->emu->linear_panning) {
670                 /* assuming linear volume */
671                 if (pan != vp->apan) {
672                         vp->apan = pan;
673                         if (pan == 0)
674                                 vp->aaux = 0xff;
675                         else
676                                 vp->aaux = (-pan) & 0xff;
677                         return 1;
678                 } else
679                         return 0;
680         } else {
681                 /* using volume table */
682                 if (vp->apan != (int)pan_volumes[pan]) {
683                         vp->apan = pan_volumes[pan];
684                         vp->aaux = pan_volumes[255 - pan];
685                         return 1;
686                 }
687                 return 0;
688         }
689 }
690 
691 
692 /*
693  * calculate volume attenuation
694  *
695  * Voice volume is controlled by volume attenuation parameter.
696  * So volume becomes maximum when avol is 0 (no attenuation), and
697  * minimum when 255 (-96dB or silence).
698  */
699 
700 /* tables for volume->attenuation calculation */
701 static unsigned char voltab1[128] = {
702    0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
703    0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22,
704    0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
705    0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14,
706    0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10,
707    0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d,
708    0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b,
709    0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,
710    0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,
711    0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,
712    0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02,
713    0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
714    0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
715 };
716 
717 static unsigned char voltab2[128] = {
718    0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a,
719    0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21,
720    0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a,
721    0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15,
722    0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10,
723    0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d,
724    0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a,
725    0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
726    0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
727    0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
728    0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
729    0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
730    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
731 };
732 
733 static unsigned char expressiontab[128] = {
734    0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42,
735    0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30,
736    0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,
737    0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e,
738    0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18,
739    0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13,
740    0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f,
741    0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c,
742    0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09,
743    0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
744    0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
745    0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
746    0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
747 };
748 
749 /*
750  * Magic to calculate the volume (actually attenuation) from all the
751  * voice and channels parameters.
752  */
753 static int
754 calc_volume(struct snd_emux_voice *vp)
755 {
756         int vol;
757         int main_vol, expression_vol, master_vol;
758         struct snd_midi_channel *chan = vp->chan;
759         struct snd_emux_port *port = vp->port;
760 
761         expression_vol = chan->control[MIDI_CTL_MSB_EXPRESSION];
762         LIMITMAX(vp->velocity, 127);
763         LIMITVALUE(expression_vol, 0, 127);
764         if (port->port_mode == SNDRV_EMUX_PORT_MODE_OSS_SYNTH) {
765                 /* 0 - 127 */
766                 main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME];
767                 vol = (vp->velocity * main_vol * expression_vol) / (127*127);
768                 vol = vol * vp->reg.amplitude / 127;
769 
770                 LIMITVALUE(vol, 0, 127);
771 
772                 /* calc to attenuation */
773                 vol = snd_sf_vol_table[vol];
774 
775         } else {
776                 main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME] * vp->reg.amplitude / 127;
777                 LIMITVALUE(main_vol, 0, 127);
778 
779                 vol = voltab1[main_vol] + voltab2[vp->velocity];
780                 vol = (vol * 8) / 3;
781                 vol += vp->reg.attenuation;
782                 vol += ((0x100 - vol) * expressiontab[expression_vol])/128;
783         }
784 
785         master_vol = port->chset.gs_master_volume;
786         LIMITVALUE(master_vol, 0, 127);
787         vol += snd_sf_vol_table[master_vol];
788         vol += port->volume_atten;
789 
790 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
791         if (chan->private) {
792                 struct snd_emux_effect_table *fx = chan->private;
793                 vol += fx->val[EMUX_FX_ATTEN];
794         }
795 #endif
796 
797         LIMITVALUE(vol, 0, 255);
798         if (vp->avol == vol)
799                 return 0; /* value unchanged */
800 
801         vp->avol = vol;
802         if (!SF_IS_DRUM_BANK(get_bank(port, chan))
803             && LO_BYTE(vp->reg.parm.volatkhld) < 0x7d) {
804                 int atten;
805                 if (vp->velocity < 70)
806                         atten = 70;
807                 else
808                         atten = vp->velocity;
809                 vp->acutoff = (atten * vp->reg.parm.cutoff + 0xa0) >> 7;
810         } else {
811                 vp->acutoff = vp->reg.parm.cutoff;
812         }
813 
814         return 1; /* value changed */
815 }
816 
817 /*
818  * calculate pitch offset
819  *
820  * 0xE000 is no pitch offset at 44100Hz sample.
821  * Every 4096 is one octave.
822  */
823 
824 static int
825 calc_pitch(struct snd_emux_voice *vp)
826 {
827         struct snd_midi_channel *chan = vp->chan;
828         int offset;
829 
830         /* calculate offset */
831         if (vp->reg.fixkey >= 0) {
832                 offset = (vp->reg.fixkey - vp->reg.root) * 4096 / 12;
833         } else {
834                 offset = (vp->note - vp->reg.root) * 4096 / 12;
835         }
836         offset = (offset * vp->reg.scaleTuning) / 100;
837         offset += vp->reg.tune * 4096 / 1200;
838         if (chan->midi_pitchbend != 0) {
839                 /* (128 * 8192: 1 semitone) ==> (4096: 12 semitones) */
840                 offset += chan->midi_pitchbend * chan->gm_rpn_pitch_bend_range / 3072;
841         }
842 
843         /* tuning via RPN:
844          *   coarse = -8192 to 8192 (100 cent per 128)
845          *   fine = -8192 to 8192 (max=100cent)
846          */
847         /* 4096 = 1200 cents in emu8000 parameter */
848         offset += chan->gm_rpn_coarse_tuning * 4096 / (12 * 128);
849         offset += chan->gm_rpn_fine_tuning / 24;
850 
851 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
852         /* add initial pitch correction */
853         if (chan->private) {
854                 struct snd_emux_effect_table *fx = chan->private;
855                 if (fx->flag[EMUX_FX_INIT_PITCH])
856                         offset += fx->val[EMUX_FX_INIT_PITCH];
857         }
858 #endif
859 
860         /* 0xe000: root pitch */
861         offset += 0xe000 + vp->reg.rate_offset;
862         offset += vp->emu->pitch_shift;
863         LIMITVALUE(offset, 0, 0xffff);
864         if (offset == vp->apitch)
865                 return 0; /* unchanged */
866         vp->apitch = offset;
867         return 1; /* value changed */
868 }
869 
870 /*
871  * Get the bank number assigned to the channel
872  */
873 static int
874 get_bank(struct snd_emux_port *port, struct snd_midi_channel *chan)
875 {
876         int val;
877 
878         switch (port->chset.midi_mode) {
879         case SNDRV_MIDI_MODE_XG:
880                 val = chan->control[MIDI_CTL_MSB_BANK];
881                 if (val == 127)
882                         return 128; /* return drum bank */
883                 return chan->control[MIDI_CTL_LSB_BANK];
884 
885         case SNDRV_MIDI_MODE_GS:
886                 if (chan->drum_channel)
887                         return 128;
888                 /* ignore LSB (bank map) */
889                 return chan->control[MIDI_CTL_MSB_BANK];
890                 
891         default:
892                 if (chan->drum_channel)
893                         return 128;
894                 return chan->control[MIDI_CTL_MSB_BANK];
895         }
896 }
897 
898 
899 /* Look for the zones matching with the given note and velocity.
900  * The resultant zones are stored on table.
901  */
902 static int
903 get_zone(struct snd_emux *emu, struct snd_emux_port *port,
904          int *notep, int vel, struct snd_midi_channel *chan,
905          struct snd_sf_zone **table)
906 {
907         int preset, bank, def_preset, def_bank;
908 
909         bank = get_bank(port, chan);
910         preset = chan->midi_program;
911 
912         if (SF_IS_DRUM_BANK(bank)) {
913                 def_preset = port->ctrls[EMUX_MD_DEF_DRUM];
914                 def_bank = bank;
915         } else {
916                 def_preset = preset;
917                 def_bank = port->ctrls[EMUX_MD_DEF_BANK];
918         }
919 
920         return snd_soundfont_search_zone(emu->sflist, notep, vel, preset, bank,
921                                          def_preset, def_bank,
922                                          table, SNDRV_EMUX_MAX_MULTI_VOICES);
923 }
924 
925 /*
926  */
927 void
928 snd_emux_init_voices(struct snd_emux *emu)
929 {
930         struct snd_emux_voice *vp;
931         int i;
932         unsigned long flags;
933 
934         spin_lock_irqsave(&emu->voice_lock, flags);
935         for (i = 0; i < emu->max_voices; i++) {
936                 vp = &emu->voices[i];
937                 vp->ch = -1; /* not used */
938                 vp->state = SNDRV_EMUX_ST_OFF;
939                 vp->chan = NULL;
940                 vp->port = NULL;
941                 vp->time = 0;
942                 vp->emu = emu;
943                 vp->hw = emu->hw;
944         }
945         spin_unlock_irqrestore(&emu->voice_lock, flags);
946 }
947 
948 /*
949  */
950 void snd_emux_lock_voice(struct snd_emux *emu, int voice)
951 {
952         unsigned long flags;
953 
954         spin_lock_irqsave(&emu->voice_lock, flags);
955         if (emu->voices[voice].state == SNDRV_EMUX_ST_OFF)
956                 emu->voices[voice].state = SNDRV_EMUX_ST_LOCKED;
957         else
958                 snd_printk(KERN_WARNING
959                            "invalid voice for lock %d (state = %x)\n",
960                            voice, emu->voices[voice].state);
961         spin_unlock_irqrestore(&emu->voice_lock, flags);
962 }
963 
964 EXPORT_SYMBOL(snd_emux_lock_voice);
965 
966 /*
967  */
968 void snd_emux_unlock_voice(struct snd_emux *emu, int voice)
969 {
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(KERN_WARNING
977                            "invalid voice for unlock %d (state = %x)\n",
978                            voice, emu->voices[voice].state);
979         spin_unlock_irqrestore(&emu->voice_lock, flags);
980 }
981 
982 EXPORT_SYMBOL(snd_emux_unlock_voice);
983 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp