~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/synth/emux/soundfont.c

Version: ~ [ linux-5.9.1 ] ~ [ linux-5.8.16 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.72 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.152 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.202 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.240 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.240 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 <linux/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
107 snd_soundfont_close_check(struct snd_sf_list *sflist, int client)
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) {
179         case SNDRV_SFNT_LOAD_INFO:
180                 rc = load_info(sflist, data, count);
181                 break;
182         case SNDRV_SFNT_LOAD_DATA:
183                 rc = load_data(sflist, data, count);
184                 break;
185         case SNDRV_SFNT_CLOSE_PATCH:
186                 rc = close_patch(sflist);
187                 break;
188         case SNDRV_SFNT_REPLACE_DATA:
189                 /*rc = replace_data(&patch, data, count);*/
190                 break;
191         case SNDRV_SFNT_MAP_PRESET:
192                 rc = load_map(sflist, data, count);
193                 break;
194         case SNDRV_SFNT_PROBE_DATA:
195                 rc = probe_data(sflist, patch.optarg);
196                 break;
197         case SNDRV_SFNT_REMOVE_INFO:
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)
298                 memcpy(sf->name, name, SNDRV_SFNT_PATCH_NAME_LEN);
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;
526         struct soundfont_voice_rec_hdr hdr;
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) {
560         case SNDRV_SFNT_WR_EXCLUSIVE:
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;
570         case SNDRV_SFNT_WR_REPLACE:
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 
817 EXPORT_SYMBOL(snd_sf_linear_to_log);
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 {
835         return snd_sf_linear_to_log(mhz, OFFSET_ABSCENT, ABSCENT_RATIO);
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 {
848         return snd_sf_linear_to_log(hz, OFFSET_SAMPLERATE, SAMPLERATE_RATIO);
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
895 snd_sf_calc_parm_hold(int msec)
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
920 snd_sf_calc_parm_attack(int msec)
921 {
922         return calc_parm_search(msec, attack_time_tbl);
923 }
924 
925 /* decay/release time: search from time table */
926 int
927 snd_sf_calc_parm_decay(int msec)
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;
989         if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP|WAVE_LOOP_BACK)))
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                         kfree(zone);
1025                         return rc;
1026                 }
1027                 /* memory offset is updated after */
1028         }
1029 
1030         /* update the memory offset here */
1031         sflist->mem_used += smp->v.truesize;
1032 
1033         zone->v.sample = sample_id; /* the last sample */
1034         zone->v.rate_offset = calc_rate_offset(patch.base_freq);
1035         note = freq_to_note(patch.base_note);
1036         zone->v.root = note / 100;
1037         zone->v.tune = -(note % 100);
1038         zone->v.low = (freq_to_note(patch.low_note) + 99) / 100;
1039         zone->v.high = freq_to_note(patch.high_note) / 100;
1040         /* panning position; -128 - 127 => 0-127 */
1041         zone->v.pan = (patch.panning + 128) / 2;
1042 #if 0
1043         snd_printk(KERN_DEBUG
1044                    "gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n",
1045                    (int)patch.base_freq, zone->v.rate_offset,
1046                    zone->v.root, zone->v.tune, zone->v.low, zone->v.high);
1047 #endif
1048 
1049         /* detuning is ignored */
1050         /* 6points volume envelope */
1051         if (patch.mode & WAVE_ENVELOPES) {
1052                 int attack, hold, decay, release;
1053                 attack = calc_gus_envelope_time
1054                         (patch.env_rate[0], 0, patch.env_offset[0]);
1055                 hold = calc_gus_envelope_time
1056                         (patch.env_rate[1], patch.env_offset[0],
1057                          patch.env_offset[1]);
1058                 decay = calc_gus_envelope_time
1059                         (patch.env_rate[2], patch.env_offset[1],
1060                          patch.env_offset[2]);
1061                 release = calc_gus_envelope_time
1062                         (patch.env_rate[3], patch.env_offset[1],
1063                          patch.env_offset[4]);
1064                 release += calc_gus_envelope_time
1065                         (patch.env_rate[4], patch.env_offset[3],
1066                          patch.env_offset[4]);
1067                 release += calc_gus_envelope_time
1068                         (patch.env_rate[5], patch.env_offset[4],
1069                          patch.env_offset[5]);
1070                 zone->v.parm.volatkhld = 
1071                         (snd_sf_calc_parm_hold(hold) << 8) |
1072                         snd_sf_calc_parm_attack(attack);
1073                 zone->v.parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) |
1074                         snd_sf_calc_parm_decay(decay);
1075                 zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release);
1076                 zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]);
1077 #if 0
1078                 snd_printk(KERN_DEBUG
1079                            "gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n",
1080                            zone->v.parm.volatkhld,
1081                            zone->v.parm.voldcysus,
1082                            zone->v.parm.volrelease,
1083                            zone->v.attenuation);
1084 #endif
1085         }
1086 
1087         /* fast release */
1088         if (patch.mode & WAVE_FAST_RELEASE) {
1089                 zone->v.parm.volrelease = 0x807f;
1090         }
1091 
1092         /* tremolo effect */
1093         if (patch.mode & WAVE_TREMOLO) {
1094                 int rate = (patch.tremolo_rate * 1000 / 38) / 42;
1095                 zone->v.parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate;
1096         }
1097         /* vibrato effect */
1098         if (patch.mode & WAVE_VIBRATO) {
1099                 int rate = (patch.vibrato_rate * 1000 / 38) / 42;
1100                 zone->v.parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate;
1101         }
1102         
1103         /* scale_freq, scale_factor, volume, and fractions not implemented */
1104 
1105         if (!(smp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT))
1106                 zone->v.mode = SNDRV_SFNT_MODE_LOOPING;
1107         else
1108                 zone->v.mode = 0;
1109 
1110         /* append to the tail of the list */
1111         /*zone->bank = ctrls[AWE_MD_GUS_BANK];*/
1112         zone->bank = 0;
1113         zone->instr = patch.instr_no;
1114         zone->mapped = 0;
1115         zone->v.sf_id = sf->id;
1116 
1117         zone->sample = set_sample(sf, &zone->v);
1118 
1119         /* rebuild preset now */
1120         add_preset(sflist, zone);
1121 
1122         return 0;
1123 }
1124 
1125 /* load GUS patch */
1126 int
1127 snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data,
1128                             long count, int client)
1129 {
1130         int rc;
1131         lock_preset(sflist);
1132         rc = load_guspatch(sflist, data, count, client);
1133         unlock_preset(sflist);
1134         return rc;
1135 }
1136 
1137 
1138 /*
1139  * Rebuild the preset table.  This is like a hash table in that it allows
1140  * quick access to the zone information.  For each preset there are zone
1141  * structures linked by next_instr and by next_zone.  Former is the whole
1142  * link for this preset, and latter is the link for zone (i.e. instrument/
1143  * bank/key combination).
1144  */
1145 static void
1146 rebuild_presets(struct snd_sf_list *sflist)
1147 {
1148         struct snd_soundfont *sf;
1149         struct snd_sf_zone *cur;
1150 
1151         /* clear preset table */
1152         memset(sflist->presets, 0, sizeof(sflist->presets));
1153 
1154         /* search all fonts and insert each font */
1155         for (sf = sflist->fonts; sf; sf = sf->next) {
1156                 for (cur = sf->zones; cur; cur = cur->next) {
1157                         if (! cur->mapped && cur->sample == NULL) {
1158                                 /* try again to search the corresponding sample */
1159                                 cur->sample = set_sample(sf, &cur->v);
1160                                 if (cur->sample == NULL)
1161                                         continue;
1162                         }
1163 
1164                         add_preset(sflist, cur);
1165                 }
1166         }
1167 }
1168 
1169 
1170 /*
1171  * add the given zone to preset table
1172  */
1173 static void
1174 add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur)
1175 {
1176         struct snd_sf_zone *zone;
1177         int index;
1178 
1179         zone = search_first_zone(sflist, cur->bank, cur->instr, cur->v.low);
1180         if (zone && zone->v.sf_id != cur->v.sf_id) {
1181                 /* different instrument was already defined */
1182                 struct snd_sf_zone *p;
1183                 /* compare the allocated time */
1184                 for (p = zone; p; p = p->next_zone) {
1185                         if (p->counter > cur->counter)
1186                                 /* the current is older.. skipped */
1187                                 return;
1188                 }
1189                 /* remove old zones */
1190                 delete_preset(sflist, zone);
1191                 zone = NULL; /* do not forget to clear this! */
1192         }
1193 
1194         /* prepend this zone */
1195         if ((index = get_index(cur->bank, cur->instr, cur->v.low)) < 0)
1196                 return;
1197         cur->next_zone = zone; /* zone link */
1198         cur->next_instr = sflist->presets[index]; /* preset table link */
1199         sflist->presets[index] = cur;
1200 }
1201 
1202 /*
1203  * delete the given zones from preset_table
1204  */
1205 static void
1206 delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp)
1207 {
1208         int index;
1209         struct snd_sf_zone *p;
1210 
1211         if ((index = get_index(zp->bank, zp->instr, zp->v.low)) < 0)
1212                 return;
1213         for (p = sflist->presets[index]; p; p = p->next_instr) {
1214                 while (p->next_instr == zp) {
1215                         p->next_instr = zp->next_instr;
1216                         zp = zp->next_zone;
1217                         if (zp == NULL)
1218                                 return;
1219                 }
1220         }
1221 }
1222 
1223 
1224 /*
1225  * Search matching zones from preset table.
1226  * The note can be rewritten by preset mapping (alias).
1227  * The found zones are stored on 'table' array.  max_layers defines
1228  * the maximum number of elements in this array.
1229  * This function returns the number of found zones.  0 if not found.
1230  */
1231 int
1232 snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel,
1233                           int preset, int bank,
1234                           int def_preset, int def_bank,
1235                           struct snd_sf_zone **table, int max_layers)
1236 {
1237         int nvoices;
1238         unsigned long flags;
1239 
1240         /* this function is supposed to be called atomically,
1241          * so we check the lock.  if it's busy, just returns 0 to
1242          * tell the caller the busy state
1243          */
1244         spin_lock_irqsave(&sflist->lock, flags);
1245         if (sflist->presets_locked) {
1246                 spin_unlock_irqrestore(&sflist->lock, flags);
1247                 return 0;
1248         }
1249         nvoices = search_zones(sflist, notep, vel, preset, bank,
1250                                table, max_layers, 0);
1251         if (! nvoices) {
1252                 if (preset != def_preset || bank != def_bank)
1253                         nvoices = search_zones(sflist, notep, vel,
1254                                                def_preset, def_bank,
1255                                                table, max_layers, 0);
1256         }
1257         spin_unlock_irqrestore(&sflist->lock, flags);
1258         return nvoices;
1259 }
1260 
1261 
1262 /*
1263  * search the first matching zone
1264  */
1265 static struct snd_sf_zone *
1266 search_first_zone(struct snd_sf_list *sflist, int bank, int preset, int key)
1267 {
1268         int index;
1269         struct snd_sf_zone *zp;
1270 
1271         if ((index = get_index(bank, preset, key)) < 0)
1272                 return NULL;
1273         for (zp = sflist->presets[index]; zp; zp = zp->next_instr) {
1274                 if (zp->instr == preset && zp->bank == bank)
1275                         return zp;
1276         }
1277         return NULL;
1278 }
1279 
1280 
1281 /*
1282  * search matching zones from sflist.  can be called recursively.
1283  */
1284 static int
1285 search_zones(struct snd_sf_list *sflist, int *notep, int vel,
1286              int preset, int bank, struct snd_sf_zone **table,
1287              int max_layers, int level)
1288 {
1289         struct snd_sf_zone *zp;
1290         int nvoices;
1291 
1292         zp = search_first_zone(sflist, bank, preset, *notep);
1293         nvoices = 0;
1294         for (; zp; zp = zp->next_zone) {
1295                 if (*notep >= zp->v.low && *notep <= zp->v.high &&
1296                     vel >= zp->v.vellow && vel <= zp->v.velhigh) {
1297                         if (zp->mapped) {
1298                                 /* search preset mapping (aliasing) */
1299                                 int key = zp->v.fixkey;
1300                                 preset = zp->v.start;
1301                                 bank = zp->v.end;
1302 
1303                                 if (level > 5) /* too deep alias level */
1304                                         return 0;
1305                                 if (key < 0)
1306                                         key = *notep;
1307                                 nvoices = search_zones(sflist, &key, vel,
1308                                                        preset, bank, table,
1309                                                        max_layers, level + 1);
1310                                 if (nvoices > 0)
1311                                         *notep = key;
1312                                 break;
1313                         }
1314                         table[nvoices++] = zp;
1315                         if (nvoices >= max_layers)
1316                                 break;
1317                 }
1318         }
1319 
1320         return nvoices;
1321 }
1322 
1323 
1324 /* calculate the index of preset table:
1325  * drums are mapped from 128 to 255 according to its note key.
1326  * other instruments are mapped from 0 to 127.
1327  * if the index is out of range, return -1.
1328  */
1329 static int
1330 get_index(int bank, int instr, int key)
1331 {
1332         int index;
1333         if (SF_IS_DRUM_BANK(bank))
1334                 index = key + SF_MAX_INSTRUMENTS;
1335         else
1336                 index = instr;
1337         index = index % SF_MAX_PRESETS;
1338         if (index < 0)
1339                 return -1;
1340         return index;
1341 }
1342 
1343 /*
1344  * Initialise the sflist structure.
1345  */
1346 static void
1347 snd_sf_init(struct snd_sf_list *sflist)
1348 {
1349         memset(sflist->presets, 0, sizeof(sflist->presets));
1350 
1351         sflist->mem_used = 0;
1352         sflist->currsf = NULL;
1353         sflist->open_client = -1;
1354         sflist->fonts = NULL;
1355         sflist->fonts_size = 0;
1356         sflist->zone_counter = 0;
1357         sflist->sample_counter = 0;
1358         sflist->zone_locked = 0;
1359         sflist->sample_locked = 0;
1360 }
1361 
1362 /*
1363  * Release all list records
1364  */
1365 static void
1366 snd_sf_clear(struct snd_sf_list *sflist)
1367 {
1368         struct snd_soundfont *sf, *nextsf;
1369         struct snd_sf_zone *zp, *nextzp;
1370         struct snd_sf_sample *sp, *nextsp;
1371 
1372         for (sf = sflist->fonts; sf; sf = nextsf) {
1373                 nextsf = sf->next;
1374                 for (zp = sf->zones; zp; zp = nextzp) {
1375                         nextzp = zp->next;
1376                         kfree(zp);
1377                 }
1378                 for (sp = sf->samples; sp; sp = nextsp) {
1379                         nextsp = sp->next;
1380                         if (sflist->callback.sample_free)
1381                                 sflist->callback.sample_free(sflist->callback.private_data,
1382                                                              sp, sflist->memhdr);
1383                         kfree(sp);
1384                 }
1385                 kfree(sf);
1386         }
1387 
1388         snd_sf_init(sflist);
1389 }
1390 
1391 
1392 /*
1393  * Create a new sflist structure
1394  */
1395 struct snd_sf_list *
1396 snd_sf_new(struct snd_sf_callback *callback, struct snd_util_memhdr *hdr)
1397 {
1398         struct snd_sf_list *sflist;
1399 
1400         if ((sflist = kzalloc(sizeof(*sflist), GFP_KERNEL)) == NULL)
1401                 return NULL;
1402 
1403         mutex_init(&sflist->presets_mutex);
1404         spin_lock_init(&sflist->lock);
1405         sflist->memhdr = hdr;
1406 
1407         if (callback)
1408                 sflist->callback = *callback;
1409 
1410         snd_sf_init(sflist);
1411         return sflist;
1412 }
1413 
1414 
1415 /*
1416  * Free everything allocated off the sflist structure.
1417  */
1418 void
1419 snd_sf_free(struct snd_sf_list *sflist)
1420 {
1421         if (sflist == NULL)
1422                 return;
1423         
1424         lock_preset(sflist);
1425         if (sflist->callback.sample_reset)
1426                 sflist->callback.sample_reset(sflist->callback.private_data);
1427         snd_sf_clear(sflist);
1428         unlock_preset(sflist);
1429 
1430         kfree(sflist);
1431 }
1432 
1433 /*
1434  * Remove all samples
1435  * The soundcard should be silet before calling this function.
1436  */
1437 int
1438 snd_soundfont_remove_samples(struct snd_sf_list *sflist)
1439 {
1440         lock_preset(sflist);
1441         if (sflist->callback.sample_reset)
1442                 sflist->callback.sample_reset(sflist->callback.private_data);
1443         snd_sf_clear(sflist);
1444         unlock_preset(sflist);
1445 
1446         return 0;
1447 }
1448 
1449 /*
1450  * Remove unlocked samples.
1451  * The soundcard should be silent before calling this function.
1452  */
1453 int
1454 snd_soundfont_remove_unlocked(struct snd_sf_list *sflist)
1455 {
1456         struct snd_soundfont *sf;
1457         struct snd_sf_zone *zp, *nextzp;
1458         struct snd_sf_sample *sp, *nextsp;
1459 
1460         lock_preset(sflist);
1461 
1462         if (sflist->callback.sample_reset)
1463                 sflist->callback.sample_reset(sflist->callback.private_data);
1464 
1465         /* to be sure */
1466         memset(sflist->presets, 0, sizeof(sflist->presets));
1467 
1468         for (sf = sflist->fonts; sf; sf = sf->next) {
1469                 for (zp = sf->zones; zp; zp = nextzp) {
1470                         if (zp->counter < sflist->zone_locked)
1471                                 break;
1472                         nextzp = zp->next;
1473                         sf->zones = nextzp;
1474                         kfree(zp);
1475                 }
1476 
1477                 for (sp = sf->samples; sp; sp = nextsp) {
1478                         if (sp->counter < sflist->sample_locked)
1479                                 break;
1480                         nextsp = sp->next;
1481                         sf->samples = nextsp;
1482                         sflist->mem_used -= sp->v.truesize;
1483                         if (sflist->callback.sample_free)
1484                                 sflist->callback.sample_free(sflist->callback.private_data,
1485                                                              sp, sflist->memhdr);
1486                         kfree(sp);
1487                 }
1488         }
1489 
1490         sflist->zone_counter = sflist->zone_locked;
1491         sflist->sample_counter = sflist->sample_locked;
1492 
1493         rebuild_presets(sflist);
1494 
1495         unlock_preset(sflist);
1496         return 0;
1497 }
1498 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp