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