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