src/fluid_ramsfont.c

00001 /* FluidSynth - A Software Synthesizer
00002  *
00003  * Copyright (C) 2003  Peter Hanappe and others.
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public License
00007  * as published by the Free Software Foundation; either version 2 of
00008  * the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public
00016  * License along with this library; if not, write to the Free
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018  * 02111-1307, USA
00019  */
00020 
00021 #include "fluid_ramsfont.h"
00022 #include "fluid_sys.h"
00023 #include "fluid_synth.h"
00024 
00025 /* thenumber of samples before the start and after the end */
00026 #define SAMPLE_LOOP_MARGIN 8
00027 
00028 /* Prototypes */
00029 int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample, int lokey, int hikey);
00030 int fluid_rampreset_izone_set_gen(fluid_rampreset_t* preset, fluid_sample_t* sample, int gen_type, float value);
00031 int fluid_rampreset_izone_set_loop(fluid_rampreset_t* preset, fluid_sample_t* sample, int on, float loopstart, float loopend);
00032 int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* sample);
00033 void fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val);
00034 
00035 /*
00036  * fluid_ramsfont_create_sfont
00037  */
00038 fluid_sfont_t*
00039 fluid_ramsfont_create_sfont()
00040 {
00041         fluid_sfont_t* sfont;
00042         fluid_ramsfont_t* ramsfont;
00043 
00044         ramsfont = new_fluid_ramsfont();
00045         if (ramsfont == NULL) {
00046     return NULL;
00047   }
00048 
00049   sfont = FLUID_NEW(fluid_sfont_t);
00050   if (sfont == NULL) {
00051     FLUID_LOG(FLUID_ERR, "Out of memory");
00052     return NULL;
00053   }
00054 
00055   sfont->data = ramsfont;
00056   sfont->free = fluid_ramsfont_sfont_delete;
00057   sfont->get_name = fluid_ramsfont_sfont_get_name;
00058   sfont->get_preset = fluid_ramsfont_sfont_get_preset;
00059   sfont->iteration_start = fluid_ramsfont_sfont_iteration_start;
00060   sfont->iteration_next = fluid_ramsfont_sfont_iteration_next;
00061 
00062   return sfont;
00063 
00064 }
00065 
00066 /***************************************************************
00067  *
00068  *                           PUBLIC INTERFACE
00069  */
00070 
00071 int fluid_ramsfont_sfont_delete(fluid_sfont_t* sfont)
00072 {
00073         if (delete_fluid_ramsfont(sfont->data) != 0)
00074                 return -1;
00075         FLUID_FREE(sfont);
00076         return 0;
00077 }
00078 
00079 char* fluid_ramsfont_sfont_get_name(fluid_sfont_t* sfont)
00080 {
00081   return fluid_ramsfont_get_name((fluid_ramsfont_t*) sfont->data);
00082 }
00083 
00084 fluid_preset_t* fluid_ramsfont_sfont_get_preset(fluid_sfont_t* sfont, unsigned int bank, unsigned int prenum)
00085 {
00086   fluid_preset_t* preset;
00087   fluid_rampreset_t* rampreset;
00088 
00089   rampreset = fluid_ramsfont_get_preset((fluid_ramsfont_t*) sfont->data, bank, prenum);
00090 
00091   if (rampreset == NULL) {
00092     return NULL;
00093   }
00094 
00095   preset = FLUID_NEW(fluid_preset_t);
00096   if (preset == NULL) {
00097     FLUID_LOG(FLUID_ERR, "Out of memory");
00098     return NULL;
00099   }
00100 
00101   preset->sfont = sfont;
00102   preset->data = rampreset;
00103   preset->free = fluid_rampreset_preset_delete;
00104   preset->get_name = fluid_rampreset_preset_get_name;
00105   preset->get_banknum = fluid_rampreset_preset_get_banknum;
00106   preset->get_num = fluid_rampreset_preset_get_num;
00107   preset->noteon = fluid_rampreset_preset_noteon;
00108   preset->notify = NULL;
00109 
00110   return preset;
00111 }
00112 
00113 void fluid_ramsfont_sfont_iteration_start(fluid_sfont_t* sfont)
00114 {
00115   fluid_ramsfont_iteration_start((fluid_ramsfont_t*) sfont->data);
00116 }
00117 
00118 int fluid_ramsfont_sfont_iteration_next(fluid_sfont_t* sfont, fluid_preset_t* preset)
00119 {
00120   preset->free = fluid_rampreset_preset_delete;
00121   preset->get_name = fluid_rampreset_preset_get_name;
00122   preset->get_banknum = fluid_rampreset_preset_get_banknum;
00123   preset->get_num = fluid_rampreset_preset_get_num;
00124   preset->noteon = fluid_rampreset_preset_noteon;
00125   preset->notify = NULL;
00126 
00127   return fluid_ramsfont_iteration_next((fluid_ramsfont_t*) sfont->data, preset);
00128 }
00129 
00130 int fluid_rampreset_preset_delete(fluid_preset_t* preset)
00131 {
00132   FLUID_FREE(preset);
00133 
00134 /* TODO: free modulators */
00135 
00136   return 0;
00137 }
00138 
00139 char* fluid_rampreset_preset_get_name(fluid_preset_t* preset)
00140 {
00141   return fluid_rampreset_get_name((fluid_rampreset_t*) preset->data);
00142 }
00143 
00144 int fluid_rampreset_preset_get_banknum(fluid_preset_t* preset)
00145 {
00146   return fluid_rampreset_get_banknum((fluid_rampreset_t*) preset->data);
00147 }
00148 
00149 int fluid_rampreset_preset_get_num(fluid_preset_t* preset)
00150 {
00151   return fluid_rampreset_get_num((fluid_rampreset_t*) preset->data);
00152 }
00153 
00154 int fluid_rampreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
00155 {
00156   return fluid_rampreset_noteon((fluid_rampreset_t*) preset->data, synth, chan, key, vel);
00157 }
00158 
00159 
00160 
00161 
00162 /***************************************************************
00163  *
00164  *                           SFONT
00165  */
00166 
00167 /*
00168  * new_fluid_ramsfont
00169  */
00170 fluid_ramsfont_t* new_fluid_ramsfont()
00171 {
00172   fluid_ramsfont_t* sfont;
00173 
00174   sfont = FLUID_NEW(fluid_ramsfont_t);
00175   if (sfont == NULL) {
00176     FLUID_LOG(FLUID_ERR, "Out of memory");
00177     return NULL;
00178   }
00179 
00180   sfont->name[0] = 0;
00181   sfont->sample = NULL;
00182   sfont->preset = NULL;
00183 
00184   return sfont;
00185 }
00186 
00187 /*
00188  * delete_fluid_ramsfont
00189  */
00190 int delete_fluid_ramsfont(fluid_ramsfont_t* sfont)
00191 {
00192   fluid_list_t *list;
00193   fluid_rampreset_t* preset;
00194 
00195   /* Check that no samples are currently used */
00196   for (list = sfont->sample; list; list = fluid_list_next(list)) {
00197     fluid_sample_t* sam = (fluid_sample_t*) fluid_list_get(list);
00198     if (fluid_sample_refcount(sam) != 0) {
00199       return -1;
00200     }
00201   }
00202 
00203   for (list = sfont->sample; list; list = fluid_list_next(list)) {
00204         /* in ram soundfonts, the samples hold their data : so we should free it ourselves */
00205         fluid_sample_t* sam = (fluid_sample_t*)fluid_list_get(list);
00206     delete_fluid_ramsample(sam);
00207   }
00208 
00209   if (sfont->sample) {
00210     delete_fluid_list(sfont->sample);
00211   }
00212 
00213   preset = sfont->preset;
00214   while (preset != NULL) {
00215     sfont->preset = preset->next;
00216     delete_fluid_rampreset(preset);
00217     preset = sfont->preset;
00218   }
00219 
00220   FLUID_FREE(sfont);
00221   return FLUID_OK;
00222 }
00223 
00224 /*
00225  * fluid_ramsfont_get_name
00226  */
00227 char* fluid_ramsfont_get_name(fluid_ramsfont_t* sfont)
00228 {
00229   return sfont->name;
00230 }
00231 
00232 /*
00233  * fluid_ramsfont_set_name
00234  */
00235 int
00236 fluid_ramsfont_set_name(fluid_ramsfont_t* sfont, char * name)
00237 {
00238   FLUID_MEMCPY(sfont->name, name, 20);
00239   return FLUID_OK;
00240 }
00241 
00242 
00243 /* fluid_ramsfont_add_preset
00244  *
00245  * Add a preset to the SoundFont
00246  */
00247 int fluid_ramsfont_add_preset(fluid_ramsfont_t* sfont, fluid_rampreset_t* preset)
00248 {
00249   fluid_rampreset_t *cur, *prev;
00250   if (sfont->preset == NULL) {
00251     preset->next = NULL;
00252     sfont->preset = preset;
00253   } else {
00254     /* sort them as we go along. very basic sorting trick. */
00255     cur = sfont->preset;
00256     prev = NULL;
00257     while (cur != NULL) {
00258       if ((preset->bank < cur->bank)
00259           || ((preset->bank == cur->bank) && (preset->num < cur->num))) {
00260         if (prev == NULL) {
00261           preset->next = cur;
00262           sfont->preset = preset;
00263         } else {
00264           preset->next = cur;
00265           prev->next = preset;
00266         }
00267         return FLUID_OK;
00268       }
00269       prev = cur;
00270       cur = cur->next;
00271     }
00272     preset->next = NULL;
00273     prev->next = preset;
00274   }
00275   return FLUID_OK;
00276 }
00277 
00278 /*
00279  * fluid_ramsfont_add_ramsample
00280  */
00281 int fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont,
00282                                 unsigned int bank, unsigned int num, fluid_sample_t* sample,
00283                                 int lokey, int hikey)
00284 {
00285         /*- find or create a preset
00286                 - add it the sample using the fluid_rampreset_add_sample fucntion
00287                 - add the sample to the list of samples
00288         */
00289         int err;
00290 
00291         fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
00292         if (preset == NULL) {
00293                 // Create it
00294                 preset = new_fluid_rampreset(sfont);
00295                 if (preset == NULL) {
00296                         return FLUID_FAILED;
00297                 }
00298 
00299                 preset->bank = bank;
00300                 preset->num = num;
00301 
00302                 err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
00303                 if (err != FLUID_OK) {
00304                         return FLUID_FAILED;
00305                 }
00306 
00307                 // sort the preset
00308                 fluid_ramsfont_add_preset(sfont, preset);
00309 
00310         } else {
00311 
00312                 // just add it
00313                 err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
00314                 if (err != FLUID_OK) {
00315                         return FLUID_FAILED;
00316                 }
00317         }
00318 
00319   sfont->sample = fluid_list_append(sfont->sample, sample);
00320   return FLUID_OK;
00321 }
00322 
00323 int fluid_ramsfont_remove_izone(fluid_ramsfont_t* sfont,
00324          unsigned int bank, unsigned int num, fluid_sample_t* sample) {
00325         int err;
00326         fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
00327         if (preset == NULL) {
00328                 return FLUID_FAILED;
00329         }
00330 
00331         // Fixed a crash bug : remove the sample from the sfont list after
00332         // removing the izone (aschmitt august 2005)
00333         err = fluid_rampreset_remove_izone(preset, sample);
00334         if (err != FLUID_OK)
00335                 return err;
00336 
00337         // now we must remove the sample from sfont->sample
00338         sfont->sample = fluid_list_remove(sfont->sample, sample);
00339 
00340         return FLUID_OK;
00341 }
00342 
00343 
00344 /* Note for version 2.0 : missing API fluid_ramsfont_izone_get_gen - Antoine Schmitt May 2003 */
00345 int fluid_ramsfont_izone_set_gen(fluid_ramsfont_t* sfont,
00346                                 unsigned int bank, unsigned int num, fluid_sample_t* sample,
00347                                 int gen_type, float value) {
00348 
00349         fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
00350         if (preset == NULL) {
00351                         return FLUID_FAILED;
00352         }
00353 
00354         return fluid_rampreset_izone_set_gen(preset, sample, gen_type, value);
00355 }
00356 
00357 /* Note for version 2.0 : missing API fluid_ramsfont_izone_get_loop - Antoine Schmitt May 2003 */
00358 int fluid_ramsfont_izone_set_loop(fluid_ramsfont_t* sfont,
00359                                 unsigned int bank, unsigned int num, fluid_sample_t* sample,
00360                                 int on, float loopstart, float loopend) {
00361         fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
00362         if (preset == NULL) {
00363                         return FLUID_FAILED;
00364         }
00365 
00366         return fluid_rampreset_izone_set_loop(preset, sample, on, loopstart, loopend);
00367 }
00368 
00369 /*
00370  * fluid_ramsfont_get_preset
00371  */
00372 fluid_rampreset_t* fluid_ramsfont_get_preset(fluid_ramsfont_t* sfont, unsigned int bank, unsigned int num)
00373 {
00374   fluid_rampreset_t* preset = sfont->preset;
00375   while (preset != NULL) {
00376     if ((preset->bank == bank) && ((preset->num == num))) {
00377       return preset;
00378     }
00379     preset = preset->next;
00380   }
00381   return NULL;
00382 }
00383 
00384 /*
00385  * fluid_ramsfont_iteration_start
00386  */
00387 void fluid_ramsfont_iteration_start(fluid_ramsfont_t* sfont)
00388 {
00389   sfont->iter_cur = sfont->preset;
00390 }
00391 
00392 /*
00393  * fluid_ramsfont_iteration_next
00394  */
00395 int fluid_ramsfont_iteration_next(fluid_ramsfont_t* sfont, fluid_preset_t* preset)
00396 {
00397   if (sfont->iter_cur == NULL) {
00398     return 0;
00399   }
00400 
00401   preset->data = (void*) sfont->iter_cur;
00402   sfont->iter_cur = fluid_rampreset_next(sfont->iter_cur);
00403   return 1;
00404 }
00405 
00406 /***************************************************************
00407  *
00408  *                           PRESET
00409  */
00410 
00411 typedef struct _fluid_rampreset_voice_t fluid_rampreset_voice_t;
00412 struct _fluid_rampreset_voice_t {
00413         fluid_voice_t *voice;
00414         unsigned int voiceID;
00415 };
00416 
00417 /*
00418  * new_fluid_rampreset
00419  */
00420 fluid_rampreset_t*
00421 new_fluid_rampreset(fluid_ramsfont_t* sfont)
00422 {
00423   fluid_rampreset_t* preset = FLUID_NEW(fluid_rampreset_t);
00424   if (preset == NULL) {
00425     FLUID_LOG(FLUID_ERR, "Out of memory");
00426     return NULL;
00427   }
00428   preset->next = NULL;
00429   preset->sfont = sfont;
00430   preset->name[0] = 0;
00431   preset->bank = 0;
00432   preset->num = 0;
00433   preset->global_zone = NULL;
00434   preset->zone = NULL;
00435   preset->presetvoices = NULL;
00436   return preset;
00437 }
00438 
00439 /*
00440  * delete_fluid_rampreset
00441  */
00442 int
00443 delete_fluid_rampreset(fluid_rampreset_t* preset)
00444 {
00445   int err = FLUID_OK;
00446   fluid_preset_zone_t* zone;
00447   fluid_rampreset_voice_t *data;
00448 
00449   if (preset->global_zone != NULL) {
00450     if (delete_fluid_preset_zone(preset->global_zone) != FLUID_OK) {
00451       err = FLUID_FAILED;
00452     }
00453     preset->global_zone = NULL;
00454   }
00455   zone = preset->zone;
00456   while (zone != NULL) {
00457     preset->zone = zone->next;
00458     if (delete_fluid_preset_zone(zone) != FLUID_OK) {
00459       err = FLUID_FAILED;
00460     }
00461     zone = preset->zone;
00462   }
00463 
00464   if (preset->presetvoices != NULL) {
00465         fluid_list_t *tmp = preset->presetvoices, *next;
00466         while (tmp) {
00467                 data = (fluid_rampreset_voice_t *)(tmp->data);
00468                 FLUID_FREE(data);
00469 
00470                 next = tmp->next;
00471                 FLUID_FREE(tmp);
00472                 tmp = next;
00473         }
00474   }
00475   preset->presetvoices = NULL;
00476 
00477   FLUID_FREE(preset);
00478   return err;
00479 }
00480 
00481 int
00482 fluid_rampreset_get_banknum(fluid_rampreset_t* preset)
00483 {
00484   return preset->bank;
00485 }
00486 
00487 int
00488 fluid_rampreset_get_num(fluid_rampreset_t* preset)
00489 {
00490   return preset->num;
00491 }
00492 
00493 char*
00494 fluid_rampreset_get_name(fluid_rampreset_t* preset)
00495 {
00496   return preset->name;
00497 }
00498 
00499 /*
00500  * fluid_rampreset_next
00501  */
00502 fluid_rampreset_t*
00503 fluid_rampreset_next(fluid_rampreset_t* preset)
00504 {
00505   return preset->next;
00506 }
00507 
00508 
00509 /*
00510  * fluid_rampreset_add_zone
00511  */
00512 int
00513 fluid_rampreset_add_zone(fluid_rampreset_t* preset, fluid_preset_zone_t* zone)
00514 {
00515   if (preset->zone == NULL) {
00516     zone->next = NULL;
00517     preset->zone = zone;
00518   } else {
00519     zone->next = preset->zone;
00520     preset->zone = zone;
00521   }
00522   return FLUID_OK;
00523 }
00524 
00525 
00526 /*
00527  * fluid_rampreset_add_sample
00528  */
00529 int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample, int lokey, int hikey)
00530 {
00531         /* create a new instrument zone, with the given sample */
00532 
00533         /* one preset zone */
00534         if (preset->zone == NULL) {
00535                 fluid_preset_zone_t* zone;
00536                 zone = new_fluid_preset_zone("");
00537                 if (zone == NULL) {
00538                         return FLUID_FAILED;
00539                 }
00540 
00541                 /* its instrument */
00542                 zone->inst = (fluid_inst_t*) new_fluid_inst();
00543     if (zone->inst == NULL) {
00544       delete_fluid_preset_zone(zone);
00545       return FLUID_FAILED;
00546     }
00547 
00548                 fluid_rampreset_add_zone(preset, zone);
00549         }
00550 
00551         /* add an instrument zone for each sample */
00552         {
00553                 fluid_inst_t* inst = fluid_preset_zone_get_inst(preset->zone);
00554                 fluid_inst_zone_t* izone = new_fluid_inst_zone("");
00555                 if (izone == NULL) {
00556                         return FLUID_FAILED;
00557                 }
00558 
00559                 if (fluid_inst_add_zone(inst, izone) != FLUID_OK) {
00560                         delete_fluid_inst_zone(izone);
00561                         return FLUID_FAILED;
00562                 }
00563 
00564                 izone->sample = sample;
00565                 izone->keylo = lokey;
00566                 izone->keyhi = hikey;
00567 
00568                 // give the preset the name of the sample
00569                 FLUID_MEMCPY(preset->name, sample->name, 20);
00570         }
00571 
00572         return FLUID_OK;
00573 }
00574 
00575 fluid_inst_zone_t* fluid_rampreset_izoneforsample(fluid_rampreset_t* preset, fluid_sample_t* sample)
00576 {
00577         fluid_inst_t* inst;
00578         fluid_inst_zone_t* izone;
00579 
00580         if (preset->zone == NULL) return NULL;
00581 
00582         inst = fluid_preset_zone_get_inst(preset->zone);
00583         izone = inst->zone;
00584         while (izone) {
00585                 if (izone->sample == sample)
00586                         return izone;
00587                 izone = izone->next;
00588         }
00589         return NULL;
00590 }
00591 
00592 int fluid_rampreset_izone_set_loop(fluid_rampreset_t* preset, fluid_sample_t* sample,
00593        int on, float loopstart, float loopend) {
00594         fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample);
00595         short coarse, fine;
00596 
00597         if (izone == NULL)
00598                         return FLUID_FAILED;
00599 
00600         if (!on) {
00601                 izone->gen[GEN_SAMPLEMODE].flags = GEN_SET;
00602                 izone->gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED;
00603                 fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_UNLOOPED);
00604                 return FLUID_OK;
00605 }
00606 
00607         /* NOTE : We should check that (sample->startloop + loopStart <= sample->endloop - loopend - 32) */
00608 
00609         /* loopstart */
00610         if (loopstart > 32767. || loopstart < -32767.) {
00611                 coarse = (short)(loopstart/32768.);
00612                 fine = (short)(loopstart - (float)(coarse)*32768.);
00613         } else {
00614                 coarse = 0;
00615                 fine = (short)loopstart;
00616         }
00617         izone->gen[GEN_STARTLOOPADDROFS].flags = GEN_SET;
00618         izone->gen[GEN_STARTLOOPADDROFS].val = fine;
00619         fluid_rampreset_updatevoices(preset, GEN_STARTLOOPADDROFS, fine);
00620         if (coarse) {
00621                 izone->gen[GEN_STARTLOOPADDRCOARSEOFS].flags = GEN_SET;
00622                 izone->gen[GEN_STARTLOOPADDRCOARSEOFS].val = coarse;
00623         } else {
00624                 izone->gen[GEN_STARTLOOPADDRCOARSEOFS].flags = GEN_UNUSED;
00625         }
00626         fluid_rampreset_updatevoices(preset, GEN_STARTLOOPADDRCOARSEOFS, coarse);
00627 
00628         /* loopend */
00629         if (loopend > 32767. || loopend < -32767.) {
00630                 coarse = (short)(loopend/32768.);
00631                 fine = (short)(loopend - (float)(coarse)*32768.);
00632         } else {
00633                 coarse = 0;
00634                 fine = (short)loopend;
00635         }
00636         izone->gen[GEN_ENDLOOPADDROFS].flags = GEN_SET;
00637         izone->gen[GEN_ENDLOOPADDROFS].val = fine;
00638         fluid_rampreset_updatevoices(preset, GEN_ENDLOOPADDROFS, fine);
00639         if (coarse) {
00640                 izone->gen[GEN_ENDLOOPADDRCOARSEOFS].flags = GEN_SET;
00641                 izone->gen[GEN_ENDLOOPADDRCOARSEOFS].val = coarse;
00642         } else {
00643                 izone->gen[GEN_ENDLOOPADDRCOARSEOFS].flags = GEN_UNUSED;
00644         }
00645         fluid_rampreset_updatevoices(preset, GEN_ENDLOOPADDRCOARSEOFS, coarse);
00646 
00647         izone->gen[GEN_SAMPLEMODE].flags = GEN_SET;
00648         izone->gen[GEN_SAMPLEMODE].val = FLUID_LOOP_DURING_RELEASE;
00649         fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_LOOP_DURING_RELEASE);
00650 
00651         /* If the loop points are the whole samples, we are supposed to
00652            copy the frames around in the margins (the start to the end margin and
00653            the end to the start margin), but it works fine without this. Maybe some time
00654            it will be needed (see SAMPLE_LOOP_MARGIN) -- Antoie Schmitt May 2003 */
00655 
00656         return FLUID_OK;
00657 }
00658 
00659 int fluid_rampreset_izone_set_gen(fluid_rampreset_t* preset, fluid_sample_t* sample,
00660        int gen_type, float value) {
00661         fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample);
00662         if (izone == NULL)
00663                         return FLUID_FAILED;
00664 
00665         izone->gen[gen_type].flags = GEN_SET;
00666         izone->gen[gen_type].val = value;
00667 
00668         fluid_rampreset_updatevoices(preset, gen_type, value);
00669 
00670         return FLUID_OK;
00671 }
00672 
00673 int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* sample) {
00674         fluid_inst_t* inst;
00675         fluid_inst_zone_t* izone, * prev;
00676         int found = 0;
00677 
00678         if (preset->zone == NULL) return FLUID_FAILED;
00679         inst = fluid_preset_zone_get_inst(preset->zone);
00680         izone = inst->zone;
00681         prev = NULL;
00682         while (izone && !found) {
00683                 if (izone->sample == sample) {
00684                         if (prev == NULL) {
00685                                 inst->zone = izone->next;
00686                         } else {
00687                                 prev->next = izone->next;
00688                         }
00689                         izone->next = NULL;
00690                         delete_fluid_inst_zone(izone);
00691                         found = 1;
00692                 } else {
00693                         prev = izone;
00694                         izone = izone->next;
00695                 }
00696         }
00697         if (!found)
00698                 return FLUID_FAILED;
00699 
00700         // stop all the voices that use this sample, so that
00701         // the sample can be cleared up
00702         {
00703                 fluid_list_t *tmp = preset->presetvoices;
00704                 while (tmp) {
00705                         fluid_rampreset_voice_t *presetvoice = (fluid_rampreset_voice_t *)(tmp->data);
00706                         fluid_voice_t *voice = presetvoice->voice;
00707                         if (fluid_voice_is_playing(voice) && (fluid_voice_get_id(voice) == presetvoice->voiceID)) {
00708                                 // still belongs to the preset
00709                                 if (voice->sample == sample) {
00710                                         // uses this sample : turn it off.
00711                                         // our presetvoices struct will be cleaneup at the next update
00712                                         fluid_voice_off(voice);
00713                                 }
00714                         }
00715                         tmp = tmp->next;
00716                 }
00717         }
00718         return FLUID_OK;
00719 }
00720 
00721 /*
00722  * fluid_rampreset_remembervoice
00723  */
00724 int
00725 fluid_rampreset_remembervoice(fluid_rampreset_t* preset, fluid_voice_t* voice) {
00726         /* stores the voice and the its ID in the preset for later update on gen_set */
00727         fluid_rampreset_voice_t *presetvoice = FLUID_NEW(fluid_rampreset_voice_t);
00728         if (presetvoice == NULL) {
00729     FLUID_LOG(FLUID_ERR, "Out of memory");
00730     return FLUID_FAILED;
00731   }
00732 
00733   presetvoice->voice = voice;
00734   presetvoice->voiceID = fluid_voice_get_id(voice);
00735 
00736   preset->presetvoices = fluid_list_append(preset->presetvoices, (void *)presetvoice);
00737   if (preset->presetvoices == NULL) {
00738         FLUID_FREE(presetvoice);
00739     FLUID_LOG(FLUID_ERR, "Out of memory");
00740     return FLUID_FAILED;
00741   }
00742   return FLUID_OK;
00743 }
00744 
00745 /*
00746  * fluid_rampreset_updatevoice
00747  */
00748 void
00749 fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val) {
00750         fluid_list_t *tmp = preset->presetvoices, *prev = NULL, *next;
00751 
00752         /* walk the presetvoice to update them if they are still active and ours.
00753            If their ID has changed or their state is not playing, they are not ours, so we forget them
00754         */
00755         while (tmp) {
00756                 fluid_rampreset_voice_t *presetvoice = (fluid_rampreset_voice_t *)(tmp->data);
00757                 fluid_voice_t *voice = presetvoice->voice;
00758                 if (!fluid_voice_is_playing(voice) || (fluid_voice_get_id(voice) != presetvoice->voiceID)) {
00759                         /* forget it */
00760                 FLUID_FREE(presetvoice);
00761 
00762                         /* unlink it */
00763                         next = tmp->next;
00764                 FLUID_FREE(tmp);
00765                         if (prev) {
00766                                 prev->next = next;
00767                         } else {
00768                                 preset->presetvoices = next;
00769                         }
00770                 tmp = next;
00771 
00772                 } else {
00773 
00774                         /* update */
00775                         fluid_voice_gen_set(voice, gen_type, val);
00776                         fluid_voice_update_param(voice, gen_type);
00777 
00778                         /* next */
00779                         prev = tmp;
00780                         tmp = tmp->next;
00781                 }
00782         }
00783 }
00784 
00785 
00786 /*
00787  * fluid_rampreset_noteon
00788  */
00789 int
00790 fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
00791 {
00792   fluid_preset_zone_t *preset_zone;
00793   fluid_inst_t* inst;
00794   fluid_inst_zone_t *inst_zone, *global_inst_zone, *z;
00795   fluid_sample_t* sample;
00796   fluid_voice_t* voice;
00797   fluid_mod_t * mod;
00798   fluid_mod_t * mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset modulators */
00799   int mod_list_count;
00800   int i;
00801 
00802   /* run thru all the zones of this preset */
00803   preset_zone = preset->zone;
00804   while (preset_zone != NULL) {
00805 
00806     /* check if the note falls into the key and velocity range of this
00807        preset */
00808     if (fluid_preset_zone_inside_range(preset_zone, key, vel)) {
00809 
00810       inst = fluid_preset_zone_get_inst(preset_zone);
00811       global_inst_zone = fluid_inst_get_global_zone(inst);
00812 
00813       /* run thru all the zones of this instrument */
00814       inst_zone = fluid_inst_get_zone(inst);
00815       while (inst_zone != NULL) {
00816 
00817         /* make sure this instrument zone has a valid sample */
00818         sample = fluid_inst_zone_get_sample(inst_zone);
00819         if (fluid_sample_in_rom(sample) || (sample == NULL)) {
00820           inst_zone = fluid_inst_zone_next(inst_zone);
00821           continue;
00822         }
00823 
00824         /* check if the note falls into the key and velocity range of this
00825            instrument */
00826 
00827         if (fluid_inst_zone_inside_range(inst_zone, key, vel) && (sample != NULL)) {
00828 
00829           /* this is a good zone. allocate a new synthesis process and
00830              initialize it */
00831 
00832           voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel);
00833           if (voice == NULL) {
00834             return FLUID_FAILED;
00835           }
00836 
00837           if (fluid_rampreset_remembervoice(preset, voice) != FLUID_OK) {
00838             return FLUID_FAILED;
00839           }
00840 
00841           z = inst_zone;
00842 
00843           /* Instrument level, generators */
00844 
00845           for (i = 0; i < GEN_LAST; i++) {
00846 
00847             /* SF 2.01 section 9.4 'bullet' 4:
00848              *
00849              * A generator in a local instrument zone supersedes a
00850              * global instrument zone generator.  Both cases supersede
00851              * the default generator -> voice_gen_set */
00852 
00853             if (inst_zone->gen[i].flags){
00854               fluid_voice_gen_set(voice, i, inst_zone->gen[i].val);
00855 
00856             } else if (global_inst_zone != NULL && global_inst_zone->gen[i].flags){
00857               fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val);
00858 
00859             } else {
00860               /* The generator has not been defined in this instrument.
00861                * Do nothing, leave it at the default.
00862                */
00863             };
00864 
00865           }; /* for all generators */
00866 
00867           /* global instrument zone, modulators: Put them all into a
00868            * list. */
00869 
00870           mod_list_count = 0;
00871 
00872           if (global_inst_zone){
00873             mod = global_inst_zone->mod;
00874             while (mod){
00875               mod_list[mod_list_count++] = mod;
00876               mod = mod->next;
00877             };
00878           };
00879 
00880           /* local instrument zone, modulators.
00881            * Replace modulators with the same definition in the list:
00882            * SF 2.01 page 69, 'bullet' 8
00883            */
00884           mod = inst_zone->mod;
00885 
00886           while (mod){
00887 
00888             /* 'Identical' modulators will be deleted by setting their
00889              *  list entry to NULL.  The list length is known, NULL
00890              *  entries will be ignored later.  SF2.01 section 9.5.1
00891              *  page 69, 'bullet' 3 defines 'identical'.  */
00892 
00893             for (i = 0; i < mod_list_count; i++){
00894               if (fluid_mod_test_identity(mod,mod_list[i])){
00895                 mod_list[i] = NULL;
00896               };
00897             };
00898 
00899             /* Finally add the new modulator to to the list. */
00900             mod_list[mod_list_count++] = mod;
00901             mod = mod->next;
00902           };
00903 
00904           /* Add instrument modulators (global / local) to the voice. */
00905           for (i = 0; i < mod_list_count; i++){
00906 
00907             mod = mod_list[i];
00908 
00909             if (mod != NULL){ /* disabled modulators CANNOT be skipped. */
00910 
00911               /* Instrument modulators -supersede- existing (default)
00912                * modulators.  SF 2.01 page 69, 'bullet' 6 */
00913               fluid_voice_add_mod(voice, mod, FLUID_VOICE_OVERWRITE);
00914             };
00915           };
00916 
00917           /* Preset level, generators */
00918 
00919           for (i = 0; i < GEN_LAST; i++) {
00920 
00921             /* SF 2.01 section 8.5 page 58: If some generators are
00922              * encountered at preset level, they should be ignored */
00923             if ((i != GEN_STARTADDROFS)
00924                 && (i != GEN_ENDADDROFS)
00925                 && (i != GEN_STARTLOOPADDROFS)
00926                 && (i != GEN_ENDLOOPADDROFS)
00927                 && (i != GEN_STARTADDRCOARSEOFS)
00928                 && (i != GEN_ENDADDRCOARSEOFS)
00929                 && (i != GEN_STARTLOOPADDRCOARSEOFS)
00930                 && (i != GEN_KEYNUM)
00931                 && (i != GEN_VELOCITY)
00932                 && (i != GEN_ENDLOOPADDRCOARSEOFS)
00933                 && (i != GEN_SAMPLEMODE)
00934                 && (i != GEN_EXCLUSIVECLASS)
00935                 && (i != GEN_OVERRIDEROOTKEY)) {
00936 
00937               /* SF 2.01 section 9.4 'bullet' 9: A generator in a
00938                * local preset zone supersedes a global preset zone
00939                * generator.  The effect is -added- to the destination
00940                * summing node -> voice_gen_incr */
00941 
00942               if (preset_zone->gen[i].flags){
00943                 fluid_voice_gen_incr(voice, i, preset_zone->gen[i].val);
00944               } else {
00945                 /* The generator has not been defined in this preset
00946                  * Do nothing, leave it unchanged.
00947                  */
00948               };
00949             }; /* if available at preset level */
00950           }; /* for all generators */
00951 
00952 
00953           /* Global preset zone, modulators: put them all into a
00954            * list. */
00955           mod_list_count = 0;
00956 
00957           /* Process the modulators of the local preset zone.  Kick
00958            * out all identical modulators from the global preset zone
00959            * (SF 2.01 page 69, second-last bullet) */
00960 
00961           mod = preset_zone->mod;
00962           while (mod){
00963             for (i = 0; i < mod_list_count; i++){
00964               if (fluid_mod_test_identity(mod,mod_list[i])){
00965                 mod_list[i] = NULL;
00966               };
00967             };
00968 
00969             /* Finally add the new modulator to the list. */
00970             mod_list[mod_list_count++] = mod;
00971             mod = mod->next;
00972           };
00973 
00974           /* Add preset modulators (global / local) to the voice. */
00975           for (i = 0; i < mod_list_count; i++){
00976             mod = mod_list[i];
00977             if ((mod != NULL) && (mod->amount != 0)) { /* disabled modulators can be skipped. */
00978 
00979               /* Preset modulators -add- to existing instrument /
00980                * default modulators.  SF2.01 page 70 first bullet on
00981                * page */
00982               fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD);
00983             };
00984           };
00985 
00986           /* add the synthesis process to the synthesis loop. */
00987           fluid_synth_start_voice(synth, voice);
00988 
00989           /* Store the ID of the first voice that was created by this noteon event.
00990            * Exclusive class may only terminate older voices.
00991            * That avoids killing voices, which have just been created.
00992            * (a noteon event can create several voice processes with the same exclusive
00993            * class - for example when using stereo samples)
00994            */
00995         }
00996 
00997         inst_zone = fluid_inst_zone_next(inst_zone);
00998       }
00999     }
01000     preset_zone = fluid_preset_zone_next(preset_zone);
01001   }
01002 
01003   return FLUID_OK;
01004 }
01005 
01006 
01007 
01008 /***************************************************************
01009  *
01010  *                           SAMPLE
01011  */
01012 
01013 
01014 
01015 /*
01016  * fluid_sample_set_name
01017  */
01018 int
01019 fluid_sample_set_name(fluid_sample_t* sample, char * name)
01020 {
01021   FLUID_MEMCPY(sample->name, name, 20);
01022   return FLUID_OK;
01023 }
01024 
01025 /*
01026  * fluid_sample_set_sound_data
01027  */
01028 int
01029 fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nbframes, short copy_data, int rootkey)
01030 {
01031         /* 16 bit mono 44.1KHz data in */
01032         /* in all cases, the sample has ownership of the data : it will release it in the end */
01033         unsigned int storedNbFrames;
01034 
01035         /* in case we already have some data */
01036   if (sample->data != NULL) {
01037         FLUID_FREE(sample->data);
01038   }
01039 
01040         if (copy_data) {
01041 
01042                 /* nbframes should be >= 48 (SoundFont specs) */
01043                 storedNbFrames = nbframes;
01044                 if (storedNbFrames < 48) storedNbFrames = 48;
01045 
01046           sample->data = FLUID_MALLOC(storedNbFrames*2 + 4*SAMPLE_LOOP_MARGIN);
01047           if (sample->data == NULL) {
01048             FLUID_LOG(FLUID_ERR, "Out of memory");
01049             return FLUID_FAILED;
01050           }
01051           FLUID_MEMSET(sample->data, 0, storedNbFrames*2 + 4*SAMPLE_LOOP_MARGIN);
01052           FLUID_MEMCPY((char*)(sample->data) + 2*SAMPLE_LOOP_MARGIN, data, nbframes*2);
01053 
01054 #if 0
01055           /* this would do the fill of the margins */
01056           FLUID_MEMCPY((char*)(sample->data) + 2*SAMPLE_LOOP_MARGIN + storedNbFrames*2, (char*)data, 2*SAMPLE_LOOP_MARGIN);
01057           FLUID_MEMCPY((char*)(sample->data), (char*)data + nbframes*2 - 2*SAMPLE_LOOP_MARGIN, 2*SAMPLE_LOOP_MARGIN);
01058 #endif
01059 
01060           /* pointers */
01061           /* all from the start of data */
01062           sample->start = SAMPLE_LOOP_MARGIN;
01063           sample->end = SAMPLE_LOOP_MARGIN + storedNbFrames;
01064   } else {
01065         /* we cannot assure the SAMPLE_LOOP_MARGIN */
01066         sample->data = data;
01067           sample->start = 0;
01068           sample->end = nbframes;
01069   }
01070 
01071   /* only used as markers for the LOOP generators : set them on the first real frame */
01072   sample->loopstart = sample->start;
01073   sample->loopend = sample->end;
01074 
01075   sample->samplerate = 44100;
01076   sample->origpitch = rootkey;
01077   sample->pitchadj = 0;
01078   sample->sampletype = FLUID_SAMPLETYPE_MONO;
01079   sample->valid = 1;
01080 
01081   return FLUID_OK;
01082 }
01083 
01084 /*
01085  * new_fluid_ramsample
01086  */
01087 fluid_sample_t*
01088 new_fluid_ramsample()
01089 {
01090         /* same as new_fluid_sample. Only here so that it is exported */
01091   fluid_sample_t* sample = NULL;
01092 
01093   sample = FLUID_NEW(fluid_sample_t);
01094   if (sample == NULL) {
01095     FLUID_LOG(FLUID_ERR, "Out of memory");
01096     return NULL;
01097   }
01098 
01099   memset(sample, 0, sizeof(fluid_sample_t));
01100 
01101   return sample;
01102 }
01103 
01104 /*
01105  * delete_fluid_ramsample
01106  */
01107 int
01108 delete_fluid_ramsample(fluid_sample_t* sample)
01109 {
01110         /* same as delete_fluid_sample, plus frees the data */
01111   if (sample->data != NULL) {
01112         FLUID_FREE(sample->data);
01113   }
01114   sample->data = NULL;
01115   FLUID_FREE(sample);
01116   return FLUID_OK;
01117 }

Generated on Sat Nov 17 13:40:23 2007 for libfluidsynth by  doxygen 1.5.3