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