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