Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Soundfont generic routines.
0004  *  It is intended that these should be used by any driver that is willing
0005  *  to accept soundfont patches.
0006  *
0007  *  Copyright (C) 1999 Steve Ratcliffe
0008  *  Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>
0009  */
0010 /*
0011  * Deal with reading in of a soundfont.  Code follows the OSS way
0012  * of doing things so that the old sfxload utility can be used.
0013  * Everything may change when there is an alsa way of doing things.
0014  */
0015 #include <linux/uaccess.h>
0016 #include <linux/slab.h>
0017 #include <linux/export.h>
0018 #include <sound/core.h>
0019 #include <sound/soundfont.h>
0020 #include <sound/seq_oss_legacy.h>
0021 
0022 /* Prototypes for static functions */
0023 
0024 static int open_patch(struct snd_sf_list *sflist, const char __user *data,
0025               int count, int client);
0026 static struct snd_soundfont *newsf(struct snd_sf_list *sflist, int type, char *name);
0027 static int is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name);
0028 static int close_patch(struct snd_sf_list *sflist);
0029 static int probe_data(struct snd_sf_list *sflist, int sample_id);
0030 static void set_zone_counter(struct snd_sf_list *sflist,
0031                  struct snd_soundfont *sf, struct snd_sf_zone *zp);
0032 static struct snd_sf_zone *sf_zone_new(struct snd_sf_list *sflist,
0033                        struct snd_soundfont *sf);
0034 static void set_sample_counter(struct snd_sf_list *sflist,
0035                    struct snd_soundfont *sf, struct snd_sf_sample *sp);
0036 static struct snd_sf_sample *sf_sample_new(struct snd_sf_list *sflist,
0037                        struct snd_soundfont *sf);
0038 static void sf_sample_delete(struct snd_sf_list *sflist,
0039                  struct snd_soundfont *sf, struct snd_sf_sample *sp);
0040 static int load_map(struct snd_sf_list *sflist, const void __user *data, int count);
0041 static int load_info(struct snd_sf_list *sflist, const void __user *data, long count);
0042 static int remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf,
0043                int bank, int instr);
0044 static void init_voice_info(struct soundfont_voice_info *avp);
0045 static void init_voice_parm(struct soundfont_voice_parm *pp);
0046 static struct snd_sf_sample *set_sample(struct snd_soundfont *sf,
0047                     struct soundfont_voice_info *avp);
0048 static struct snd_sf_sample *find_sample(struct snd_soundfont *sf, int sample_id);
0049 static int load_data(struct snd_sf_list *sflist, const void __user *data, long count);
0050 static void rebuild_presets(struct snd_sf_list *sflist);
0051 static void add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur);
0052 static void delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp);
0053 static struct snd_sf_zone *search_first_zone(struct snd_sf_list *sflist,
0054                          int bank, int preset, int key);
0055 static int search_zones(struct snd_sf_list *sflist, int *notep, int vel,
0056             int preset, int bank, struct snd_sf_zone **table,
0057             int max_layers, int level);
0058 static int get_index(int bank, int instr, int key);
0059 static void snd_sf_init(struct snd_sf_list *sflist);
0060 static void snd_sf_clear(struct snd_sf_list *sflist);
0061 
0062 /*
0063  * lock access to sflist
0064  */
0065 static void
0066 lock_preset(struct snd_sf_list *sflist)
0067 {
0068     unsigned long flags;
0069     mutex_lock(&sflist->presets_mutex);
0070     spin_lock_irqsave(&sflist->lock, flags);
0071     sflist->presets_locked = 1;
0072     spin_unlock_irqrestore(&sflist->lock, flags);
0073 }
0074 
0075 
0076 /*
0077  * remove lock
0078  */
0079 static void
0080 unlock_preset(struct snd_sf_list *sflist)
0081 {
0082     unsigned long flags;
0083     spin_lock_irqsave(&sflist->lock, flags);
0084     sflist->presets_locked = 0;
0085     spin_unlock_irqrestore(&sflist->lock, flags);
0086     mutex_unlock(&sflist->presets_mutex);
0087 }
0088 
0089 
0090 /*
0091  * close the patch if the patch was opened by this client.
0092  */
0093 int
0094 snd_soundfont_close_check(struct snd_sf_list *sflist, int client)
0095 {
0096     unsigned long flags;
0097     spin_lock_irqsave(&sflist->lock, flags);
0098     if (sflist->open_client == client)  {
0099         spin_unlock_irqrestore(&sflist->lock, flags);
0100         return close_patch(sflist);
0101     }
0102     spin_unlock_irqrestore(&sflist->lock, flags);
0103     return 0;
0104 }
0105 
0106 
0107 /*
0108  * Deal with a soundfont patch.  Any driver could use these routines
0109  * although it was designed for the AWE64.
0110  *
0111  * The sample_write and callargs parameters allow a callback into
0112  * the actual driver to write sample data to the board or whatever
0113  * it wants to do with it.
0114  */
0115 int
0116 snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data,
0117            long count, int client)
0118 {
0119     struct soundfont_patch_info patch;
0120     unsigned long flags;
0121     int  rc;
0122 
0123     if (count < (long)sizeof(patch)) {
0124         snd_printk(KERN_ERR "patch record too small %ld\n", count);
0125         return -EINVAL;
0126     }
0127     if (copy_from_user(&patch, data, sizeof(patch)))
0128         return -EFAULT;
0129 
0130     count -= sizeof(patch);
0131     data += sizeof(patch);
0132 
0133     if (patch.key != SNDRV_OSS_SOUNDFONT_PATCH) {
0134         snd_printk(KERN_ERR "The wrong kind of patch %x\n", patch.key);
0135         return -EINVAL;
0136     }
0137     if (count < patch.len) {
0138         snd_printk(KERN_ERR "Patch too short %ld, need %d\n",
0139                count, patch.len);
0140         return -EINVAL;
0141     }
0142     if (patch.len < 0) {
0143         snd_printk(KERN_ERR "poor length %d\n", patch.len);
0144         return -EINVAL;
0145     }
0146 
0147     if (patch.type == SNDRV_SFNT_OPEN_PATCH) {
0148         /* grab sflist to open */
0149         lock_preset(sflist);
0150         rc = open_patch(sflist, data, count, client);
0151         unlock_preset(sflist);
0152         return rc;
0153     }
0154 
0155     /* check if other client already opened patch */
0156     spin_lock_irqsave(&sflist->lock, flags);
0157     if (sflist->open_client != client) {
0158         spin_unlock_irqrestore(&sflist->lock, flags);
0159         return -EBUSY;
0160     }
0161     spin_unlock_irqrestore(&sflist->lock, flags);
0162 
0163     lock_preset(sflist);
0164     rc = -EINVAL;
0165     switch (patch.type) {
0166     case SNDRV_SFNT_LOAD_INFO:
0167         rc = load_info(sflist, data, count);
0168         break;
0169     case SNDRV_SFNT_LOAD_DATA:
0170         rc = load_data(sflist, data, count);
0171         break;
0172     case SNDRV_SFNT_CLOSE_PATCH:
0173         rc = close_patch(sflist);
0174         break;
0175     case SNDRV_SFNT_REPLACE_DATA:
0176         /*rc = replace_data(&patch, data, count);*/
0177         break;
0178     case SNDRV_SFNT_MAP_PRESET:
0179         rc = load_map(sflist, data, count);
0180         break;
0181     case SNDRV_SFNT_PROBE_DATA:
0182         rc = probe_data(sflist, patch.optarg);
0183         break;
0184     case SNDRV_SFNT_REMOVE_INFO:
0185         /* patch must be opened */
0186         if (!sflist->currsf) {
0187             snd_printk(KERN_ERR "soundfont: remove_info: "
0188                    "patch not opened\n");
0189             rc = -EINVAL;
0190         } else {
0191             int bank, instr;
0192             bank = ((unsigned short)patch.optarg >> 8) & 0xff;
0193             instr = (unsigned short)patch.optarg & 0xff;
0194             if (! remove_info(sflist, sflist->currsf, bank, instr))
0195                 rc = -EINVAL;
0196             else
0197                 rc = 0;
0198         }
0199         break;
0200     }
0201     unlock_preset(sflist);
0202 
0203     return rc;
0204 }
0205 
0206 
0207 /* check if specified type is special font (GUS or preset-alias) */
0208 static inline int
0209 is_special_type(int type)
0210 {
0211     type &= 0x0f;
0212     return (type == SNDRV_SFNT_PAT_TYPE_GUS ||
0213         type == SNDRV_SFNT_PAT_TYPE_MAP);
0214 }
0215 
0216 
0217 /* open patch; create sf list */
0218 static int
0219 open_patch(struct snd_sf_list *sflist, const char __user *data,
0220        int count, int client)
0221 {
0222     struct soundfont_open_parm parm;
0223     struct snd_soundfont *sf;
0224     unsigned long flags;
0225 
0226     spin_lock_irqsave(&sflist->lock, flags);
0227     if (sflist->open_client >= 0 || sflist->currsf) {
0228         spin_unlock_irqrestore(&sflist->lock, flags);
0229         return -EBUSY;
0230     }
0231     spin_unlock_irqrestore(&sflist->lock, flags);
0232 
0233     if (copy_from_user(&parm, data, sizeof(parm)))
0234         return -EFAULT;
0235 
0236     if (is_special_type(parm.type)) {
0237         parm.type |= SNDRV_SFNT_PAT_SHARED;
0238         sf = newsf(sflist, parm.type, NULL);
0239     } else 
0240         sf = newsf(sflist, parm.type, parm.name);
0241     if (sf == NULL) {
0242         return -ENOMEM;
0243     }
0244 
0245     spin_lock_irqsave(&sflist->lock, flags);
0246     sflist->open_client = client;
0247     sflist->currsf = sf;
0248     spin_unlock_irqrestore(&sflist->lock, flags);
0249 
0250     return 0;
0251 }
0252 
0253 /*
0254  * Allocate a new soundfont structure.
0255  */
0256 static struct snd_soundfont *
0257 newsf(struct snd_sf_list *sflist, int type, char *name)
0258 {
0259     struct snd_soundfont *sf;
0260 
0261     /* check the shared fonts */
0262     if (type & SNDRV_SFNT_PAT_SHARED) {
0263         for (sf = sflist->fonts; sf; sf = sf->next) {
0264             if (is_identical_font(sf, type, name)) {
0265                 return sf;
0266             }
0267         }
0268     }
0269 
0270     /* not found -- create a new one */
0271     sf = kzalloc(sizeof(*sf), GFP_KERNEL);
0272     if (sf == NULL)
0273         return NULL;
0274     sf->id = sflist->fonts_size;
0275     sflist->fonts_size++;
0276 
0277     /* prepend this record */
0278     sf->next = sflist->fonts;
0279     sflist->fonts = sf;
0280 
0281     sf->type = type;
0282     sf->zones = NULL;
0283     sf->samples = NULL;
0284     if (name)
0285         memcpy(sf->name, name, SNDRV_SFNT_PATCH_NAME_LEN);
0286 
0287     return sf;
0288 }
0289 
0290 /* check if the given name matches to the existing list */
0291 static int
0292 is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name)
0293 {
0294     return ((sf->type & SNDRV_SFNT_PAT_SHARED) &&
0295         (sf->type & 0x0f) == (type & 0x0f) &&
0296         (name == NULL ||
0297          memcmp(sf->name, name, SNDRV_SFNT_PATCH_NAME_LEN) == 0));
0298 }
0299 
0300 /*
0301  * Close the current patch.
0302  */
0303 static int
0304 close_patch(struct snd_sf_list *sflist)
0305 {
0306     unsigned long flags;
0307 
0308     spin_lock_irqsave(&sflist->lock, flags);
0309     sflist->currsf = NULL;
0310     sflist->open_client = -1;
0311     spin_unlock_irqrestore(&sflist->lock, flags);
0312 
0313     rebuild_presets(sflist);
0314 
0315     return 0;
0316 
0317 }
0318 
0319 /* probe sample in the current list -- nothing to be loaded */
0320 static int
0321 probe_data(struct snd_sf_list *sflist, int sample_id)
0322 {
0323     /* patch must be opened */
0324     if (sflist->currsf) {
0325         /* search the specified sample by optarg */
0326         if (find_sample(sflist->currsf, sample_id))
0327             return 0;
0328     }
0329     return -EINVAL;
0330 }
0331 
0332 /*
0333  * increment zone counter
0334  */
0335 static void
0336 set_zone_counter(struct snd_sf_list *sflist, struct snd_soundfont *sf,
0337          struct snd_sf_zone *zp)
0338 {
0339     zp->counter = sflist->zone_counter++;
0340     if (sf->type & SNDRV_SFNT_PAT_LOCKED)
0341         sflist->zone_locked = sflist->zone_counter;
0342 }
0343 
0344 /*
0345  * allocate a new zone record
0346  */
0347 static struct snd_sf_zone *
0348 sf_zone_new(struct snd_sf_list *sflist, struct snd_soundfont *sf)
0349 {
0350     struct snd_sf_zone *zp;
0351 
0352     zp = kzalloc(sizeof(*zp), GFP_KERNEL);
0353     if (!zp)
0354         return NULL;
0355     zp->next = sf->zones;
0356     sf->zones = zp;
0357 
0358     init_voice_info(&zp->v);
0359 
0360     set_zone_counter(sflist, sf, zp);
0361     return zp;
0362 }
0363 
0364 
0365 /*
0366  * increment sample counter
0367  */
0368 static void
0369 set_sample_counter(struct snd_sf_list *sflist, struct snd_soundfont *sf,
0370            struct snd_sf_sample *sp)
0371 {
0372     sp->counter = sflist->sample_counter++;
0373     if (sf->type & SNDRV_SFNT_PAT_LOCKED)
0374         sflist->sample_locked = sflist->sample_counter;
0375 }
0376 
0377 /*
0378  * allocate a new sample list record
0379  */
0380 static struct snd_sf_sample *
0381 sf_sample_new(struct snd_sf_list *sflist, struct snd_soundfont *sf)
0382 {
0383     struct snd_sf_sample *sp;
0384 
0385     sp = kzalloc(sizeof(*sp), GFP_KERNEL);
0386     if (!sp)
0387         return NULL;
0388 
0389     sp->next = sf->samples;
0390     sf->samples = sp;
0391 
0392     set_sample_counter(sflist, sf, sp);
0393     return sp;
0394 }
0395 
0396 /*
0397  * delete sample list -- this is an exceptional job.
0398  * only the last allocated sample can be deleted.
0399  */
0400 static void
0401 sf_sample_delete(struct snd_sf_list *sflist, struct snd_soundfont *sf,
0402          struct snd_sf_sample *sp)
0403 {
0404     /* only last sample is accepted */
0405     if (sp == sf->samples) {
0406         sf->samples = sp->next;
0407         kfree(sp);
0408     }
0409 }
0410 
0411 
0412 /* load voice map */
0413 static int
0414 load_map(struct snd_sf_list *sflist, const void __user *data, int count)
0415 {
0416     struct snd_sf_zone *zp, *prevp;
0417     struct snd_soundfont *sf;
0418     struct soundfont_voice_map map;
0419 
0420     /* get the link info */
0421     if (count < (int)sizeof(map))
0422         return -EINVAL;
0423     if (copy_from_user(&map, data, sizeof(map)))
0424         return -EFAULT;
0425 
0426     if (map.map_instr < 0 || map.map_instr >= SF_MAX_INSTRUMENTS)
0427         return -EINVAL;
0428     
0429     sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_MAP|SNDRV_SFNT_PAT_SHARED, NULL);
0430     if (sf == NULL)
0431         return -ENOMEM;
0432 
0433     prevp = NULL;
0434     for (zp = sf->zones; zp; prevp = zp, zp = zp->next) {
0435         if (zp->mapped &&
0436             zp->instr == map.map_instr &&
0437             zp->bank == map.map_bank &&
0438             zp->v.low == map.map_key &&
0439             zp->v.start == map.src_instr &&
0440             zp->v.end == map.src_bank &&
0441             zp->v.fixkey == map.src_key) {
0442             /* the same mapping is already present */
0443             /* relink this record to the link head */
0444             if (prevp) {
0445                 prevp->next = zp->next;
0446                 zp->next = sf->zones;
0447                 sf->zones = zp;
0448             }
0449             /* update the counter */
0450             set_zone_counter(sflist, sf, zp);
0451             return 0;
0452         }
0453     }
0454 
0455     /* create a new zone */
0456     zp = sf_zone_new(sflist, sf);
0457     if (!zp)
0458         return -ENOMEM;
0459 
0460     zp->bank = map.map_bank;
0461     zp->instr = map.map_instr;
0462     zp->mapped = 1;
0463     if (map.map_key >= 0) {
0464         zp->v.low = map.map_key;
0465         zp->v.high = map.map_key;
0466     }
0467     zp->v.start = map.src_instr;
0468     zp->v.end = map.src_bank;
0469     zp->v.fixkey = map.src_key;
0470     zp->v.sf_id = sf->id;
0471 
0472     add_preset(sflist, zp);
0473 
0474     return 0;
0475 }
0476 
0477 
0478 /* remove the present instrument layers */
0479 static int
0480 remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf,
0481         int bank, int instr)
0482 {
0483     struct snd_sf_zone *prev, *next, *p;
0484     int removed = 0;
0485 
0486     prev = NULL;
0487     for (p = sf->zones; p; p = next) {
0488         next = p->next;
0489         if (! p->mapped &&
0490             p->bank == bank && p->instr == instr) {
0491             /* remove this layer */
0492             if (prev)
0493                 prev->next = next;
0494             else
0495                 sf->zones = next;
0496             removed++;
0497             kfree(p);
0498         } else
0499             prev = p;
0500     }
0501     if (removed)
0502         rebuild_presets(sflist);
0503     return removed;
0504 }
0505 
0506 
0507 /*
0508  * Read an info record from the user buffer and save it on the current
0509  * open soundfont.
0510  */
0511 static int
0512 load_info(struct snd_sf_list *sflist, const void __user *data, long count)
0513 {
0514     struct snd_soundfont *sf;
0515     struct snd_sf_zone *zone;
0516     struct soundfont_voice_rec_hdr hdr;
0517     int i;
0518 
0519     /* patch must be opened */
0520     sf = sflist->currsf;
0521     if (!sf)
0522         return -EINVAL;
0523 
0524     if (is_special_type(sf->type))
0525         return -EINVAL;
0526 
0527     if (count < (long)sizeof(hdr)) {
0528         printk(KERN_ERR "Soundfont error: invalid patch zone length\n");
0529         return -EINVAL;
0530     }
0531     if (copy_from_user((char*)&hdr, data, sizeof(hdr)))
0532         return -EFAULT;
0533     
0534     data += sizeof(hdr);
0535     count -= sizeof(hdr);
0536 
0537     if (hdr.nvoices <= 0 || hdr.nvoices >= 100) {
0538         printk(KERN_ERR "Soundfont error: Illegal voice number %d\n",
0539                hdr.nvoices);
0540         return -EINVAL;
0541     }
0542 
0543     if (count < (long)sizeof(struct soundfont_voice_info) * hdr.nvoices) {
0544         printk(KERN_ERR "Soundfont Error: "
0545                "patch length(%ld) is smaller than nvoices(%d)\n",
0546                count, hdr.nvoices);
0547         return -EINVAL;
0548     }
0549 
0550     switch (hdr.write_mode) {
0551     case SNDRV_SFNT_WR_EXCLUSIVE:
0552         /* exclusive mode - if the instrument already exists,
0553            return error */
0554         for (zone = sf->zones; zone; zone = zone->next) {
0555             if (!zone->mapped &&
0556                 zone->bank == hdr.bank &&
0557                 zone->instr == hdr.instr)
0558                 return -EINVAL;
0559         }
0560         break;
0561     case SNDRV_SFNT_WR_REPLACE:
0562         /* replace mode - remove the instrument if it already exists */
0563         remove_info(sflist, sf, hdr.bank, hdr.instr);
0564         break;
0565     }
0566 
0567     for (i = 0; i < hdr.nvoices; i++) {
0568         struct snd_sf_zone tmpzone;
0569 
0570         /* copy awe_voice_info parameters */
0571         if (copy_from_user(&tmpzone.v, data, sizeof(tmpzone.v))) {
0572             return -EFAULT;
0573         }
0574 
0575         data += sizeof(tmpzone.v);
0576         count -= sizeof(tmpzone.v);
0577 
0578         tmpzone.bank = hdr.bank;
0579         tmpzone.instr = hdr.instr;
0580         tmpzone.mapped = 0;
0581         tmpzone.v.sf_id = sf->id;
0582         if (tmpzone.v.mode & SNDRV_SFNT_MODE_INIT_PARM)
0583             init_voice_parm(&tmpzone.v.parm);
0584 
0585         /* create a new zone */
0586         zone = sf_zone_new(sflist, sf);
0587         if (!zone)
0588             return -ENOMEM;
0589 
0590         /* copy the temporary data */
0591         zone->bank = tmpzone.bank;
0592         zone->instr = tmpzone.instr;
0593         zone->v = tmpzone.v;
0594 
0595         /* look up the sample */
0596         zone->sample = set_sample(sf, &zone->v);
0597     }
0598 
0599     return 0;
0600 }
0601 
0602 
0603 /* initialize voice_info record */
0604 static void
0605 init_voice_info(struct soundfont_voice_info *avp)
0606 {
0607     memset(avp, 0, sizeof(*avp));
0608 
0609     avp->root = 60;
0610     avp->high = 127;
0611     avp->velhigh = 127;
0612     avp->fixkey = -1;
0613     avp->fixvel = -1;
0614     avp->fixpan = -1;
0615     avp->pan = -1;
0616     avp->amplitude = 127;
0617     avp->scaleTuning = 100;
0618 
0619     init_voice_parm(&avp->parm);
0620 }
0621 
0622 /* initialize voice_parm record:
0623  * Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0.
0624  * Vibrato and Tremolo effects are zero.
0625  * Cutoff is maximum.
0626  * Chorus and Reverb effects are zero.
0627  */
0628 static void
0629 init_voice_parm(struct soundfont_voice_parm *pp)
0630 {
0631     memset(pp, 0, sizeof(*pp));
0632 
0633     pp->moddelay = 0x8000;
0634     pp->modatkhld = 0x7f7f;
0635     pp->moddcysus = 0x7f7f;
0636     pp->modrelease = 0x807f;
0637 
0638     pp->voldelay = 0x8000;
0639     pp->volatkhld = 0x7f7f;
0640     pp->voldcysus = 0x7f7f;
0641     pp->volrelease = 0x807f;
0642 
0643     pp->lfo1delay = 0x8000;
0644     pp->lfo2delay = 0x8000;
0645 
0646     pp->cutoff = 0xff;
0647 }   
0648 
0649 /* search the specified sample */
0650 static struct snd_sf_sample *
0651 set_sample(struct snd_soundfont *sf, struct soundfont_voice_info *avp)
0652 {
0653     struct snd_sf_sample *sample;
0654 
0655     sample = find_sample(sf, avp->sample);
0656     if (sample == NULL)
0657         return NULL;
0658 
0659     /* add in the actual sample offsets:
0660      * The voice_info addresses define only the relative offset
0661      * from sample pointers.  Here we calculate the actual DRAM
0662      * offset from sample pointers.
0663      */
0664     avp->start += sample->v.start;
0665     avp->end += sample->v.end;
0666     avp->loopstart += sample->v.loopstart;
0667     avp->loopend += sample->v.loopend;
0668 
0669     /* copy mode flags */
0670     avp->sample_mode = sample->v.mode_flags;
0671 
0672     return sample;
0673 }
0674 
0675 /* find the sample pointer with the given id in the soundfont */
0676 static struct snd_sf_sample *
0677 find_sample(struct snd_soundfont *sf, int sample_id)
0678 {
0679     struct snd_sf_sample *p;
0680 
0681     if (sf == NULL)
0682         return NULL;
0683 
0684     for (p = sf->samples; p; p = p->next) {
0685         if (p->v.sample == sample_id)
0686             return p;
0687     }
0688     return NULL;
0689 }
0690 
0691 
0692 /*
0693  * Load sample information, this can include data to be loaded onto
0694  * the soundcard.  It can also just be a pointer into soundcard ROM.
0695  * If there is data it will be written to the soundcard via the callback
0696  * routine.
0697  */
0698 static int
0699 load_data(struct snd_sf_list *sflist, const void __user *data, long count)
0700 {
0701     struct snd_soundfont *sf;
0702     struct soundfont_sample_info sample_info;
0703     struct snd_sf_sample *sp;
0704     long off;
0705 
0706     /* patch must be opened */
0707     sf = sflist->currsf;
0708     if (!sf)
0709         return -EINVAL;
0710 
0711     if (is_special_type(sf->type))
0712         return -EINVAL;
0713 
0714     if (copy_from_user(&sample_info, data, sizeof(sample_info)))
0715         return -EFAULT;
0716 
0717     off = sizeof(sample_info);
0718 
0719     if (sample_info.size != (count-off)/2)
0720         return -EINVAL;
0721 
0722     /* Check for dup */
0723     if (find_sample(sf, sample_info.sample)) {
0724         /* if shared sample, skip this data */
0725         if (sf->type & SNDRV_SFNT_PAT_SHARED)
0726             return 0;
0727         return -EINVAL;
0728     }
0729 
0730     /* Allocate a new sample structure */
0731     sp = sf_sample_new(sflist, sf);
0732     if (!sp)
0733         return -ENOMEM;
0734 
0735     sp->v = sample_info;
0736     sp->v.sf_id = sf->id;
0737     sp->v.dummy = 0;
0738     sp->v.truesize = sp->v.size;
0739 
0740     /*
0741      * If there is wave data then load it.
0742      */
0743     if (sp->v.size > 0) {
0744         int  rc;
0745         rc = sflist->callback.sample_new
0746             (sflist->callback.private_data, sp, sflist->memhdr,
0747              data + off, count - off);
0748         if (rc < 0) {
0749             sf_sample_delete(sflist, sf, sp);
0750             return rc;
0751         }
0752         sflist->mem_used += sp->v.truesize;
0753     }
0754 
0755     return count;
0756 }
0757 
0758 
0759 /* log2_tbl[i] = log2(i+128) * 0x10000 */
0760 static const int log_tbl[129] = {
0761     0x70000, 0x702df, 0x705b9, 0x7088e, 0x70b5d, 0x70e26, 0x710eb, 0x713aa,
0762     0x71663, 0x71918, 0x71bc8, 0x71e72, 0x72118, 0x723b9, 0x72655, 0x728ed,
0763     0x72b80, 0x72e0e, 0x73098, 0x7331d, 0x7359e, 0x7381b, 0x73a93, 0x73d08,
0764     0x73f78, 0x741e4, 0x7444c, 0x746b0, 0x74910, 0x74b6c, 0x74dc4, 0x75019,
0765     0x75269, 0x754b6, 0x75700, 0x75946, 0x75b88, 0x75dc7, 0x76002, 0x7623a,
0766     0x7646e, 0x766a0, 0x768cd, 0x76af8, 0x76d1f, 0x76f43, 0x77164, 0x77382,
0767     0x7759d, 0x777b4, 0x779c9, 0x77bdb, 0x77dea, 0x77ff5, 0x781fe, 0x78404,
0768     0x78608, 0x78808, 0x78a06, 0x78c01, 0x78df9, 0x78fef, 0x791e2, 0x793d2,
0769     0x795c0, 0x797ab, 0x79993, 0x79b79, 0x79d5d, 0x79f3e, 0x7a11d, 0x7a2f9,
0770     0x7a4d3, 0x7a6ab, 0x7a880, 0x7aa53, 0x7ac24, 0x7adf2, 0x7afbe, 0x7b188,
0771     0x7b350, 0x7b515, 0x7b6d8, 0x7b899, 0x7ba58, 0x7bc15, 0x7bdd0, 0x7bf89,
0772     0x7c140, 0x7c2f5, 0x7c4a7, 0x7c658, 0x7c807, 0x7c9b3, 0x7cb5e, 0x7cd07,
0773     0x7ceae, 0x7d053, 0x7d1f7, 0x7d398, 0x7d538, 0x7d6d6, 0x7d872, 0x7da0c,
0774     0x7dba4, 0x7dd3b, 0x7ded0, 0x7e063, 0x7e1f4, 0x7e384, 0x7e512, 0x7e69f,
0775     0x7e829, 0x7e9b3, 0x7eb3a, 0x7ecc0, 0x7ee44, 0x7efc7, 0x7f148, 0x7f2c8,
0776     0x7f446, 0x7f5c2, 0x7f73d, 0x7f8b7, 0x7fa2f, 0x7fba5, 0x7fd1a, 0x7fe8d,
0777     0x80000,
0778 };
0779 
0780 /* convert from linear to log value
0781  *
0782  * conversion: value = log2(amount / base) * ratio
0783  *
0784  * argument:
0785  *   amount = linear value (unsigned, 32bit max)
0786  *   offset = base offset (:= log2(base) * 0x10000)
0787  *   ratio = division ratio
0788  *
0789  */
0790 int
0791 snd_sf_linear_to_log(unsigned int amount, int offset, int ratio)
0792 {
0793     int v;
0794     int s, low, bit;
0795     
0796     if (amount < 2)
0797         return 0;
0798     for (bit = 0; ! (amount & 0x80000000L); bit++)
0799         amount <<= 1;
0800     s = (amount >> 24) & 0x7f;
0801     low = (amount >> 16) & 0xff;
0802     /* linear approximation by lower 8 bit */
0803     v = (log_tbl[s + 1] * low + log_tbl[s] * (0x100 - low)) >> 8;
0804     v -= offset;
0805     v = (v * ratio) >> 16;
0806     v += (24 - bit) * ratio;
0807     return v;
0808 }
0809 
0810 EXPORT_SYMBOL(snd_sf_linear_to_log);
0811 
0812 
0813 #define OFFSET_MSEC     653117      /* base = 1000 */
0814 #define OFFSET_ABSCENT      851781      /* base = 8176 */
0815 #define OFFSET_SAMPLERATE   1011119     /* base = 44100 */
0816 
0817 #define ABSCENT_RATIO       1200
0818 #define TIMECENT_RATIO      1200
0819 #define SAMPLERATE_RATIO    4096
0820 
0821 /*
0822  * mHz to abscent
0823  * conversion: abscent = log2(MHz / 8176) * 1200
0824  */
0825 static int
0826 freq_to_note(int mhz)
0827 {
0828     return snd_sf_linear_to_log(mhz, OFFSET_ABSCENT, ABSCENT_RATIO);
0829 }
0830 
0831 /* convert Hz to AWE32 rate offset:
0832  * sample pitch offset for the specified sample rate
0833  * rate=44100 is no offset, each 4096 is 1 octave (twice).
0834  * eg, when rate is 22050, this offset becomes -4096.
0835  *
0836  * conversion: offset = log2(Hz / 44100) * 4096
0837  */
0838 static int
0839 calc_rate_offset(int hz)
0840 {
0841     return snd_sf_linear_to_log(hz, OFFSET_SAMPLERATE, SAMPLERATE_RATIO);
0842 }
0843 
0844 
0845 /* calculate GUS envelope time */
0846 static int
0847 calc_gus_envelope_time(int rate, int start, int end)
0848 {
0849     int r, p, t;
0850     r = (3 - ((rate >> 6) & 3)) * 3;
0851     p = rate & 0x3f;
0852     if (!p)
0853         p = 1;
0854     t = end - start;
0855     if (t < 0) t = -t;
0856     if (13 > r)
0857         t = t << (13 - r);
0858     else
0859         t = t >> (r - 13);
0860     return (t * 10) / (p * 441);
0861 }
0862 
0863 /* convert envelope time parameter to soundfont parameters */
0864 
0865 /* attack & decay/release time table (msec) */
0866 static const short attack_time_tbl[128] = {
0867 32767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816,
0868 707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377,
0869 361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188,
0870 180, 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94,
0871 90, 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47,
0872 45, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23,
0873 22, 21, 20, 19, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12,
0874 11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0,
0875 };
0876 
0877 static const short decay_time_tbl[128] = {
0878 32767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082,
0879 2828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507,
0880 1443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722,
0881 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361,
0882 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, 180,
0883 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, 90,
0884 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45,
0885 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 22,
0886 };
0887 
0888 /* delay time = 0x8000 - msec/92 */
0889 int
0890 snd_sf_calc_parm_hold(int msec)
0891 {
0892     int val = (0x7f * 92 - msec) / 92;
0893     if (val < 1) val = 1;
0894     if (val >= 126) val = 126;
0895     return val;
0896 }
0897 
0898 /* search an index for specified time from given time table */
0899 static int
0900 calc_parm_search(int msec, const short *table)
0901 {
0902     int left = 1, right = 127, mid;
0903     while (left < right) {
0904         mid = (left + right) / 2;
0905         if (msec < (int)table[mid])
0906             left = mid + 1;
0907         else
0908             right = mid;
0909     }
0910     return left;
0911 }
0912 
0913 /* attack time: search from time table */
0914 int
0915 snd_sf_calc_parm_attack(int msec)
0916 {
0917     return calc_parm_search(msec, attack_time_tbl);
0918 }
0919 
0920 /* decay/release time: search from time table */
0921 int
0922 snd_sf_calc_parm_decay(int msec)
0923 {
0924     return calc_parm_search(msec, decay_time_tbl);
0925 }
0926 
0927 int snd_sf_vol_table[128] = {
0928     255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49,
0929     47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32,
0930     31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22,
0931     22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16,
0932     15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10,
0933     10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6,
0934     6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3,
0935     2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,
0936 };
0937 
0938 
0939 #define calc_gus_sustain(val)  (0x7f - snd_sf_vol_table[(val)/2])
0940 #define calc_gus_attenuation(val)   snd_sf_vol_table[(val)/2]
0941 
0942 /* load GUS patch */
0943 static int
0944 load_guspatch(struct snd_sf_list *sflist, const char __user *data,
0945           long count, int client)
0946 {
0947     struct patch_info patch;
0948     struct snd_soundfont *sf;
0949     struct snd_sf_zone *zone;
0950     struct snd_sf_sample *smp;
0951     int note, sample_id;
0952     int rc;
0953 
0954     if (count < (long)sizeof(patch)) {
0955         snd_printk(KERN_ERR "patch record too small %ld\n", count);
0956         return -EINVAL;
0957     }
0958     if (copy_from_user(&patch, data, sizeof(patch)))
0959         return -EFAULT;
0960     
0961     count -= sizeof(patch);
0962     data += sizeof(patch);
0963 
0964     sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_GUS|SNDRV_SFNT_PAT_SHARED, NULL);
0965     if (sf == NULL)
0966         return -ENOMEM;
0967     smp = sf_sample_new(sflist, sf);
0968     if (!smp)
0969         return -ENOMEM;
0970     sample_id = sflist->sample_counter;
0971     smp->v.sample = sample_id;
0972     smp->v.start = 0;
0973     smp->v.end = patch.len;
0974     smp->v.loopstart = patch.loop_start;
0975     smp->v.loopend = patch.loop_end;
0976     smp->v.size = patch.len;
0977 
0978     /* set up mode flags */
0979     smp->v.mode_flags = 0;
0980     if (!(patch.mode & WAVE_16_BITS))
0981         smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_8BITS;
0982     if (patch.mode & WAVE_UNSIGNED)
0983         smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_UNSIGNED;
0984     smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_NO_BLANK;
0985     if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP|WAVE_LOOP_BACK)))
0986         smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_SINGLESHOT;
0987     if (patch.mode & WAVE_BIDIR_LOOP)
0988         smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_BIDIR_LOOP;
0989     if (patch.mode & WAVE_LOOP_BACK)
0990         smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_REVERSE_LOOP;
0991 
0992     if (patch.mode & WAVE_16_BITS) {
0993         /* convert to word offsets */
0994         smp->v.size /= 2;
0995         smp->v.end /= 2;
0996         smp->v.loopstart /= 2;
0997         smp->v.loopend /= 2;
0998     }
0999     /*smp->v.loopend++;*/
1000 
1001     smp->v.dummy = 0;
1002     smp->v.truesize = 0;
1003     smp->v.sf_id = sf->id;
1004 
1005     /* set up voice info */
1006     zone = sf_zone_new(sflist, sf);
1007     if (!zone) {
1008         sf_sample_delete(sflist, sf, smp);
1009         return -ENOMEM;
1010     }
1011 
1012     /*
1013      * load wave data
1014      */
1015     if (sflist->callback.sample_new) {
1016         rc = sflist->callback.sample_new
1017             (sflist->callback.private_data, smp, sflist->memhdr,
1018              data, count);
1019         if (rc < 0) {
1020             sf_sample_delete(sflist, sf, smp);
1021             kfree(zone);
1022             return rc;
1023         }
1024         /* memory offset is updated after */
1025     }
1026 
1027     /* update the memory offset here */
1028     sflist->mem_used += smp->v.truesize;
1029 
1030     zone->v.sample = sample_id; /* the last sample */
1031     zone->v.rate_offset = calc_rate_offset(patch.base_freq);
1032     note = freq_to_note(patch.base_note);
1033     zone->v.root = note / 100;
1034     zone->v.tune = -(note % 100);
1035     zone->v.low = (freq_to_note(patch.low_note) + 99) / 100;
1036     zone->v.high = freq_to_note(patch.high_note) / 100;
1037     /* panning position; -128 - 127 => 0-127 */
1038     zone->v.pan = (patch.panning + 128) / 2;
1039 #if 0
1040     snd_printk(KERN_DEBUG
1041            "gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n",
1042            (int)patch.base_freq, zone->v.rate_offset,
1043            zone->v.root, zone->v.tune, zone->v.low, zone->v.high);
1044 #endif
1045 
1046     /* detuning is ignored */
1047     /* 6points volume envelope */
1048     if (patch.mode & WAVE_ENVELOPES) {
1049         int attack, hold, decay, release;
1050         attack = calc_gus_envelope_time
1051             (patch.env_rate[0], 0, patch.env_offset[0]);
1052         hold = calc_gus_envelope_time
1053             (patch.env_rate[1], patch.env_offset[0],
1054              patch.env_offset[1]);
1055         decay = calc_gus_envelope_time
1056             (patch.env_rate[2], patch.env_offset[1],
1057              patch.env_offset[2]);
1058         release = calc_gus_envelope_time
1059             (patch.env_rate[3], patch.env_offset[1],
1060              patch.env_offset[4]);
1061         release += calc_gus_envelope_time
1062             (patch.env_rate[4], patch.env_offset[3],
1063              patch.env_offset[4]);
1064         release += calc_gus_envelope_time
1065             (patch.env_rate[5], patch.env_offset[4],
1066              patch.env_offset[5]);
1067         zone->v.parm.volatkhld = 
1068             (snd_sf_calc_parm_hold(hold) << 8) |
1069             snd_sf_calc_parm_attack(attack);
1070         zone->v.parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) |
1071             snd_sf_calc_parm_decay(decay);
1072         zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release);
1073         zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]);
1074 #if 0
1075         snd_printk(KERN_DEBUG
1076                "gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n",
1077                zone->v.parm.volatkhld,
1078                zone->v.parm.voldcysus,
1079                zone->v.parm.volrelease,
1080                zone->v.attenuation);
1081 #endif
1082     }
1083 
1084     /* fast release */
1085     if (patch.mode & WAVE_FAST_RELEASE) {
1086         zone->v.parm.volrelease = 0x807f;
1087     }
1088 
1089     /* tremolo effect */
1090     if (patch.mode & WAVE_TREMOLO) {
1091         int rate = (patch.tremolo_rate * 1000 / 38) / 42;
1092         zone->v.parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate;
1093     }
1094     /* vibrato effect */
1095     if (patch.mode & WAVE_VIBRATO) {
1096         int rate = (patch.vibrato_rate * 1000 / 38) / 42;
1097         zone->v.parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate;
1098     }
1099     
1100     /* scale_freq, scale_factor, volume, and fractions not implemented */
1101 
1102     if (!(smp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT))
1103         zone->v.mode = SNDRV_SFNT_MODE_LOOPING;
1104     else
1105         zone->v.mode = 0;
1106 
1107     /* append to the tail of the list */
1108     /*zone->bank = ctrls[AWE_MD_GUS_BANK];*/
1109     zone->bank = 0;
1110     zone->instr = patch.instr_no;
1111     zone->mapped = 0;
1112     zone->v.sf_id = sf->id;
1113 
1114     zone->sample = set_sample(sf, &zone->v);
1115 
1116     /* rebuild preset now */
1117     add_preset(sflist, zone);
1118 
1119     return 0;
1120 }
1121 
1122 /* load GUS patch */
1123 int
1124 snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data,
1125                 long count, int client)
1126 {
1127     int rc;
1128     lock_preset(sflist);
1129     rc = load_guspatch(sflist, data, count, client);
1130     unlock_preset(sflist);
1131     return rc;
1132 }
1133 
1134 
1135 /*
1136  * Rebuild the preset table.  This is like a hash table in that it allows
1137  * quick access to the zone information.  For each preset there are zone
1138  * structures linked by next_instr and by next_zone.  Former is the whole
1139  * link for this preset, and latter is the link for zone (i.e. instrument/
1140  * bank/key combination).
1141  */
1142 static void
1143 rebuild_presets(struct snd_sf_list *sflist)
1144 {
1145     struct snd_soundfont *sf;
1146     struct snd_sf_zone *cur;
1147 
1148     /* clear preset table */
1149     memset(sflist->presets, 0, sizeof(sflist->presets));
1150 
1151     /* search all fonts and insert each font */
1152     for (sf = sflist->fonts; sf; sf = sf->next) {
1153         for (cur = sf->zones; cur; cur = cur->next) {
1154             if (! cur->mapped && cur->sample == NULL) {
1155                 /* try again to search the corresponding sample */
1156                 cur->sample = set_sample(sf, &cur->v);
1157                 if (cur->sample == NULL)
1158                     continue;
1159             }
1160 
1161             add_preset(sflist, cur);
1162         }
1163     }
1164 }
1165 
1166 
1167 /*
1168  * add the given zone to preset table
1169  */
1170 static void
1171 add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur)
1172 {
1173     struct snd_sf_zone *zone;
1174     int index;
1175 
1176     zone = search_first_zone(sflist, cur->bank, cur->instr, cur->v.low);
1177     if (zone && zone->v.sf_id != cur->v.sf_id) {
1178         /* different instrument was already defined */
1179         struct snd_sf_zone *p;
1180         /* compare the allocated time */
1181         for (p = zone; p; p = p->next_zone) {
1182             if (p->counter > cur->counter)
1183                 /* the current is older.. skipped */
1184                 return;
1185         }
1186         /* remove old zones */
1187         delete_preset(sflist, zone);
1188         zone = NULL; /* do not forget to clear this! */
1189     }
1190 
1191     /* prepend this zone */
1192     index = get_index(cur->bank, cur->instr, cur->v.low);
1193     if (index < 0)
1194         return;
1195     cur->next_zone = zone; /* zone link */
1196     cur->next_instr = sflist->presets[index]; /* preset table link */
1197     sflist->presets[index] = cur;
1198 }
1199 
1200 /*
1201  * delete the given zones from preset_table
1202  */
1203 static void
1204 delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp)
1205 {
1206     int index;
1207     struct snd_sf_zone *p;
1208 
1209     index = get_index(zp->bank, zp->instr, zp->v.low);
1210     if (index < 0)
1211         return;
1212     for (p = sflist->presets[index]; p; p = p->next_instr) {
1213         while (p->next_instr == zp) {
1214             p->next_instr = zp->next_instr;
1215             zp = zp->next_zone;
1216             if (zp == NULL)
1217                 return;
1218         }
1219     }
1220 }
1221 
1222 
1223 /*
1224  * Search matching zones from preset table.
1225  * The note can be rewritten by preset mapping (alias).
1226  * The found zones are stored on 'table' array.  max_layers defines
1227  * the maximum number of elements in this array.
1228  * This function returns the number of found zones.  0 if not found.
1229  */
1230 int
1231 snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel,
1232               int preset, int bank,
1233               int def_preset, int def_bank,
1234               struct snd_sf_zone **table, int max_layers)
1235 {
1236     int nvoices;
1237     unsigned long flags;
1238 
1239     /* this function is supposed to be called atomically,
1240      * so we check the lock.  if it's busy, just returns 0 to
1241      * tell the caller the busy state
1242      */
1243     spin_lock_irqsave(&sflist->lock, flags);
1244     if (sflist->presets_locked) {
1245         spin_unlock_irqrestore(&sflist->lock, flags);
1246         return 0;
1247     }
1248     nvoices = search_zones(sflist, notep, vel, preset, bank,
1249                    table, max_layers, 0);
1250     if (! nvoices) {
1251         if (preset != def_preset || bank != def_bank)
1252             nvoices = search_zones(sflist, notep, vel,
1253                            def_preset, def_bank,
1254                            table, max_layers, 0);
1255     }
1256     spin_unlock_irqrestore(&sflist->lock, flags);
1257     return nvoices;
1258 }
1259 
1260 
1261 /*
1262  * search the first matching zone
1263  */
1264 static struct snd_sf_zone *
1265 search_first_zone(struct snd_sf_list *sflist, int bank, int preset, int key)
1266 {
1267     int index;
1268     struct snd_sf_zone *zp;
1269 
1270     index = get_index(bank, preset, key);
1271     if (index < 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     sflist = kzalloc(sizeof(*sflist), GFP_KERNEL);
1401     if (!sflist)
1402         return NULL;
1403 
1404     mutex_init(&sflist->presets_mutex);
1405     spin_lock_init(&sflist->lock);
1406     sflist->memhdr = hdr;
1407 
1408     if (callback)
1409         sflist->callback = *callback;
1410 
1411     snd_sf_init(sflist);
1412     return sflist;
1413 }
1414 
1415 
1416 /*
1417  * Free everything allocated off the sflist structure.
1418  */
1419 void
1420 snd_sf_free(struct snd_sf_list *sflist)
1421 {
1422     if (sflist == NULL)
1423         return;
1424     
1425     lock_preset(sflist);
1426     if (sflist->callback.sample_reset)
1427         sflist->callback.sample_reset(sflist->callback.private_data);
1428     snd_sf_clear(sflist);
1429     unlock_preset(sflist);
1430 
1431     kfree(sflist);
1432 }
1433 
1434 /*
1435  * Remove all samples
1436  * The soundcard should be silent before calling this function.
1437  */
1438 int
1439 snd_soundfont_remove_samples(struct snd_sf_list *sflist)
1440 {
1441     lock_preset(sflist);
1442     if (sflist->callback.sample_reset)
1443         sflist->callback.sample_reset(sflist->callback.private_data);
1444     snd_sf_clear(sflist);
1445     unlock_preset(sflist);
1446 
1447     return 0;
1448 }
1449 
1450 /*
1451  * Remove unlocked samples.
1452  * The soundcard should be silent before calling this function.
1453  */
1454 int
1455 snd_soundfont_remove_unlocked(struct snd_sf_list *sflist)
1456 {
1457     struct snd_soundfont *sf;
1458     struct snd_sf_zone *zp, *nextzp;
1459     struct snd_sf_sample *sp, *nextsp;
1460 
1461     lock_preset(sflist);
1462 
1463     if (sflist->callback.sample_reset)
1464         sflist->callback.sample_reset(sflist->callback.private_data);
1465 
1466     /* to be sure */
1467     memset(sflist->presets, 0, sizeof(sflist->presets));
1468 
1469     for (sf = sflist->fonts; sf; sf = sf->next) {
1470         for (zp = sf->zones; zp; zp = nextzp) {
1471             if (zp->counter < sflist->zone_locked)
1472                 break;
1473             nextzp = zp->next;
1474             sf->zones = nextzp;
1475             kfree(zp);
1476         }
1477 
1478         for (sp = sf->samples; sp; sp = nextsp) {
1479             if (sp->counter < sflist->sample_locked)
1480                 break;
1481             nextsp = sp->next;
1482             sf->samples = nextsp;
1483             sflist->mem_used -= sp->v.truesize;
1484             if (sflist->callback.sample_free)
1485                 sflist->callback.sample_free(sflist->callback.private_data,
1486                                  sp, sflist->memhdr);
1487             kfree(sp);
1488         }
1489     }
1490 
1491     sflist->zone_counter = sflist->zone_locked;
1492     sflist->sample_counter = sflist->sample_locked;
1493 
1494     rebuild_presets(sflist);
1495 
1496     unlock_preset(sflist);
1497     return 0;
1498 }