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