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

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

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

~ [ 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