Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/synth/emux/soundfont.c
10817 views
1
/*
2
* Soundfont generic routines.
3
* It is intended that these should be used by any driver that is willing
4
* to accept soundfont patches.
5
*
6
* Copyright (C) 1999 Steve Ratcliffe
7
* Copyright (c) 1999-2000 Takashi Iwai <[email protected]>
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
* Deal with reading in of a soundfont. Code follows the OSS way
25
* of doing things so that the old sfxload utility can be used.
26
* Everything may change when there is an alsa way of doing things.
27
*/
28
#include <asm/uaccess.h>
29
#include <linux/slab.h>
30
#include <sound/core.h>
31
#include <sound/soundfont.h>
32
#include <sound/seq_oss_legacy.h>
33
34
/* Prototypes for static functions */
35
36
static int open_patch(struct snd_sf_list *sflist, const char __user *data,
37
int count, int client);
38
static struct snd_soundfont *newsf(struct snd_sf_list *sflist, int type, char *name);
39
static int is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name);
40
static int close_patch(struct snd_sf_list *sflist);
41
static int probe_data(struct snd_sf_list *sflist, int sample_id);
42
static void set_zone_counter(struct snd_sf_list *sflist,
43
struct snd_soundfont *sf, struct snd_sf_zone *zp);
44
static struct snd_sf_zone *sf_zone_new(struct snd_sf_list *sflist,
45
struct snd_soundfont *sf);
46
static void set_sample_counter(struct snd_sf_list *sflist,
47
struct snd_soundfont *sf, struct snd_sf_sample *sp);
48
static struct snd_sf_sample *sf_sample_new(struct snd_sf_list *sflist,
49
struct snd_soundfont *sf);
50
static void sf_sample_delete(struct snd_sf_list *sflist,
51
struct snd_soundfont *sf, struct snd_sf_sample *sp);
52
static int load_map(struct snd_sf_list *sflist, const void __user *data, int count);
53
static int load_info(struct snd_sf_list *sflist, const void __user *data, long count);
54
static int remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf,
55
int bank, int instr);
56
static void init_voice_info(struct soundfont_voice_info *avp);
57
static void init_voice_parm(struct soundfont_voice_parm *pp);
58
static struct snd_sf_sample *set_sample(struct snd_soundfont *sf,
59
struct soundfont_voice_info *avp);
60
static struct snd_sf_sample *find_sample(struct snd_soundfont *sf, int sample_id);
61
static int load_data(struct snd_sf_list *sflist, const void __user *data, long count);
62
static void rebuild_presets(struct snd_sf_list *sflist);
63
static void add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur);
64
static void delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp);
65
static struct snd_sf_zone *search_first_zone(struct snd_sf_list *sflist,
66
int bank, int preset, int key);
67
static int search_zones(struct snd_sf_list *sflist, int *notep, int vel,
68
int preset, int bank, struct snd_sf_zone **table,
69
int max_layers, int level);
70
static int get_index(int bank, int instr, int key);
71
static void snd_sf_init(struct snd_sf_list *sflist);
72
static void snd_sf_clear(struct snd_sf_list *sflist);
73
74
/*
75
* lock access to sflist
76
*/
77
static void
78
lock_preset(struct snd_sf_list *sflist)
79
{
80
unsigned long flags;
81
mutex_lock(&sflist->presets_mutex);
82
spin_lock_irqsave(&sflist->lock, flags);
83
sflist->presets_locked = 1;
84
spin_unlock_irqrestore(&sflist->lock, flags);
85
}
86
87
88
/*
89
* remove lock
90
*/
91
static void
92
unlock_preset(struct snd_sf_list *sflist)
93
{
94
unsigned long flags;
95
spin_lock_irqsave(&sflist->lock, flags);
96
sflist->presets_locked = 0;
97
spin_unlock_irqrestore(&sflist->lock, flags);
98
mutex_unlock(&sflist->presets_mutex);
99
}
100
101
102
/*
103
* close the patch if the patch was opened by this client.
104
*/
105
int
106
snd_soundfont_close_check(struct snd_sf_list *sflist, int client)
107
{
108
unsigned long flags;
109
spin_lock_irqsave(&sflist->lock, flags);
110
if (sflist->open_client == client) {
111
spin_unlock_irqrestore(&sflist->lock, flags);
112
return close_patch(sflist);
113
}
114
spin_unlock_irqrestore(&sflist->lock, flags);
115
return 0;
116
}
117
118
119
/*
120
* Deal with a soundfont patch. Any driver could use these routines
121
* although it was designed for the AWE64.
122
*
123
* The sample_write and callargs pararameters allow a callback into
124
* the actual driver to write sample data to the board or whatever
125
* it wants to do with it.
126
*/
127
int
128
snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data,
129
long count, int client)
130
{
131
struct soundfont_patch_info patch;
132
unsigned long flags;
133
int rc;
134
135
if (count < (long)sizeof(patch)) {
136
snd_printk(KERN_ERR "patch record too small %ld\n", count);
137
return -EINVAL;
138
}
139
if (copy_from_user(&patch, data, sizeof(patch)))
140
return -EFAULT;
141
142
count -= sizeof(patch);
143
data += sizeof(patch);
144
145
if (patch.key != SNDRV_OSS_SOUNDFONT_PATCH) {
146
snd_printk(KERN_ERR "The wrong kind of patch %x\n", patch.key);
147
return -EINVAL;
148
}
149
if (count < patch.len) {
150
snd_printk(KERN_ERR "Patch too short %ld, need %d\n",
151
count, patch.len);
152
return -EINVAL;
153
}
154
if (patch.len < 0) {
155
snd_printk(KERN_ERR "poor length %d\n", patch.len);
156
return -EINVAL;
157
}
158
159
if (patch.type == SNDRV_SFNT_OPEN_PATCH) {
160
/* grab sflist to open */
161
lock_preset(sflist);
162
rc = open_patch(sflist, data, count, client);
163
unlock_preset(sflist);
164
return rc;
165
}
166
167
/* check if other client already opened patch */
168
spin_lock_irqsave(&sflist->lock, flags);
169
if (sflist->open_client != client) {
170
spin_unlock_irqrestore(&sflist->lock, flags);
171
return -EBUSY;
172
}
173
spin_unlock_irqrestore(&sflist->lock, flags);
174
175
lock_preset(sflist);
176
rc = -EINVAL;
177
switch (patch.type) {
178
case SNDRV_SFNT_LOAD_INFO:
179
rc = load_info(sflist, data, count);
180
break;
181
case SNDRV_SFNT_LOAD_DATA:
182
rc = load_data(sflist, data, count);
183
break;
184
case SNDRV_SFNT_CLOSE_PATCH:
185
rc = close_patch(sflist);
186
break;
187
case SNDRV_SFNT_REPLACE_DATA:
188
/*rc = replace_data(&patch, data, count);*/
189
break;
190
case SNDRV_SFNT_MAP_PRESET:
191
rc = load_map(sflist, data, count);
192
break;
193
case SNDRV_SFNT_PROBE_DATA:
194
rc = probe_data(sflist, patch.optarg);
195
break;
196
case SNDRV_SFNT_REMOVE_INFO:
197
/* patch must be opened */
198
if (!sflist->currsf) {
199
snd_printk(KERN_ERR "soundfont: remove_info: "
200
"patch not opened\n");
201
rc = -EINVAL;
202
} else {
203
int bank, instr;
204
bank = ((unsigned short)patch.optarg >> 8) & 0xff;
205
instr = (unsigned short)patch.optarg & 0xff;
206
if (! remove_info(sflist, sflist->currsf, bank, instr))
207
rc = -EINVAL;
208
else
209
rc = 0;
210
}
211
break;
212
}
213
unlock_preset(sflist);
214
215
return rc;
216
}
217
218
219
/* check if specified type is special font (GUS or preset-alias) */
220
static inline int
221
is_special_type(int type)
222
{
223
type &= 0x0f;
224
return (type == SNDRV_SFNT_PAT_TYPE_GUS ||
225
type == SNDRV_SFNT_PAT_TYPE_MAP);
226
}
227
228
229
/* open patch; create sf list */
230
static int
231
open_patch(struct snd_sf_list *sflist, const char __user *data,
232
int count, int client)
233
{
234
struct soundfont_open_parm parm;
235
struct snd_soundfont *sf;
236
unsigned long flags;
237
238
spin_lock_irqsave(&sflist->lock, flags);
239
if (sflist->open_client >= 0 || sflist->currsf) {
240
spin_unlock_irqrestore(&sflist->lock, flags);
241
return -EBUSY;
242
}
243
spin_unlock_irqrestore(&sflist->lock, flags);
244
245
if (copy_from_user(&parm, data, sizeof(parm)))
246
return -EFAULT;
247
248
if (is_special_type(parm.type)) {
249
parm.type |= SNDRV_SFNT_PAT_SHARED;
250
sf = newsf(sflist, parm.type, NULL);
251
} else
252
sf = newsf(sflist, parm.type, parm.name);
253
if (sf == NULL) {
254
return -ENOMEM;
255
}
256
257
spin_lock_irqsave(&sflist->lock, flags);
258
sflist->open_client = client;
259
sflist->currsf = sf;
260
spin_unlock_irqrestore(&sflist->lock, flags);
261
262
return 0;
263
}
264
265
/*
266
* Allocate a new soundfont structure.
267
*/
268
static struct snd_soundfont *
269
newsf(struct snd_sf_list *sflist, int type, char *name)
270
{
271
struct snd_soundfont *sf;
272
273
/* check the shared fonts */
274
if (type & SNDRV_SFNT_PAT_SHARED) {
275
for (sf = sflist->fonts; sf; sf = sf->next) {
276
if (is_identical_font(sf, type, name)) {
277
return sf;
278
}
279
}
280
}
281
282
/* not found -- create a new one */
283
sf = kzalloc(sizeof(*sf), GFP_KERNEL);
284
if (sf == NULL)
285
return NULL;
286
sf->id = sflist->fonts_size;
287
sflist->fonts_size++;
288
289
/* prepend this record */
290
sf->next = sflist->fonts;
291
sflist->fonts = sf;
292
293
sf->type = type;
294
sf->zones = NULL;
295
sf->samples = NULL;
296
if (name)
297
memcpy(sf->name, name, SNDRV_SFNT_PATCH_NAME_LEN);
298
299
return sf;
300
}
301
302
/* check if the given name matches to the existing list */
303
static int
304
is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name)
305
{
306
return ((sf->type & SNDRV_SFNT_PAT_SHARED) &&
307
(sf->type & 0x0f) == (type & 0x0f) &&
308
(name == NULL ||
309
memcmp(sf->name, name, SNDRV_SFNT_PATCH_NAME_LEN) == 0));
310
}
311
312
/*
313
* Close the current patch.
314
*/
315
static int
316
close_patch(struct snd_sf_list *sflist)
317
{
318
unsigned long flags;
319
320
spin_lock_irqsave(&sflist->lock, flags);
321
sflist->currsf = NULL;
322
sflist->open_client = -1;
323
spin_unlock_irqrestore(&sflist->lock, flags);
324
325
rebuild_presets(sflist);
326
327
return 0;
328
329
}
330
331
/* probe sample in the current list -- nothing to be loaded */
332
static int
333
probe_data(struct snd_sf_list *sflist, int sample_id)
334
{
335
/* patch must be opened */
336
if (sflist->currsf) {
337
/* search the specified sample by optarg */
338
if (find_sample(sflist->currsf, sample_id))
339
return 0;
340
}
341
return -EINVAL;
342
}
343
344
/*
345
* increment zone counter
346
*/
347
static void
348
set_zone_counter(struct snd_sf_list *sflist, struct snd_soundfont *sf,
349
struct snd_sf_zone *zp)
350
{
351
zp->counter = sflist->zone_counter++;
352
if (sf->type & SNDRV_SFNT_PAT_LOCKED)
353
sflist->zone_locked = sflist->zone_counter;
354
}
355
356
/*
357
* allocate a new zone record
358
*/
359
static struct snd_sf_zone *
360
sf_zone_new(struct snd_sf_list *sflist, struct snd_soundfont *sf)
361
{
362
struct snd_sf_zone *zp;
363
364
if ((zp = kzalloc(sizeof(*zp), GFP_KERNEL)) == NULL)
365
return NULL;
366
zp->next = sf->zones;
367
sf->zones = zp;
368
369
init_voice_info(&zp->v);
370
371
set_zone_counter(sflist, sf, zp);
372
return zp;
373
}
374
375
376
/*
377
* increment sample counter
378
*/
379
static void
380
set_sample_counter(struct snd_sf_list *sflist, struct snd_soundfont *sf,
381
struct snd_sf_sample *sp)
382
{
383
sp->counter = sflist->sample_counter++;
384
if (sf->type & SNDRV_SFNT_PAT_LOCKED)
385
sflist->sample_locked = sflist->sample_counter;
386
}
387
388
/*
389
* allocate a new sample list record
390
*/
391
static struct snd_sf_sample *
392
sf_sample_new(struct snd_sf_list *sflist, struct snd_soundfont *sf)
393
{
394
struct snd_sf_sample *sp;
395
396
if ((sp = kzalloc(sizeof(*sp), GFP_KERNEL)) == NULL)
397
return NULL;
398
399
sp->next = sf->samples;
400
sf->samples = sp;
401
402
set_sample_counter(sflist, sf, sp);
403
return sp;
404
}
405
406
/*
407
* delete sample list -- this is an exceptional job.
408
* only the last allocated sample can be deleted.
409
*/
410
static void
411
sf_sample_delete(struct snd_sf_list *sflist, struct snd_soundfont *sf,
412
struct snd_sf_sample *sp)
413
{
414
/* only last sample is accepted */
415
if (sp == sf->samples) {
416
sf->samples = sp->next;
417
kfree(sp);
418
}
419
}
420
421
422
/* load voice map */
423
static int
424
load_map(struct snd_sf_list *sflist, const void __user *data, int count)
425
{
426
struct snd_sf_zone *zp, *prevp;
427
struct snd_soundfont *sf;
428
struct soundfont_voice_map map;
429
430
/* get the link info */
431
if (count < (int)sizeof(map))
432
return -EINVAL;
433
if (copy_from_user(&map, data, sizeof(map)))
434
return -EFAULT;
435
436
if (map.map_instr < 0 || map.map_instr >= SF_MAX_INSTRUMENTS)
437
return -EINVAL;
438
439
sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_MAP|SNDRV_SFNT_PAT_SHARED, NULL);
440
if (sf == NULL)
441
return -ENOMEM;
442
443
prevp = NULL;
444
for (zp = sf->zones; zp; prevp = zp, zp = zp->next) {
445
if (zp->mapped &&
446
zp->instr == map.map_instr &&
447
zp->bank == map.map_bank &&
448
zp->v.low == map.map_key &&
449
zp->v.start == map.src_instr &&
450
zp->v.end == map.src_bank &&
451
zp->v.fixkey == map.src_key) {
452
/* the same mapping is already present */
453
/* relink this record to the link head */
454
if (prevp) {
455
prevp->next = zp->next;
456
zp->next = sf->zones;
457
sf->zones = zp;
458
}
459
/* update the counter */
460
set_zone_counter(sflist, sf, zp);
461
return 0;
462
}
463
}
464
465
/* create a new zone */
466
if ((zp = sf_zone_new(sflist, sf)) == NULL)
467
return -ENOMEM;
468
469
zp->bank = map.map_bank;
470
zp->instr = map.map_instr;
471
zp->mapped = 1;
472
if (map.map_key >= 0) {
473
zp->v.low = map.map_key;
474
zp->v.high = map.map_key;
475
}
476
zp->v.start = map.src_instr;
477
zp->v.end = map.src_bank;
478
zp->v.fixkey = map.src_key;
479
zp->v.sf_id = sf->id;
480
481
add_preset(sflist, zp);
482
483
return 0;
484
}
485
486
487
/* remove the present instrument layers */
488
static int
489
remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf,
490
int bank, int instr)
491
{
492
struct snd_sf_zone *prev, *next, *p;
493
int removed = 0;
494
495
prev = NULL;
496
for (p = sf->zones; p; p = next) {
497
next = p->next;
498
if (! p->mapped &&
499
p->bank == bank && p->instr == instr) {
500
/* remove this layer */
501
if (prev)
502
prev->next = next;
503
else
504
sf->zones = next;
505
removed++;
506
kfree(p);
507
} else
508
prev = p;
509
}
510
if (removed)
511
rebuild_presets(sflist);
512
return removed;
513
}
514
515
516
/*
517
* Read an info record from the user buffer and save it on the current
518
* open soundfont.
519
*/
520
static int
521
load_info(struct snd_sf_list *sflist, const void __user *data, long count)
522
{
523
struct snd_soundfont *sf;
524
struct snd_sf_zone *zone;
525
struct soundfont_voice_rec_hdr hdr;
526
int i;
527
528
/* patch must be opened */
529
if ((sf = sflist->currsf) == NULL)
530
return -EINVAL;
531
532
if (is_special_type(sf->type))
533
return -EINVAL;
534
535
if (count < (long)sizeof(hdr)) {
536
printk(KERN_ERR "Soundfont error: invalid patch zone length\n");
537
return -EINVAL;
538
}
539
if (copy_from_user((char*)&hdr, data, sizeof(hdr)))
540
return -EFAULT;
541
542
data += sizeof(hdr);
543
count -= sizeof(hdr);
544
545
if (hdr.nvoices <= 0 || hdr.nvoices >= 100) {
546
printk(KERN_ERR "Soundfont error: Illegal voice number %d\n",
547
hdr.nvoices);
548
return -EINVAL;
549
}
550
551
if (count < (long)sizeof(struct soundfont_voice_info) * hdr.nvoices) {
552
printk(KERN_ERR "Soundfont Error: "
553
"patch length(%ld) is smaller than nvoices(%d)\n",
554
count, hdr.nvoices);
555
return -EINVAL;
556
}
557
558
switch (hdr.write_mode) {
559
case SNDRV_SFNT_WR_EXCLUSIVE:
560
/* exclusive mode - if the instrument already exists,
561
return error */
562
for (zone = sf->zones; zone; zone = zone->next) {
563
if (!zone->mapped &&
564
zone->bank == hdr.bank &&
565
zone->instr == hdr.instr)
566
return -EINVAL;
567
}
568
break;
569
case SNDRV_SFNT_WR_REPLACE:
570
/* replace mode - remove the instrument if it already exists */
571
remove_info(sflist, sf, hdr.bank, hdr.instr);
572
break;
573
}
574
575
for (i = 0; i < hdr.nvoices; i++) {
576
struct snd_sf_zone tmpzone;
577
578
/* copy awe_voice_info parameters */
579
if (copy_from_user(&tmpzone.v, data, sizeof(tmpzone.v))) {
580
return -EFAULT;
581
}
582
583
data += sizeof(tmpzone.v);
584
count -= sizeof(tmpzone.v);
585
586
tmpzone.bank = hdr.bank;
587
tmpzone.instr = hdr.instr;
588
tmpzone.mapped = 0;
589
tmpzone.v.sf_id = sf->id;
590
if (tmpzone.v.mode & SNDRV_SFNT_MODE_INIT_PARM)
591
init_voice_parm(&tmpzone.v.parm);
592
593
/* create a new zone */
594
if ((zone = sf_zone_new(sflist, sf)) == NULL) {
595
return -ENOMEM;
596
}
597
598
/* copy the temporary data */
599
zone->bank = tmpzone.bank;
600
zone->instr = tmpzone.instr;
601
zone->v = tmpzone.v;
602
603
/* look up the sample */
604
zone->sample = set_sample(sf, &zone->v);
605
}
606
607
return 0;
608
}
609
610
611
/* initialize voice_info record */
612
static void
613
init_voice_info(struct soundfont_voice_info *avp)
614
{
615
memset(avp, 0, sizeof(*avp));
616
617
avp->root = 60;
618
avp->high = 127;
619
avp->velhigh = 127;
620
avp->fixkey = -1;
621
avp->fixvel = -1;
622
avp->fixpan = -1;
623
avp->pan = -1;
624
avp->amplitude = 127;
625
avp->scaleTuning = 100;
626
627
init_voice_parm(&avp->parm);
628
}
629
630
/* initialize voice_parm record:
631
* Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0.
632
* Vibrato and Tremolo effects are zero.
633
* Cutoff is maximum.
634
* Chorus and Reverb effects are zero.
635
*/
636
static void
637
init_voice_parm(struct soundfont_voice_parm *pp)
638
{
639
memset(pp, 0, sizeof(*pp));
640
641
pp->moddelay = 0x8000;
642
pp->modatkhld = 0x7f7f;
643
pp->moddcysus = 0x7f7f;
644
pp->modrelease = 0x807f;
645
646
pp->voldelay = 0x8000;
647
pp->volatkhld = 0x7f7f;
648
pp->voldcysus = 0x7f7f;
649
pp->volrelease = 0x807f;
650
651
pp->lfo1delay = 0x8000;
652
pp->lfo2delay = 0x8000;
653
654
pp->cutoff = 0xff;
655
}
656
657
/* search the specified sample */
658
static struct snd_sf_sample *
659
set_sample(struct snd_soundfont *sf, struct soundfont_voice_info *avp)
660
{
661
struct snd_sf_sample *sample;
662
663
sample = find_sample(sf, avp->sample);
664
if (sample == NULL)
665
return NULL;
666
667
/* add in the actual sample offsets:
668
* The voice_info addresses define only the relative offset
669
* from sample pointers. Here we calculate the actual DRAM
670
* offset from sample pointers.
671
*/
672
avp->start += sample->v.start;
673
avp->end += sample->v.end;
674
avp->loopstart += sample->v.loopstart;
675
avp->loopend += sample->v.loopend;
676
677
/* copy mode flags */
678
avp->sample_mode = sample->v.mode_flags;
679
680
return sample;
681
}
682
683
/* find the sample pointer with the given id in the soundfont */
684
static struct snd_sf_sample *
685
find_sample(struct snd_soundfont *sf, int sample_id)
686
{
687
struct snd_sf_sample *p;
688
689
if (sf == NULL)
690
return NULL;
691
692
for (p = sf->samples; p; p = p->next) {
693
if (p->v.sample == sample_id)
694
return p;
695
}
696
return NULL;
697
}
698
699
700
/*
701
* Load sample information, this can include data to be loaded onto
702
* the soundcard. It can also just be a pointer into soundcard ROM.
703
* If there is data it will be written to the soundcard via the callback
704
* routine.
705
*/
706
static int
707
load_data(struct snd_sf_list *sflist, const void __user *data, long count)
708
{
709
struct snd_soundfont *sf;
710
struct soundfont_sample_info sample_info;
711
struct snd_sf_sample *sp;
712
long off;
713
714
/* patch must be opened */
715
if ((sf = sflist->currsf) == NULL)
716
return -EINVAL;
717
718
if (is_special_type(sf->type))
719
return -EINVAL;
720
721
if (copy_from_user(&sample_info, data, sizeof(sample_info)))
722
return -EFAULT;
723
724
off = sizeof(sample_info);
725
726
if (sample_info.size != (count-off)/2)
727
return -EINVAL;
728
729
/* Check for dup */
730
if (find_sample(sf, sample_info.sample)) {
731
/* if shared sample, skip this data */
732
if (sf->type & SNDRV_SFNT_PAT_SHARED)
733
return 0;
734
return -EINVAL;
735
}
736
737
/* Allocate a new sample structure */
738
if ((sp = sf_sample_new(sflist, sf)) == NULL)
739
return -ENOMEM;
740
741
sp->v = sample_info;
742
sp->v.sf_id = sf->id;
743
sp->v.dummy = 0;
744
sp->v.truesize = sp->v.size;
745
746
/*
747
* If there is wave data then load it.
748
*/
749
if (sp->v.size > 0) {
750
int rc;
751
rc = sflist->callback.sample_new
752
(sflist->callback.private_data, sp, sflist->memhdr,
753
data + off, count - off);
754
if (rc < 0) {
755
sf_sample_delete(sflist, sf, sp);
756
return rc;
757
}
758
sflist->mem_used += sp->v.truesize;
759
}
760
761
return count;
762
}
763
764
765
/* log2_tbl[i] = log2(i+128) * 0x10000 */
766
static int log_tbl[129] = {
767
0x70000, 0x702df, 0x705b9, 0x7088e, 0x70b5d, 0x70e26, 0x710eb, 0x713aa,
768
0x71663, 0x71918, 0x71bc8, 0x71e72, 0x72118, 0x723b9, 0x72655, 0x728ed,
769
0x72b80, 0x72e0e, 0x73098, 0x7331d, 0x7359e, 0x7381b, 0x73a93, 0x73d08,
770
0x73f78, 0x741e4, 0x7444c, 0x746b0, 0x74910, 0x74b6c, 0x74dc4, 0x75019,
771
0x75269, 0x754b6, 0x75700, 0x75946, 0x75b88, 0x75dc7, 0x76002, 0x7623a,
772
0x7646e, 0x766a0, 0x768cd, 0x76af8, 0x76d1f, 0x76f43, 0x77164, 0x77382,
773
0x7759d, 0x777b4, 0x779c9, 0x77bdb, 0x77dea, 0x77ff5, 0x781fe, 0x78404,
774
0x78608, 0x78808, 0x78a06, 0x78c01, 0x78df9, 0x78fef, 0x791e2, 0x793d2,
775
0x795c0, 0x797ab, 0x79993, 0x79b79, 0x79d5d, 0x79f3e, 0x7a11d, 0x7a2f9,
776
0x7a4d3, 0x7a6ab, 0x7a880, 0x7aa53, 0x7ac24, 0x7adf2, 0x7afbe, 0x7b188,
777
0x7b350, 0x7b515, 0x7b6d8, 0x7b899, 0x7ba58, 0x7bc15, 0x7bdd0, 0x7bf89,
778
0x7c140, 0x7c2f5, 0x7c4a7, 0x7c658, 0x7c807, 0x7c9b3, 0x7cb5e, 0x7cd07,
779
0x7ceae, 0x7d053, 0x7d1f7, 0x7d398, 0x7d538, 0x7d6d6, 0x7d872, 0x7da0c,
780
0x7dba4, 0x7dd3b, 0x7ded0, 0x7e063, 0x7e1f4, 0x7e384, 0x7e512, 0x7e69f,
781
0x7e829, 0x7e9b3, 0x7eb3a, 0x7ecc0, 0x7ee44, 0x7efc7, 0x7f148, 0x7f2c8,
782
0x7f446, 0x7f5c2, 0x7f73d, 0x7f8b7, 0x7fa2f, 0x7fba5, 0x7fd1a, 0x7fe8d,
783
0x80000,
784
};
785
786
/* convert from linear to log value
787
*
788
* conversion: value = log2(amount / base) * ratio
789
*
790
* argument:
791
* amount = linear value (unsigned, 32bit max)
792
* offset = base offset (:= log2(base) * 0x10000)
793
* ratio = division ratio
794
*
795
*/
796
int
797
snd_sf_linear_to_log(unsigned int amount, int offset, int ratio)
798
{
799
int v;
800
int s, low, bit;
801
802
if (amount < 2)
803
return 0;
804
for (bit = 0; ! (amount & 0x80000000L); bit++)
805
amount <<= 1;
806
s = (amount >> 24) & 0x7f;
807
low = (amount >> 16) & 0xff;
808
/* linear approxmimation by lower 8 bit */
809
v = (log_tbl[s + 1] * low + log_tbl[s] * (0x100 - low)) >> 8;
810
v -= offset;
811
v = (v * ratio) >> 16;
812
v += (24 - bit) * ratio;
813
return v;
814
}
815
816
EXPORT_SYMBOL(snd_sf_linear_to_log);
817
818
819
#define OFFSET_MSEC 653117 /* base = 1000 */
820
#define OFFSET_ABSCENT 851781 /* base = 8176 */
821
#define OFFSET_SAMPLERATE 1011119 /* base = 44100 */
822
823
#define ABSCENT_RATIO 1200
824
#define TIMECENT_RATIO 1200
825
#define SAMPLERATE_RATIO 4096
826
827
/*
828
* mHz to abscent
829
* conversion: abscent = log2(MHz / 8176) * 1200
830
*/
831
static int
832
freq_to_note(int mhz)
833
{
834
return snd_sf_linear_to_log(mhz, OFFSET_ABSCENT, ABSCENT_RATIO);
835
}
836
837
/* convert Hz to AWE32 rate offset:
838
* sample pitch offset for the specified sample rate
839
* rate=44100 is no offset, each 4096 is 1 octave (twice).
840
* eg, when rate is 22050, this offset becomes -4096.
841
*
842
* conversion: offset = log2(Hz / 44100) * 4096
843
*/
844
static int
845
calc_rate_offset(int hz)
846
{
847
return snd_sf_linear_to_log(hz, OFFSET_SAMPLERATE, SAMPLERATE_RATIO);
848
}
849
850
851
/* calculate GUS envelope time */
852
static int
853
calc_gus_envelope_time(int rate, int start, int end)
854
{
855
int r, p, t;
856
r = (3 - ((rate >> 6) & 3)) * 3;
857
p = rate & 0x3f;
858
t = end - start;
859
if (t < 0) t = -t;
860
if (13 > r)
861
t = t << (13 - r);
862
else
863
t = t >> (r - 13);
864
return (t * 10) / (p * 441);
865
}
866
867
/* convert envelope time parameter to soundfont parameters */
868
869
/* attack & decay/release time table (msec) */
870
static short attack_time_tbl[128] = {
871
32767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816,
872
707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377,
873
361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188,
874
180, 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94,
875
90, 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47,
876
45, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23,
877
22, 21, 20, 19, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12,
878
11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0,
879
};
880
881
static short decay_time_tbl[128] = {
882
32767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082,
883
2828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507,
884
1443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722,
885
691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361,
886
345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, 180,
887
172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, 90,
888
86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45,
889
43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 22,
890
};
891
892
/* delay time = 0x8000 - msec/92 */
893
int
894
snd_sf_calc_parm_hold(int msec)
895
{
896
int val = (0x7f * 92 - msec) / 92;
897
if (val < 1) val = 1;
898
if (val >= 126) val = 126;
899
return val;
900
}
901
902
/* search an index for specified time from given time table */
903
static int
904
calc_parm_search(int msec, short *table)
905
{
906
int left = 1, right = 127, mid;
907
while (left < right) {
908
mid = (left + right) / 2;
909
if (msec < (int)table[mid])
910
left = mid + 1;
911
else
912
right = mid;
913
}
914
return left;
915
}
916
917
/* attack time: search from time table */
918
int
919
snd_sf_calc_parm_attack(int msec)
920
{
921
return calc_parm_search(msec, attack_time_tbl);
922
}
923
924
/* decay/release time: search from time table */
925
int
926
snd_sf_calc_parm_decay(int msec)
927
{
928
return calc_parm_search(msec, decay_time_tbl);
929
}
930
931
int snd_sf_vol_table[128] = {
932
255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49,
933
47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32,
934
31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22,
935
22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16,
936
15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10,
937
10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6,
938
6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3,
939
2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,
940
};
941
942
943
#define calc_gus_sustain(val) (0x7f - snd_sf_vol_table[(val)/2])
944
#define calc_gus_attenuation(val) snd_sf_vol_table[(val)/2]
945
946
/* load GUS patch */
947
static int
948
load_guspatch(struct snd_sf_list *sflist, const char __user *data,
949
long count, int client)
950
{
951
struct patch_info patch;
952
struct snd_soundfont *sf;
953
struct snd_sf_zone *zone;
954
struct snd_sf_sample *smp;
955
int note, sample_id;
956
int rc;
957
958
if (count < (long)sizeof(patch)) {
959
snd_printk(KERN_ERR "patch record too small %ld\n", count);
960
return -EINVAL;
961
}
962
if (copy_from_user(&patch, data, sizeof(patch)))
963
return -EFAULT;
964
965
count -= sizeof(patch);
966
data += sizeof(patch);
967
968
sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_GUS|SNDRV_SFNT_PAT_SHARED, NULL);
969
if (sf == NULL)
970
return -ENOMEM;
971
if ((smp = sf_sample_new(sflist, sf)) == NULL)
972
return -ENOMEM;
973
sample_id = sflist->sample_counter;
974
smp->v.sample = sample_id;
975
smp->v.start = 0;
976
smp->v.end = patch.len;
977
smp->v.loopstart = patch.loop_start;
978
smp->v.loopend = patch.loop_end;
979
smp->v.size = patch.len;
980
981
/* set up mode flags */
982
smp->v.mode_flags = 0;
983
if (!(patch.mode & WAVE_16_BITS))
984
smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_8BITS;
985
if (patch.mode & WAVE_UNSIGNED)
986
smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_UNSIGNED;
987
smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_NO_BLANK;
988
if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP|WAVE_LOOP_BACK)))
989
smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_SINGLESHOT;
990
if (patch.mode & WAVE_BIDIR_LOOP)
991
smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_BIDIR_LOOP;
992
if (patch.mode & WAVE_LOOP_BACK)
993
smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_REVERSE_LOOP;
994
995
if (patch.mode & WAVE_16_BITS) {
996
/* convert to word offsets */
997
smp->v.size /= 2;
998
smp->v.end /= 2;
999
smp->v.loopstart /= 2;
1000
smp->v.loopend /= 2;
1001
}
1002
/*smp->v.loopend++;*/
1003
1004
smp->v.dummy = 0;
1005
smp->v.truesize = 0;
1006
smp->v.sf_id = sf->id;
1007
1008
/* set up voice info */
1009
if ((zone = sf_zone_new(sflist, sf)) == NULL) {
1010
sf_sample_delete(sflist, sf, smp);
1011
return -ENOMEM;
1012
}
1013
1014
/*
1015
* load wave data
1016
*/
1017
if (sflist->callback.sample_new) {
1018
rc = sflist->callback.sample_new
1019
(sflist->callback.private_data, smp, sflist->memhdr,
1020
data, count);
1021
if (rc < 0) {
1022
sf_sample_delete(sflist, sf, smp);
1023
return rc;
1024
}
1025
/* memory offset is updated after */
1026
}
1027
1028
/* update the memory offset here */
1029
sflist->mem_used += smp->v.truesize;
1030
1031
zone->v.sample = sample_id; /* the last sample */
1032
zone->v.rate_offset = calc_rate_offset(patch.base_freq);
1033
note = freq_to_note(patch.base_note);
1034
zone->v.root = note / 100;
1035
zone->v.tune = -(note % 100);
1036
zone->v.low = (freq_to_note(patch.low_note) + 99) / 100;
1037
zone->v.high = freq_to_note(patch.high_note) / 100;
1038
/* panning position; -128 - 127 => 0-127 */
1039
zone->v.pan = (patch.panning + 128) / 2;
1040
#if 0
1041
snd_printk(KERN_DEBUG
1042
"gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n",
1043
(int)patch.base_freq, zone->v.rate_offset,
1044
zone->v.root, zone->v.tune, zone->v.low, zone->v.high);
1045
#endif
1046
1047
/* detuning is ignored */
1048
/* 6points volume envelope */
1049
if (patch.mode & WAVE_ENVELOPES) {
1050
int attack, hold, decay, release;
1051
attack = calc_gus_envelope_time
1052
(patch.env_rate[0], 0, patch.env_offset[0]);
1053
hold = calc_gus_envelope_time
1054
(patch.env_rate[1], patch.env_offset[0],
1055
patch.env_offset[1]);
1056
decay = calc_gus_envelope_time
1057
(patch.env_rate[2], patch.env_offset[1],
1058
patch.env_offset[2]);
1059
release = calc_gus_envelope_time
1060
(patch.env_rate[3], patch.env_offset[1],
1061
patch.env_offset[4]);
1062
release += calc_gus_envelope_time
1063
(patch.env_rate[4], patch.env_offset[3],
1064
patch.env_offset[4]);
1065
release += calc_gus_envelope_time
1066
(patch.env_rate[5], patch.env_offset[4],
1067
patch.env_offset[5]);
1068
zone->v.parm.volatkhld =
1069
(snd_sf_calc_parm_hold(hold) << 8) |
1070
snd_sf_calc_parm_attack(attack);
1071
zone->v.parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) |
1072
snd_sf_calc_parm_decay(decay);
1073
zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release);
1074
zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]);
1075
#if 0
1076
snd_printk(KERN_DEBUG
1077
"gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n",
1078
zone->v.parm.volatkhld,
1079
zone->v.parm.voldcysus,
1080
zone->v.parm.volrelease,
1081
zone->v.attenuation);
1082
#endif
1083
}
1084
1085
/* fast release */
1086
if (patch.mode & WAVE_FAST_RELEASE) {
1087
zone->v.parm.volrelease = 0x807f;
1088
}
1089
1090
/* tremolo effect */
1091
if (patch.mode & WAVE_TREMOLO) {
1092
int rate = (patch.tremolo_rate * 1000 / 38) / 42;
1093
zone->v.parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate;
1094
}
1095
/* vibrato effect */
1096
if (patch.mode & WAVE_VIBRATO) {
1097
int rate = (patch.vibrato_rate * 1000 / 38) / 42;
1098
zone->v.parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate;
1099
}
1100
1101
/* scale_freq, scale_factor, volume, and fractions not implemented */
1102
1103
if (!(smp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT))
1104
zone->v.mode = SNDRV_SFNT_MODE_LOOPING;
1105
else
1106
zone->v.mode = 0;
1107
1108
/* append to the tail of the list */
1109
/*zone->bank = ctrls[AWE_MD_GUS_BANK];*/
1110
zone->bank = 0;
1111
zone->instr = patch.instr_no;
1112
zone->mapped = 0;
1113
zone->v.sf_id = sf->id;
1114
1115
zone->sample = set_sample(sf, &zone->v);
1116
1117
/* rebuild preset now */
1118
add_preset(sflist, zone);
1119
1120
return 0;
1121
}
1122
1123
/* load GUS patch */
1124
int
1125
snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data,
1126
long count, int client)
1127
{
1128
int rc;
1129
lock_preset(sflist);
1130
rc = load_guspatch(sflist, data, count, client);
1131
unlock_preset(sflist);
1132
return rc;
1133
}
1134
1135
1136
/*
1137
* Rebuild the preset table. This is like a hash table in that it allows
1138
* quick access to the zone information. For each preset there are zone
1139
* structures linked by next_instr and by next_zone. Former is the whole
1140
* link for this preset, and latter is the link for zone (i.e. instrument/
1141
* bank/key combination).
1142
*/
1143
static void
1144
rebuild_presets(struct snd_sf_list *sflist)
1145
{
1146
struct snd_soundfont *sf;
1147
struct snd_sf_zone *cur;
1148
1149
/* clear preset table */
1150
memset(sflist->presets, 0, sizeof(sflist->presets));
1151
1152
/* search all fonts and insert each font */
1153
for (sf = sflist->fonts; sf; sf = sf->next) {
1154
for (cur = sf->zones; cur; cur = cur->next) {
1155
if (! cur->mapped && cur->sample == NULL) {
1156
/* try again to search the corresponding sample */
1157
cur->sample = set_sample(sf, &cur->v);
1158
if (cur->sample == NULL)
1159
continue;
1160
}
1161
1162
add_preset(sflist, cur);
1163
}
1164
}
1165
}
1166
1167
1168
/*
1169
* add the given zone to preset table
1170
*/
1171
static void
1172
add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur)
1173
{
1174
struct snd_sf_zone *zone;
1175
int index;
1176
1177
zone = search_first_zone(sflist, cur->bank, cur->instr, cur->v.low);
1178
if (zone && zone->v.sf_id != cur->v.sf_id) {
1179
/* different instrument was already defined */
1180
struct snd_sf_zone *p;
1181
/* compare the allocated time */
1182
for (p = zone; p; p = p->next_zone) {
1183
if (p->counter > cur->counter)
1184
/* the current is older.. skipped */
1185
return;
1186
}
1187
/* remove old zones */
1188
delete_preset(sflist, zone);
1189
zone = NULL; /* do not forget to clear this! */
1190
}
1191
1192
/* prepend this zone */
1193
if ((index = get_index(cur->bank, cur->instr, cur->v.low)) < 0)
1194
return;
1195
cur->next_zone = zone; /* zone link */
1196
cur->next_instr = sflist->presets[index]; /* preset table link */
1197
sflist->presets[index] = cur;
1198
}
1199
1200
/*
1201
* delete the given zones from preset_table
1202
*/
1203
static void
1204
delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp)
1205
{
1206
int index;
1207
struct snd_sf_zone *p;
1208
1209
if ((index = get_index(zp->bank, zp->instr, zp->v.low)) < 0)
1210
return;
1211
for (p = sflist->presets[index]; p; p = p->next_instr) {
1212
while (p->next_instr == zp) {
1213
p->next_instr = zp->next_instr;
1214
zp = zp->next_zone;
1215
if (zp == NULL)
1216
return;
1217
}
1218
}
1219
}
1220
1221
1222
/*
1223
* Search matching zones from preset table.
1224
* The note can be rewritten by preset mapping (alias).
1225
* The found zones are stored on 'table' array. max_layers defines
1226
* the maximum number of elements in this array.
1227
* This function returns the number of found zones. 0 if not found.
1228
*/
1229
int
1230
snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel,
1231
int preset, int bank,
1232
int def_preset, int def_bank,
1233
struct snd_sf_zone **table, int max_layers)
1234
{
1235
int nvoices;
1236
unsigned long flags;
1237
1238
/* this function is supposed to be called atomically,
1239
* so we check the lock. if it's busy, just returns 0 to
1240
* tell the caller the busy state
1241
*/
1242
spin_lock_irqsave(&sflist->lock, flags);
1243
if (sflist->presets_locked) {
1244
spin_unlock_irqrestore(&sflist->lock, flags);
1245
return 0;
1246
}
1247
nvoices = search_zones(sflist, notep, vel, preset, bank,
1248
table, max_layers, 0);
1249
if (! nvoices) {
1250
if (preset != def_preset || bank != def_bank)
1251
nvoices = search_zones(sflist, notep, vel,
1252
def_preset, def_bank,
1253
table, max_layers, 0);
1254
}
1255
spin_unlock_irqrestore(&sflist->lock, flags);
1256
return nvoices;
1257
}
1258
1259
1260
/*
1261
* search the first matching zone
1262
*/
1263
static struct snd_sf_zone *
1264
search_first_zone(struct snd_sf_list *sflist, int bank, int preset, int key)
1265
{
1266
int index;
1267
struct snd_sf_zone *zp;
1268
1269
if ((index = get_index(bank, preset, key)) < 0)
1270
return NULL;
1271
for (zp = sflist->presets[index]; zp; zp = zp->next_instr) {
1272
if (zp->instr == preset && zp->bank == bank)
1273
return zp;
1274
}
1275
return NULL;
1276
}
1277
1278
1279
/*
1280
* search matching zones from sflist. can be called recursively.
1281
*/
1282
static int
1283
search_zones(struct snd_sf_list *sflist, int *notep, int vel,
1284
int preset, int bank, struct snd_sf_zone **table,
1285
int max_layers, int level)
1286
{
1287
struct snd_sf_zone *zp;
1288
int nvoices;
1289
1290
zp = search_first_zone(sflist, bank, preset, *notep);
1291
nvoices = 0;
1292
for (; zp; zp = zp->next_zone) {
1293
if (*notep >= zp->v.low && *notep <= zp->v.high &&
1294
vel >= zp->v.vellow && vel <= zp->v.velhigh) {
1295
if (zp->mapped) {
1296
/* search preset mapping (aliasing) */
1297
int key = zp->v.fixkey;
1298
preset = zp->v.start;
1299
bank = zp->v.end;
1300
1301
if (level > 5) /* too deep alias level */
1302
return 0;
1303
if (key < 0)
1304
key = *notep;
1305
nvoices = search_zones(sflist, &key, vel,
1306
preset, bank, table,
1307
max_layers, level + 1);
1308
if (nvoices > 0)
1309
*notep = key;
1310
break;
1311
}
1312
table[nvoices++] = zp;
1313
if (nvoices >= max_layers)
1314
break;
1315
}
1316
}
1317
1318
return nvoices;
1319
}
1320
1321
1322
/* calculate the index of preset table:
1323
* drums are mapped from 128 to 255 according to its note key.
1324
* other instruments are mapped from 0 to 127.
1325
* if the index is out of range, return -1.
1326
*/
1327
static int
1328
get_index(int bank, int instr, int key)
1329
{
1330
int index;
1331
if (SF_IS_DRUM_BANK(bank))
1332
index = key + SF_MAX_INSTRUMENTS;
1333
else
1334
index = instr;
1335
index = index % SF_MAX_PRESETS;
1336
if (index < 0)
1337
return -1;
1338
return index;
1339
}
1340
1341
/*
1342
* Initialise the sflist structure.
1343
*/
1344
static void
1345
snd_sf_init(struct snd_sf_list *sflist)
1346
{
1347
memset(sflist->presets, 0, sizeof(sflist->presets));
1348
1349
sflist->mem_used = 0;
1350
sflist->currsf = NULL;
1351
sflist->open_client = -1;
1352
sflist->fonts = NULL;
1353
sflist->fonts_size = 0;
1354
sflist->zone_counter = 0;
1355
sflist->sample_counter = 0;
1356
sflist->zone_locked = 0;
1357
sflist->sample_locked = 0;
1358
}
1359
1360
/*
1361
* Release all list records
1362
*/
1363
static void
1364
snd_sf_clear(struct snd_sf_list *sflist)
1365
{
1366
struct snd_soundfont *sf, *nextsf;
1367
struct snd_sf_zone *zp, *nextzp;
1368
struct snd_sf_sample *sp, *nextsp;
1369
1370
for (sf = sflist->fonts; sf; sf = nextsf) {
1371
nextsf = sf->next;
1372
for (zp = sf->zones; zp; zp = nextzp) {
1373
nextzp = zp->next;
1374
kfree(zp);
1375
}
1376
for (sp = sf->samples; sp; sp = nextsp) {
1377
nextsp = sp->next;
1378
if (sflist->callback.sample_free)
1379
sflist->callback.sample_free(sflist->callback.private_data,
1380
sp, sflist->memhdr);
1381
kfree(sp);
1382
}
1383
kfree(sf);
1384
}
1385
1386
snd_sf_init(sflist);
1387
}
1388
1389
1390
/*
1391
* Create a new sflist structure
1392
*/
1393
struct snd_sf_list *
1394
snd_sf_new(struct snd_sf_callback *callback, struct snd_util_memhdr *hdr)
1395
{
1396
struct snd_sf_list *sflist;
1397
1398
if ((sflist = kzalloc(sizeof(*sflist), GFP_KERNEL)) == NULL)
1399
return NULL;
1400
1401
mutex_init(&sflist->presets_mutex);
1402
spin_lock_init(&sflist->lock);
1403
sflist->memhdr = hdr;
1404
1405
if (callback)
1406
sflist->callback = *callback;
1407
1408
snd_sf_init(sflist);
1409
return sflist;
1410
}
1411
1412
1413
/*
1414
* Free everything allocated off the sflist structure.
1415
*/
1416
void
1417
snd_sf_free(struct snd_sf_list *sflist)
1418
{
1419
if (sflist == NULL)
1420
return;
1421
1422
lock_preset(sflist);
1423
if (sflist->callback.sample_reset)
1424
sflist->callback.sample_reset(sflist->callback.private_data);
1425
snd_sf_clear(sflist);
1426
unlock_preset(sflist);
1427
1428
kfree(sflist);
1429
}
1430
1431
/*
1432
* Remove all samples
1433
* The soundcard should be silet before calling this function.
1434
*/
1435
int
1436
snd_soundfont_remove_samples(struct snd_sf_list *sflist)
1437
{
1438
lock_preset(sflist);
1439
if (sflist->callback.sample_reset)
1440
sflist->callback.sample_reset(sflist->callback.private_data);
1441
snd_sf_clear(sflist);
1442
unlock_preset(sflist);
1443
1444
return 0;
1445
}
1446
1447
/*
1448
* Remove unlocked samples.
1449
* The soundcard should be silent before calling this function.
1450
*/
1451
int
1452
snd_soundfont_remove_unlocked(struct snd_sf_list *sflist)
1453
{
1454
struct snd_soundfont *sf;
1455
struct snd_sf_zone *zp, *nextzp;
1456
struct snd_sf_sample *sp, *nextsp;
1457
1458
lock_preset(sflist);
1459
1460
if (sflist->callback.sample_reset)
1461
sflist->callback.sample_reset(sflist->callback.private_data);
1462
1463
/* to be sure */
1464
memset(sflist->presets, 0, sizeof(sflist->presets));
1465
1466
for (sf = sflist->fonts; sf; sf = sf->next) {
1467
for (zp = sf->zones; zp; zp = nextzp) {
1468
if (zp->counter < sflist->zone_locked)
1469
break;
1470
nextzp = zp->next;
1471
sf->zones = nextzp;
1472
kfree(zp);
1473
}
1474
1475
for (sp = sf->samples; sp; sp = nextsp) {
1476
if (sp->counter < sflist->sample_locked)
1477
break;
1478
nextsp = sp->next;
1479
sf->samples = nextsp;
1480
sflist->mem_used -= sp->v.truesize;
1481
if (sflist->callback.sample_free)
1482
sflist->callback.sample_free(sflist->callback.private_data,
1483
sp, sflist->memhdr);
1484
kfree(sp);
1485
}
1486
}
1487
1488
sflist->zone_counter = sflist->zone_locked;
1489
sflist->sample_counter = sflist->sample_locked;
1490
1491
rebuild_presets(sflist);
1492
1493
unlock_preset(sflist);
1494
return 0;
1495
}
1496
1497