0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
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
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
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
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
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
0109
0110
0111
0112
0113
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
0149 lock_preset(sflist);
0150 rc = open_patch(sflist, data, count, client);
0151 unlock_preset(sflist);
0152 return rc;
0153 }
0154
0155
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
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
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
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
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
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
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
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
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
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
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
0320 static int
0321 probe_data(struct snd_sf_list *sflist, int sample_id)
0322 {
0323
0324 if (sflist->currsf) {
0325
0326 if (find_sample(sflist->currsf, sample_id))
0327 return 0;
0328 }
0329 return -EINVAL;
0330 }
0331
0332
0333
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
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
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
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
0398
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
0405 if (sp == sf->samples) {
0406 sf->samples = sp->next;
0407 kfree(sp);
0408 }
0409 }
0410
0411
0412
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
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
0443
0444 if (prevp) {
0445 prevp->next = zp->next;
0446 zp->next = sf->zones;
0447 sf->zones = zp;
0448 }
0449
0450 set_zone_counter(sflist, sf, zp);
0451 return 0;
0452 }
0453 }
0454
0455
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
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
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
0509
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
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
0553
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
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
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
0586 zone = sf_zone_new(sflist, sf);
0587 if (!zone)
0588 return -ENOMEM;
0589
0590
0591 zone->bank = tmpzone.bank;
0592 zone->instr = tmpzone.instr;
0593 zone->v = tmpzone.v;
0594
0595
0596 zone->sample = set_sample(sf, &zone->v);
0597 }
0598
0599 return 0;
0600 }
0601
0602
0603
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
0623
0624
0625
0626
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
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
0660
0661
0662
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
0670 avp->sample_mode = sample->v.mode_flags;
0671
0672 return sample;
0673 }
0674
0675
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
0694
0695
0696
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
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
0723 if (find_sample(sf, sample_info.sample)) {
0724
0725 if (sf->type & SNDRV_SFNT_PAT_SHARED)
0726 return 0;
0727 return -EINVAL;
0728 }
0729
0730
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
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
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
0781
0782
0783
0784
0785
0786
0787
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
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
0814 #define OFFSET_ABSCENT 851781
0815 #define OFFSET_SAMPLERATE 1011119
0816
0817 #define ABSCENT_RATIO 1200
0818 #define TIMECENT_RATIO 1200
0819 #define SAMPLERATE_RATIO 4096
0820
0821
0822
0823
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
0832
0833
0834
0835
0836
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
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
0864
0865
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
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
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
0914 int
0915 snd_sf_calc_parm_attack(int msec)
0916 {
0917 return calc_parm_search(msec, attack_time_tbl);
0918 }
0919
0920
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
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
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
0994 smp->v.size /= 2;
0995 smp->v.end /= 2;
0996 smp->v.loopstart /= 2;
0997 smp->v.loopend /= 2;
0998 }
0999
1000
1001 smp->v.dummy = 0;
1002 smp->v.truesize = 0;
1003 smp->v.sf_id = sf->id;
1004
1005
1006 zone = sf_zone_new(sflist, sf);
1007 if (!zone) {
1008 sf_sample_delete(sflist, sf, smp);
1009 return -ENOMEM;
1010 }
1011
1012
1013
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
1025 }
1026
1027
1028 sflist->mem_used += smp->v.truesize;
1029
1030 zone->v.sample = sample_id;
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
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
1047
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
1085 if (patch.mode & WAVE_FAST_RELEASE) {
1086 zone->v.parm.volrelease = 0x807f;
1087 }
1088
1089
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
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
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
1108
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
1117 add_preset(sflist, zone);
1118
1119 return 0;
1120 }
1121
1122
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
1137
1138
1139
1140
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
1149 memset(sflist->presets, 0, sizeof(sflist->presets));
1150
1151
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
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
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
1179 struct snd_sf_zone *p;
1180
1181 for (p = zone; p; p = p->next_zone) {
1182 if (p->counter > cur->counter)
1183
1184 return;
1185 }
1186
1187 delete_preset(sflist, zone);
1188 zone = NULL;
1189 }
1190
1191
1192 index = get_index(cur->bank, cur->instr, cur->v.low);
1193 if (index < 0)
1194 return;
1195 cur->next_zone = zone;
1196 cur->next_instr = sflist->presets[index];
1197 sflist->presets[index] = cur;
1198 }
1199
1200
1201
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
1225
1226
1227
1228
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
1240
1241
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
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
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
1299 int key = zp->v.fixkey;
1300 preset = zp->v.start;
1301 bank = zp->v.end;
1302
1303 if (level > 5)
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
1325
1326
1327
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
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
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
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
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
1436
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
1452
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
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 }