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