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