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

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

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

~ [ 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