OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [sound/] [synth/] [emux/] [emux_synth.c] - Blame information for rev 3

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.