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