]> bbs.cooldavid.org Git - net-next-2.6.git/blame - sound/synth/emux/soundfont.c
xps: Transmit Packet Steering
[net-next-2.6.git] / sound / synth / emux / soundfont.c
CommitLineData
1da177e4
LT
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 <tiwai@suse.de>
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 */
1da177e4
LT
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
03da312a
TI
36static int open_patch(struct snd_sf_list *sflist, const char __user *data,
37 int count, int client);
38static struct snd_soundfont *newsf(struct snd_sf_list *sflist, int type, char *name);
39static int is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name);
40static int close_patch(struct snd_sf_list *sflist);
41static int probe_data(struct snd_sf_list *sflist, int sample_id);
42static void set_zone_counter(struct snd_sf_list *sflist,
43 struct snd_soundfont *sf, struct snd_sf_zone *zp);
44static struct snd_sf_zone *sf_zone_new(struct snd_sf_list *sflist,
45 struct snd_soundfont *sf);
46static void set_sample_counter(struct snd_sf_list *sflist,
47 struct snd_soundfont *sf, struct snd_sf_sample *sp);
48static struct snd_sf_sample *sf_sample_new(struct snd_sf_list *sflist,
49 struct snd_soundfont *sf);
50static void sf_sample_delete(struct snd_sf_list *sflist,
51 struct snd_soundfont *sf, struct snd_sf_sample *sp);
52static int load_map(struct snd_sf_list *sflist, const void __user *data, int count);
53static int load_info(struct snd_sf_list *sflist, const void __user *data, long count);
54static int remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf,
55 int bank, int instr);
56static void init_voice_info(struct soundfont_voice_info *avp);
57static void init_voice_parm(struct soundfont_voice_parm *pp);
58static struct snd_sf_sample *set_sample(struct snd_soundfont *sf,
59 struct soundfont_voice_info *avp);
60static struct snd_sf_sample *find_sample(struct snd_soundfont *sf, int sample_id);
61static int load_data(struct snd_sf_list *sflist, const void __user *data, long count);
62static void rebuild_presets(struct snd_sf_list *sflist);
63static void add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur);
64static void delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp);
65static struct snd_sf_zone *search_first_zone(struct snd_sf_list *sflist,
66 int bank, int preset, int key);
67static 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);
1da177e4 70static int get_index(int bank, int instr, int key);
03da312a
TI
71static void snd_sf_init(struct snd_sf_list *sflist);
72static void snd_sf_clear(struct snd_sf_list *sflist);
1da177e4
LT
73
74/*
75 * lock access to sflist
76 */
77static void
03da312a 78lock_preset(struct snd_sf_list *sflist)
1da177e4
LT
79{
80 unsigned long flags;
ef9f0a42 81 mutex_lock(&sflist->presets_mutex);
1da177e4
LT
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 */
91static void
03da312a 92unlock_preset(struct snd_sf_list *sflist)
1da177e4
LT
93{
94 unsigned long flags;
95 spin_lock_irqsave(&sflist->lock, flags);
96 sflist->presets_locked = 0;
97 spin_unlock_irqrestore(&sflist->lock, flags);
ef9f0a42 98 mutex_unlock(&sflist->presets_mutex);
1da177e4
LT
99}
100
101
102/*
103 * close the patch if the patch was opened by this client.
104 */
105int
03da312a 106snd_soundfont_close_check(struct snd_sf_list *sflist, int client)
1da177e4
LT
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 */
127int
03da312a
TI
128snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data,
129 long count, int client)
1da177e4 130{
03da312a 131 struct soundfont_patch_info patch;
1da177e4
LT
132 unsigned long flags;
133 int rc;
134
135 if (count < (long)sizeof(patch)) {
42b0158b 136 snd_printk(KERN_ERR "patch record too small %ld\n", count);
1da177e4
LT
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) {
42b0158b 146 snd_printk(KERN_ERR "The wrong kind of patch %x\n", patch.key);
1da177e4
LT
147 return -EINVAL;
148 }
149 if (count < patch.len) {
42b0158b
TI
150 snd_printk(KERN_ERR "Patch too short %ld, need %d\n",
151 count, patch.len);
1da177e4
LT
152 return -EINVAL;
153 }
154 if (patch.len < 0) {
42b0158b 155 snd_printk(KERN_ERR "poor length %d\n", patch.len);
1da177e4
LT
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 */
d20cad60 198 if (!sflist->currsf) {
42b0158b
TI
199 snd_printk(KERN_ERR "soundfont: remove_info: "
200 "patch not opened\n");
1da177e4
LT
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) */
220static inline int
221is_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 */
230static int
03da312a
TI
231open_patch(struct snd_sf_list *sflist, const char __user *data,
232 int count, int client)
1da177e4 233{
03da312a
TI
234 struct soundfont_open_parm parm;
235 struct snd_soundfont *sf;
1da177e4
LT
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 */
03da312a
TI
268static struct snd_soundfont *
269newsf(struct snd_sf_list *sflist, int type, char *name)
1da177e4 270{
03da312a 271 struct snd_soundfont *sf;
1da177e4
LT
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 */
561b220a 283 sf = kzalloc(sizeof(*sf), GFP_KERNEL);
1da177e4
LT
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 */
303static int
03da312a 304is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name)
1da177e4
LT
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 */
315static int
03da312a 316close_patch(struct snd_sf_list *sflist)
1da177e4
LT
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 */
332static int
03da312a 333probe_data(struct snd_sf_list *sflist, int sample_id)
1da177e4
LT
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 */
347static void
03da312a
TI
348set_zone_counter(struct snd_sf_list *sflist, struct snd_soundfont *sf,
349 struct snd_sf_zone *zp)
1da177e4
LT
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 */
03da312a
TI
359static struct snd_sf_zone *
360sf_zone_new(struct snd_sf_list *sflist, struct snd_soundfont *sf)
1da177e4 361{
03da312a 362 struct snd_sf_zone *zp;
1da177e4 363
561b220a 364 if ((zp = kzalloc(sizeof(*zp), GFP_KERNEL)) == NULL)
1da177e4
LT
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/*
fbfecd37 377 * increment sample counter
1da177e4
LT
378 */
379static void
03da312a
TI
380set_sample_counter(struct snd_sf_list *sflist, struct snd_soundfont *sf,
381 struct snd_sf_sample *sp)
1da177e4
LT
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 */
03da312a
TI
391static struct snd_sf_sample *
392sf_sample_new(struct snd_sf_list *sflist, struct snd_soundfont *sf)
1da177e4 393{
03da312a 394 struct snd_sf_sample *sp;
1da177e4 395
561b220a 396 if ((sp = kzalloc(sizeof(*sp), GFP_KERNEL)) == NULL)
1da177e4
LT
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 */
410static void
03da312a
TI
411sf_sample_delete(struct snd_sf_list *sflist, struct snd_soundfont *sf,
412 struct snd_sf_sample *sp)
1da177e4
LT
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 */
423static int
03da312a 424load_map(struct snd_sf_list *sflist, const void __user *data, int count)
1da177e4 425{
03da312a
TI
426 struct snd_sf_zone *zp, *prevp;
427 struct snd_soundfont *sf;
428 struct soundfont_voice_map map;
1da177e4
LT
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 */
488static int
03da312a
TI
489remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf,
490 int bank, int instr)
1da177e4 491{
03da312a 492 struct snd_sf_zone *prev, *next, *p;
1da177e4
LT
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 */
520static int
03da312a 521load_info(struct snd_sf_list *sflist, const void __user *data, long count)
1da177e4 522{
03da312a
TI
523 struct snd_soundfont *sf;
524 struct snd_sf_zone *zone;
525 struct soundfont_voice_rec_hdr hdr;
1da177e4
LT
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)) {
42b0158b 536 printk(KERN_ERR "Soundfont error: invalid patch zone length\n");
1da177e4
LT
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) {
42b0158b
TI
546 printk(KERN_ERR "Soundfont error: Illegal voice number %d\n",
547 hdr.nvoices);
1da177e4
LT
548 return -EINVAL;
549 }
550
03da312a 551 if (count < (long)sizeof(struct soundfont_voice_info) * hdr.nvoices) {
42b0158b
TI
552 printk(KERN_ERR "Soundfont Error: "
553 "patch length(%ld) is smaller than nvoices(%d)\n",
1da177e4
LT
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++) {
03da312a 576 struct snd_sf_zone tmpzone;
1da177e4
LT
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 */
612static void
03da312a 613init_voice_info(struct soundfont_voice_info *avp)
1da177e4
LT
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 */
636static void
03da312a 637init_voice_parm(struct soundfont_voice_parm *pp)
1da177e4
LT
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 */
03da312a
TI
658static struct snd_sf_sample *
659set_sample(struct snd_soundfont *sf, struct soundfont_voice_info *avp)
1da177e4 660{
03da312a 661 struct snd_sf_sample *sample;
1da177e4
LT
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 */
03da312a
TI
684static struct snd_sf_sample *
685find_sample(struct snd_soundfont *sf, int sample_id)
1da177e4 686{
03da312a 687 struct snd_sf_sample *p;
1da177e4
LT
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 */
706static int
03da312a 707load_data(struct snd_sf_list *sflist, const void __user *data, long count)
1da177e4 708{
03da312a
TI
709 struct snd_soundfont *sf;
710 struct soundfont_sample_info sample_info;
711 struct snd_sf_sample *sp;
1da177e4
LT
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 */
766static 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 */
796int
797snd_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
95ff1756
TI
816EXPORT_SYMBOL(snd_sf_linear_to_log);
817
818
1da177e4
LT
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 */
831static int
832freq_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 */
844static int
845calc_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 */
852static int
853calc_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) */
870static short attack_time_tbl[128] = {
87132767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816,
872707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377,
873361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188,
874180, 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94,
87590, 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47,
87645, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23,
87722, 21, 20, 19, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12,
87811, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0,
879};
880
881static short decay_time_tbl[128] = {
88232767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082,
8832828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507,
8841443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722,
885691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361,
886345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, 180,
887172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, 90,
88886, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45,
88943, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 22,
890};
891
892/* delay time = 0x8000 - msec/92 */
893int
894snd_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 */
903static int
904calc_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 */
918int
919snd_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 */
925int
926snd_sf_calc_parm_decay(int msec)
927{
928 return calc_parm_search(msec, decay_time_tbl);
929}
930
931int 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 */
947static int
03da312a
TI
948load_guspatch(struct snd_sf_list *sflist, const char __user *data,
949 long count, int client)
1da177e4
LT
950{
951 struct patch_info patch;
03da312a
TI
952 struct snd_soundfont *sf;
953 struct snd_sf_zone *zone;
954 struct snd_sf_sample *smp;
1da177e4
LT
955 int note, sample_id;
956 int rc;
957
958 if (count < (long)sizeof(patch)) {
42b0158b 959 snd_printk(KERN_ERR "patch record too small %ld\n", count);
1da177e4
LT
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
03da312a
TI
1019 (sflist->callback.private_data, smp, sflist->memhdr,
1020 data, count);
1da177e4
LT
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
42b0158b
TI
1041 snd_printk(KERN_DEBUG
1042 "gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n",
1da177e4
LT
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
42b0158b
TI
1076 snd_printk(KERN_DEBUG
1077 "gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n",
1da177e4
LT
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 */
1124int
03da312a 1125snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data,
1da177e4
LT
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 */
1143static void
03da312a 1144rebuild_presets(struct snd_sf_list *sflist)
1da177e4 1145{
03da312a
TI
1146 struct snd_soundfont *sf;
1147 struct snd_sf_zone *cur;
1da177e4
LT
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 */
1171static void
03da312a 1172add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur)
1da177e4 1173{
03da312a 1174 struct snd_sf_zone *zone;
1da177e4
LT
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 */
03da312a 1180 struct snd_sf_zone *p;
1da177e4
LT
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 */
1203static void
03da312a 1204delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp)
1da177e4
LT
1205{
1206 int index;
03da312a 1207 struct snd_sf_zone *p;
1da177e4
LT
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 */
1229int
03da312a 1230snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel,
1da177e4
LT
1231 int preset, int bank,
1232 int def_preset, int def_bank,
03da312a 1233 struct snd_sf_zone **table, int max_layers)
1da177e4
LT
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 }
03da312a
TI
1247 nvoices = search_zones(sflist, notep, vel, preset, bank,
1248 table, max_layers, 0);
1da177e4
LT
1249 if (! nvoices) {
1250 if (preset != def_preset || bank != def_bank)
03da312a
TI
1251 nvoices = search_zones(sflist, notep, vel,
1252 def_preset, def_bank,
1253 table, max_layers, 0);
1da177e4
LT
1254 }
1255 spin_unlock_irqrestore(&sflist->lock, flags);
1256 return nvoices;
1257}
1258
1259
1260/*
1261 * search the first matching zone
1262 */
03da312a
TI
1263static struct snd_sf_zone *
1264search_first_zone(struct snd_sf_list *sflist, int bank, int preset, int key)
1da177e4
LT
1265{
1266 int index;
03da312a 1267 struct snd_sf_zone *zp;
1da177e4
LT
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 */
1282static int
03da312a
TI
1283search_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)
1da177e4 1286{
03da312a 1287 struct snd_sf_zone *zp;
1da177e4
LT
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 */
1327static int
1328get_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 */
1344static void
03da312a 1345snd_sf_init(struct snd_sf_list *sflist)
1da177e4
LT
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 */
1363static void
03da312a 1364snd_sf_clear(struct snd_sf_list *sflist)
1da177e4 1365{
03da312a
TI
1366 struct snd_soundfont *sf, *nextsf;
1367 struct snd_sf_zone *zp, *nextzp;
1368 struct snd_sf_sample *sp, *nextsp;
1da177e4
LT
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)
03da312a
TI
1379 sflist->callback.sample_free(sflist->callback.private_data,
1380 sp, sflist->memhdr);
1da177e4
LT
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 */
03da312a
TI
1393struct snd_sf_list *
1394snd_sf_new(struct snd_sf_callback *callback, struct snd_util_memhdr *hdr)
1da177e4 1395{
03da312a 1396 struct snd_sf_list *sflist;
1da177e4 1397
561b220a 1398 if ((sflist = kzalloc(sizeof(*sflist), GFP_KERNEL)) == NULL)
1da177e4
LT
1399 return NULL;
1400
ef9f0a42 1401 mutex_init(&sflist->presets_mutex);
1da177e4
LT
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 */
1416void
03da312a 1417snd_sf_free(struct snd_sf_list *sflist)
1da177e4
LT
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 */
1435int
03da312a 1436snd_soundfont_remove_samples(struct snd_sf_list *sflist)
1da177e4
LT
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 */
1451int
03da312a 1452snd_soundfont_remove_unlocked(struct snd_sf_list *sflist)
1da177e4 1453{
03da312a
TI
1454 struct snd_soundfont *sf;
1455 struct snd_sf_zone *zp, *nextzp;
1456 struct snd_sf_sample *sp, *nextsp;
1da177e4
LT
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)
03da312a
TI
1482 sflist->callback.sample_free(sflist->callback.private_data,
1483 sp, sflist->memhdr);
1da177e4
LT
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}