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

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

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ 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.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | 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.

sflogo.php