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