2003-03-11 16:56:45 +00:00
|
|
|
/* FluidSynth - A Software Synthesizer
|
|
|
|
*
|
|
|
|
* Copyright (C) 2003 Peter Hanappe and others.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
2017-07-12 15:45:23 +00:00
|
|
|
* modify it under the terms of the GNU Lesser General Public License
|
2017-07-12 15:53:03 +00:00
|
|
|
* as published by the Free Software Foundation; either version 2.1 of
|
2003-03-11 16:56:45 +00:00
|
|
|
* the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
2017-07-12 15:45:23 +00:00
|
|
|
* Lesser General Public License for more details.
|
2007-03-04 16:45:05 +00:00
|
|
|
*
|
2017-07-12 15:54:54 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2003-03-11 16:56:45 +00:00
|
|
|
* License along with this library; if not, write to the Free
|
2011-08-15 12:57:10 +00:00
|
|
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
|
|
* 02110-1301, USA
|
2003-03-11 16:56:45 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "fluid_ramsfont.h"
|
|
|
|
#include "fluid_sys.h"
|
2004-05-07 09:53:39 +00:00
|
|
|
#include "fluid_synth.h"
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* thenumber of samples before the start and after the end */
|
2003-05-14 00:37:55 +00:00
|
|
|
#define SAMPLE_LOOP_MARGIN 8
|
2003-03-11 16:56:45 +00:00
|
|
|
|
|
|
|
/* Prototypes */
|
2009-10-15 07:00:30 +00:00
|
|
|
static int fluid_ramsfont_sfont_delete(fluid_sfont_t* sfont);
|
2017-09-20 10:55:55 +00:00
|
|
|
static const char *fluid_ramsfont_sfont_get_name(fluid_sfont_t* sfont);
|
2009-10-15 07:00:30 +00:00
|
|
|
static fluid_preset_t *fluid_ramsfont_sfont_get_preset(fluid_sfont_t* sfont,
|
|
|
|
unsigned int bank,
|
|
|
|
unsigned int prenum);
|
|
|
|
static void fluid_ramsfont_sfont_iteration_start(fluid_sfont_t* sfont);
|
|
|
|
static int fluid_ramsfont_sfont_iteration_next(fluid_sfont_t* sfont,
|
|
|
|
fluid_preset_t* preset);
|
|
|
|
static int fluid_rampreset_preset_delete(fluid_preset_t* preset);
|
2017-09-20 10:55:55 +00:00
|
|
|
static const char *fluid_rampreset_preset_get_name(fluid_preset_t* preset);
|
2009-10-15 07:00:30 +00:00
|
|
|
static int fluid_rampreset_preset_get_banknum(fluid_preset_t* preset);
|
|
|
|
static int fluid_rampreset_preset_get_num(fluid_preset_t* preset);
|
|
|
|
static int fluid_rampreset_preset_noteon(fluid_preset_t* preset,
|
|
|
|
fluid_synth_t* synth, int chan,
|
|
|
|
int key, int vel);
|
|
|
|
static fluid_ramsfont_t *new_fluid_ramsfont (void);
|
|
|
|
static int delete_fluid_ramsfont (fluid_ramsfont_t* sfont);
|
2017-09-20 10:55:55 +00:00
|
|
|
static const char *fluid_ramsfont_get_name(fluid_ramsfont_t* sfont);
|
2009-10-15 07:00:30 +00:00
|
|
|
static int fluid_ramsfont_add_preset (fluid_ramsfont_t* sfont,
|
|
|
|
fluid_rampreset_t* preset);
|
|
|
|
static fluid_rampreset_t *fluid_ramsfont_get_preset (fluid_ramsfont_t* sfont,
|
|
|
|
unsigned int bank, unsigned int num);
|
|
|
|
static void fluid_ramsfont_iteration_start (fluid_ramsfont_t* sfont);
|
|
|
|
static int fluid_ramsfont_iteration_next (fluid_ramsfont_t* sfont,
|
|
|
|
fluid_preset_t* preset);
|
|
|
|
static fluid_rampreset_t* new_fluid_rampreset(fluid_ramsfont_t* sfont);
|
|
|
|
static int delete_fluid_rampreset (fluid_rampreset_t* preset);
|
|
|
|
static int fluid_rampreset_get_banknum (fluid_rampreset_t* preset);
|
|
|
|
static int fluid_rampreset_get_num (fluid_rampreset_t* preset);
|
2017-09-20 10:55:55 +00:00
|
|
|
static const char *fluid_rampreset_get_name (fluid_rampreset_t* preset);
|
2009-10-15 07:00:30 +00:00
|
|
|
static fluid_rampreset_t *fluid_rampreset_next (fluid_rampreset_t* preset);
|
|
|
|
static int fluid_rampreset_add_zone(fluid_rampreset_t* preset,
|
|
|
|
fluid_preset_zone_t* zone);
|
|
|
|
static int fluid_rampreset_add_sample (fluid_rampreset_t* preset,
|
|
|
|
fluid_sample_t* sample,
|
|
|
|
int lokey, int hikey);
|
|
|
|
static fluid_inst_zone_t *fluid_rampreset_izoneforsample (fluid_rampreset_t* preset,
|
|
|
|
fluid_sample_t* sample);
|
|
|
|
static int fluid_rampreset_izone_set_loop (fluid_rampreset_t* preset,
|
|
|
|
fluid_sample_t* sample,
|
|
|
|
int on, float loopstart, float loopend);
|
|
|
|
static int fluid_rampreset_izone_set_gen (fluid_rampreset_t* preset,
|
|
|
|
fluid_sample_t* sample,
|
|
|
|
int gen_type, float value);
|
|
|
|
static int fluid_rampreset_remove_izone(fluid_rampreset_t* preset,
|
|
|
|
fluid_sample_t* sample);
|
|
|
|
static int fluid_rampreset_remembervoice (fluid_rampreset_t* preset,
|
|
|
|
fluid_voice_t* voice);
|
|
|
|
static void fluid_rampreset_updatevoices (fluid_rampreset_t* preset,
|
|
|
|
int gen_type, float val);
|
|
|
|
static int fluid_rampreset_noteon (fluid_rampreset_t* preset, fluid_synth_t* synth,
|
|
|
|
int chan, int key, int vel);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a #fluid_sfont_t wrapping a #fluid_ramsfont_t
|
|
|
|
* @return New #fluid_sfont_t or NULL if out of memory
|
2003-03-11 16:56:45 +00:00
|
|
|
*/
|
|
|
|
fluid_sfont_t*
|
|
|
|
fluid_ramsfont_create_sfont()
|
|
|
|
{
|
2009-10-15 07:00:30 +00:00
|
|
|
fluid_sfont_t* sfont;
|
|
|
|
fluid_ramsfont_t* ramsfont;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
ramsfont = new_fluid_ramsfont();
|
|
|
|
if (ramsfont == NULL) {
|
2003-03-11 16:56:45 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
sfont = FLUID_NEW(fluid_sfont_t);
|
|
|
|
if (sfont == NULL) {
|
|
|
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
2013-07-17 11:28:48 +00:00
|
|
|
delete_fluid_ramsfont(ramsfont);
|
2003-03-11 16:56:45 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
sfont->data = ramsfont;
|
|
|
|
sfont->free = fluid_ramsfont_sfont_delete;
|
|
|
|
sfont->get_name = fluid_ramsfont_sfont_get_name;
|
|
|
|
sfont->get_preset = fluid_ramsfont_sfont_get_preset;
|
|
|
|
sfont->iteration_start = fluid_ramsfont_sfont_iteration_start;
|
|
|
|
sfont->iteration_next = fluid_ramsfont_sfont_iteration_next;
|
|
|
|
|
|
|
|
return sfont;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* RAM SoundFont loader method to delete SoundFont */
|
|
|
|
static int
|
|
|
|
fluid_ramsfont_sfont_delete(fluid_sfont_t* sfont)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
2009-10-15 07:00:30 +00:00
|
|
|
if (delete_fluid_ramsfont(sfont->data) != 0)
|
|
|
|
return -1;
|
|
|
|
FLUID_FREE(sfont);
|
|
|
|
return 0;
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* RAM SoundFont loader method to get name */
|
2017-09-20 10:55:55 +00:00
|
|
|
static const char *
|
2009-10-15 07:00:30 +00:00
|
|
|
fluid_ramsfont_sfont_get_name(fluid_sfont_t* sfont)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
return fluid_ramsfont_get_name((fluid_ramsfont_t*) sfont->data);
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* RAM SoundFont loader method to get a preset */
|
|
|
|
static fluid_preset_t *
|
|
|
|
fluid_ramsfont_sfont_get_preset(fluid_sfont_t* sfont, unsigned int bank, unsigned int prenum)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
fluid_preset_t* preset;
|
|
|
|
fluid_rampreset_t* rampreset;
|
|
|
|
|
|
|
|
rampreset = fluid_ramsfont_get_preset((fluid_ramsfont_t*) sfont->data, bank, prenum);
|
|
|
|
|
|
|
|
if (rampreset == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
preset = FLUID_NEW(fluid_preset_t);
|
|
|
|
if (preset == NULL) {
|
|
|
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2003-08-30 00:55:23 +00:00
|
|
|
preset->sfont = sfont;
|
2003-03-11 16:56:45 +00:00
|
|
|
preset->data = rampreset;
|
|
|
|
preset->free = fluid_rampreset_preset_delete;
|
|
|
|
preset->get_name = fluid_rampreset_preset_get_name;
|
|
|
|
preset->get_banknum = fluid_rampreset_preset_get_banknum;
|
|
|
|
preset->get_num = fluid_rampreset_preset_get_num;
|
|
|
|
preset->noteon = fluid_rampreset_preset_noteon;
|
|
|
|
preset->notify = NULL;
|
|
|
|
|
|
|
|
return preset;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* RAM SoundFont loader method to start preset iteration */
|
|
|
|
static void
|
|
|
|
fluid_ramsfont_sfont_iteration_start(fluid_sfont_t* sfont)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
fluid_ramsfont_iteration_start((fluid_ramsfont_t*) sfont->data);
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* RAM SoundFont loader method to advance preset iteration */
|
|
|
|
static int
|
|
|
|
fluid_ramsfont_sfont_iteration_next(fluid_sfont_t* sfont, fluid_preset_t* preset)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
preset->free = fluid_rampreset_preset_delete;
|
|
|
|
preset->get_name = fluid_rampreset_preset_get_name;
|
|
|
|
preset->get_banknum = fluid_rampreset_preset_get_banknum;
|
|
|
|
preset->get_num = fluid_rampreset_preset_get_num;
|
|
|
|
preset->noteon = fluid_rampreset_preset_noteon;
|
|
|
|
preset->notify = NULL;
|
|
|
|
|
|
|
|
return fluid_ramsfont_iteration_next((fluid_ramsfont_t*) sfont->data, preset);
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* RAM SoundFont loader delete preset method */
|
|
|
|
static int
|
|
|
|
fluid_rampreset_preset_delete(fluid_preset_t* preset)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
FLUID_FREE(preset);
|
2007-09-02 23:23:47 +00:00
|
|
|
|
|
|
|
/* TODO: free modulators */
|
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* RAM SoundFont loader get preset name method */
|
2017-09-20 10:55:55 +00:00
|
|
|
static const char *
|
2009-10-15 07:00:30 +00:00
|
|
|
fluid_rampreset_preset_get_name(fluid_preset_t* preset)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
2007-03-04 16:45:05 +00:00
|
|
|
return fluid_rampreset_get_name((fluid_rampreset_t*) preset->data);
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* RAM SoundFont loader get preset bank method */
|
|
|
|
static int
|
|
|
|
fluid_rampreset_preset_get_banknum(fluid_preset_t* preset)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
2007-03-04 16:45:05 +00:00
|
|
|
return fluid_rampreset_get_banknum((fluid_rampreset_t*) preset->data);
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* RAM SoundFont loader get preset program method */
|
|
|
|
static int
|
|
|
|
fluid_rampreset_preset_get_num(fluid_preset_t* preset)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
2007-03-04 16:45:05 +00:00
|
|
|
return fluid_rampreset_get_num((fluid_rampreset_t*) preset->data);
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* RAM SoundFont loader preset noteon method */
|
|
|
|
static int
|
|
|
|
fluid_rampreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
2007-03-04 16:45:05 +00:00
|
|
|
return fluid_rampreset_noteon((fluid_rampreset_t*) preset->data, synth, chan, key, vel);
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/***************************************************************
|
|
|
|
*
|
|
|
|
* SFONT
|
|
|
|
*/
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
static fluid_ramsfont_t *
|
|
|
|
new_fluid_ramsfont (void)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
fluid_ramsfont_t* sfont;
|
|
|
|
|
|
|
|
sfont = FLUID_NEW(fluid_ramsfont_t);
|
|
|
|
if (sfont == NULL) {
|
|
|
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
sfont->name[0] = 0;
|
|
|
|
sfont->sample = NULL;
|
|
|
|
sfont->preset = NULL;
|
|
|
|
|
|
|
|
return sfont;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
static int
|
|
|
|
delete_fluid_ramsfont (fluid_ramsfont_t* sfont)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
fluid_list_t *list;
|
|
|
|
fluid_rampreset_t* preset;
|
|
|
|
|
|
|
|
/* Check that no samples are currently used */
|
|
|
|
for (list = sfont->sample; list; list = fluid_list_next(list)) {
|
|
|
|
fluid_sample_t* sam = (fluid_sample_t*) fluid_list_get(list);
|
|
|
|
if (fluid_sample_refcount(sam) != 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (list = sfont->sample; list; list = fluid_list_next(list)) {
|
|
|
|
/* in ram soundfonts, the samples hold their data : so we should free it ourselves */
|
|
|
|
fluid_sample_t* sam = (fluid_sample_t*)fluid_list_get(list);
|
|
|
|
delete_fluid_ramsample(sam);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sfont->sample) {
|
|
|
|
delete_fluid_list(sfont->sample);
|
|
|
|
}
|
|
|
|
|
|
|
|
preset = sfont->preset;
|
|
|
|
while (preset != NULL) {
|
|
|
|
sfont->preset = preset->next;
|
|
|
|
delete_fluid_rampreset(preset);
|
|
|
|
preset = sfont->preset;
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
FLUID_FREE(sfont);
|
|
|
|
return FLUID_OK;
|
|
|
|
}
|
|
|
|
|
2017-09-20 10:55:55 +00:00
|
|
|
static const char *
|
2009-10-15 07:00:30 +00:00
|
|
|
fluid_ramsfont_get_name(fluid_ramsfont_t* sfont)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
return sfont->name;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/**
|
|
|
|
* Set a RAM SoundFont name.
|
|
|
|
* @param sfont RAM SoundFont
|
|
|
|
* @param name Name to assign (should be 20 chars in length with a NULL terminator)
|
|
|
|
* @return #FLUID_OK
|
2003-03-11 16:56:45 +00:00
|
|
|
*/
|
|
|
|
int
|
2009-10-28 19:38:10 +00:00
|
|
|
fluid_ramsfont_set_name (fluid_ramsfont_t *sfont, const char *name)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
2003-05-14 00:37:55 +00:00
|
|
|
FLUID_MEMCPY(sfont->name, name, 20);
|
2003-03-11 16:56:45 +00:00
|
|
|
return FLUID_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Add a preset to a RAM SoundFont */
|
|
|
|
static int
|
|
|
|
fluid_ramsfont_add_preset (fluid_ramsfont_t* sfont, fluid_rampreset_t* preset)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
fluid_rampreset_t *cur, *prev;
|
|
|
|
if (sfont->preset == NULL) {
|
|
|
|
preset->next = NULL;
|
|
|
|
sfont->preset = preset;
|
|
|
|
} else {
|
|
|
|
/* sort them as we go along. very basic sorting trick. */
|
|
|
|
cur = sfont->preset;
|
|
|
|
prev = NULL;
|
|
|
|
while (cur != NULL) {
|
2007-03-04 16:45:05 +00:00
|
|
|
if ((preset->bank < cur->bank)
|
2003-03-11 16:56:45 +00:00
|
|
|
|| ((preset->bank == cur->bank) && (preset->num < cur->num))) {
|
|
|
|
if (prev == NULL) {
|
|
|
|
preset->next = cur;
|
|
|
|
sfont->preset = preset;
|
|
|
|
} else {
|
|
|
|
preset->next = cur;
|
|
|
|
prev->next = preset;
|
|
|
|
}
|
|
|
|
return FLUID_OK;
|
|
|
|
}
|
|
|
|
prev = cur;
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
preset->next = NULL;
|
|
|
|
prev->next = preset;
|
|
|
|
}
|
|
|
|
return FLUID_OK;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/**
|
|
|
|
* Creates one instrument zone for the sample inside the preset defined by
|
|
|
|
* \a bank and \a num
|
|
|
|
* @param sfont RAM SoundFont
|
|
|
|
* @param bank Preset bank number
|
|
|
|
* @param num Preset program number
|
|
|
|
* @param sample Sample to use for instrument zone
|
|
|
|
* @param lokey Lower MIDI key range of zone (0-127, <= \a hikey)
|
|
|
|
* @param hikey Upper MIDI key range of zone (0-127, >= \a lokey)
|
|
|
|
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
|
2003-03-11 16:56:45 +00:00
|
|
|
*/
|
2009-10-15 07:00:30 +00:00
|
|
|
int
|
|
|
|
fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont, unsigned int bank,
|
|
|
|
unsigned int num, fluid_sample_t* sample,
|
|
|
|
int lokey, int hikey)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
/*- find or create a preset
|
|
|
|
- add it the sample using the fluid_rampreset_add_sample fucntion
|
|
|
|
- add the sample to the list of samples
|
|
|
|
*/
|
|
|
|
int err;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
|
|
|
|
if (preset == NULL) {
|
|
|
|
// Create it
|
|
|
|
preset = new_fluid_rampreset(sfont);
|
|
|
|
if (preset == NULL) {
|
|
|
|
return FLUID_FAILED;
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
preset->bank = bank;
|
|
|
|
preset->num = num;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
|
|
|
|
if (err != FLUID_OK) {
|
2013-07-17 11:28:48 +00:00
|
|
|
delete_fluid_rampreset(preset);
|
2003-03-11 16:56:45 +00:00
|
|
|
return FLUID_FAILED;
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
// sort the preset
|
|
|
|
fluid_ramsfont_add_preset(sfont, preset);
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
} else {
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
// just add it
|
|
|
|
err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
|
|
|
|
if (err != FLUID_OK) {
|
|
|
|
return FLUID_FAILED;
|
2007-03-04 16:45:05 +00:00
|
|
|
}
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
sfont->sample = fluid_list_append(sfont->sample, sample);
|
|
|
|
return FLUID_OK;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/**
|
|
|
|
* Removes the instrument zone corresponding to \a bank, \a num and \a sample
|
|
|
|
* @param sfont RAM SoundFont
|
|
|
|
* @param bank Preset bank number
|
|
|
|
* @param num Preset program number
|
|
|
|
* @param sample Sample of the preset zone
|
|
|
|
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
fluid_ramsfont_remove_izone (fluid_ramsfont_t* sfont, unsigned int bank,
|
|
|
|
unsigned int num, fluid_sample_t* sample)
|
|
|
|
{
|
2005-09-05 02:45:34 +00:00
|
|
|
int err;
|
2003-03-11 16:56:45 +00:00
|
|
|
fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
|
|
|
|
if (preset == NULL) {
|
2005-09-05 02:45:34 +00:00
|
|
|
return FLUID_FAILED;
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
2005-09-05 02:45:34 +00:00
|
|
|
|
|
|
|
// Fixed a crash bug : remove the sample from the sfont list after
|
|
|
|
// removing the izone (aschmitt august 2005)
|
|
|
|
err = fluid_rampreset_remove_izone(preset, sample);
|
|
|
|
if (err != FLUID_OK)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
// now we must remove the sample from sfont->sample
|
|
|
|
sfont->sample = fluid_list_remove(sfont->sample, sample);
|
|
|
|
|
|
|
|
return FLUID_OK;
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/**
|
|
|
|
* Sets a generator on an instrument zone identified by \a bank, \a num and \a sample
|
|
|
|
* @param sfont RAM SoundFont
|
|
|
|
* @param bank Preset bank number
|
|
|
|
* @param num Preset program number
|
|
|
|
* @param sample Sample of the instrument zone.
|
|
|
|
* @param gen_type Generator ID (#fluid_gen_type)
|
|
|
|
* @param value Generator value
|
|
|
|
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
fluid_ramsfont_izone_set_gen (fluid_ramsfont_t* sfont, unsigned int bank,
|
|
|
|
unsigned int num, fluid_sample_t* sample,
|
|
|
|
int gen_type, float value)
|
|
|
|
{
|
2003-03-11 16:56:45 +00:00
|
|
|
fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
|
|
|
|
if (preset == NULL) {
|
|
|
|
return FLUID_FAILED;
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
return fluid_rampreset_izone_set_gen(preset, sample, gen_type, value);
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/**
|
|
|
|
* Sets loop start/end values of the instrument zone identified by \a bank,
|
|
|
|
* \a num and \a sample.
|
|
|
|
* @param sfont RAM SoundFont
|
|
|
|
* @param bank Preset bank number
|
|
|
|
* @param num Preset program number
|
|
|
|
* @param sample Sample of the instrument zone
|
|
|
|
* @param on TRUE to enable looping, FALSE for one shot (\a loopstart and \a loopend
|
|
|
|
* not used)
|
|
|
|
* @param loopstart Loop start, in frames (counted from 0)
|
|
|
|
* @param loopend Loop end, in frames (counted from last frame, thus is < 0)
|
|
|
|
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
fluid_ramsfont_izone_set_loop (fluid_ramsfont_t *sfont, unsigned int bank,
|
|
|
|
unsigned int num, fluid_sample_t* sample,
|
|
|
|
int on, float loopstart, float loopend)
|
|
|
|
{
|
2003-03-11 16:56:45 +00:00
|
|
|
fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
|
|
|
|
if (preset == NULL) {
|
|
|
|
return FLUID_FAILED;
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
return fluid_rampreset_izone_set_loop(preset, sample, on, loopstart, loopend);
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Get a preset from a RAM SoundFont */
|
|
|
|
static fluid_rampreset_t *
|
|
|
|
fluid_ramsfont_get_preset (fluid_ramsfont_t* sfont, unsigned int bank, unsigned int num)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
fluid_rampreset_t* preset = sfont->preset;
|
|
|
|
while (preset != NULL) {
|
|
|
|
if ((preset->bank == bank) && ((preset->num == num))) {
|
|
|
|
return preset;
|
|
|
|
}
|
|
|
|
preset = preset->next;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Start preset iteration in a RAM SoundFont */
|
|
|
|
static void
|
|
|
|
fluid_ramsfont_iteration_start (fluid_ramsfont_t* sfont)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
sfont->iter_cur = sfont->preset;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Advance preset iteration in a RAM SoundFont */
|
|
|
|
static int
|
|
|
|
fluid_ramsfont_iteration_next (fluid_ramsfont_t* sfont, fluid_preset_t* preset)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
if (sfont->iter_cur == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
preset->data = (void*) sfont->iter_cur;
|
|
|
|
sfont->iter_cur = fluid_rampreset_next(sfont->iter_cur);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************
|
|
|
|
*
|
|
|
|
* PRESET
|
|
|
|
*/
|
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
typedef struct _fluid_rampreset_voice_t fluid_rampreset_voice_t;
|
|
|
|
struct _fluid_rampreset_voice_t {
|
|
|
|
fluid_voice_t *voice;
|
|
|
|
unsigned int voiceID;
|
|
|
|
};
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Create a new RAM SoundFont preset */
|
|
|
|
static fluid_rampreset_t*
|
2003-03-11 16:56:45 +00:00
|
|
|
new_fluid_rampreset(fluid_ramsfont_t* sfont)
|
|
|
|
{
|
|
|
|
fluid_rampreset_t* preset = FLUID_NEW(fluid_rampreset_t);
|
|
|
|
if (preset == NULL) {
|
2007-03-04 16:45:05 +00:00
|
|
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
2003-03-11 16:56:45 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
preset->next = NULL;
|
|
|
|
preset->sfont = sfont;
|
|
|
|
preset->name[0] = 0;
|
|
|
|
preset->bank = 0;
|
|
|
|
preset->num = 0;
|
|
|
|
preset->global_zone = NULL;
|
|
|
|
preset->zone = NULL;
|
2003-05-14 00:37:55 +00:00
|
|
|
preset->presetvoices = NULL;
|
2003-03-11 16:56:45 +00:00
|
|
|
return preset;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Delete a RAM SoundFont preset */
|
|
|
|
static int
|
|
|
|
delete_fluid_rampreset (fluid_rampreset_t* preset)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
int err = FLUID_OK;
|
|
|
|
fluid_preset_zone_t* zone;
|
2003-05-14 00:37:55 +00:00
|
|
|
fluid_rampreset_voice_t *data;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
if (preset->global_zone != NULL) {
|
|
|
|
if (delete_fluid_preset_zone(preset->global_zone) != FLUID_OK) {
|
|
|
|
err = FLUID_FAILED;
|
|
|
|
}
|
|
|
|
preset->global_zone = NULL;
|
|
|
|
}
|
|
|
|
zone = preset->zone;
|
|
|
|
while (zone != NULL) {
|
|
|
|
preset->zone = zone->next;
|
|
|
|
if (delete_fluid_preset_zone(zone) != FLUID_OK) {
|
|
|
|
err = FLUID_FAILED;
|
|
|
|
}
|
|
|
|
zone = preset->zone;
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
if (preset->presetvoices != NULL) {
|
|
|
|
fluid_list_t *tmp = preset->presetvoices, *next;
|
|
|
|
while (tmp) {
|
|
|
|
data = (fluid_rampreset_voice_t *)(tmp->data);
|
|
|
|
FLUID_FREE(data);
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
next = tmp->next;
|
|
|
|
FLUID_FREE(tmp);
|
|
|
|
tmp = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
preset->presetvoices = NULL;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
FLUID_FREE(preset);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Get a RAM SoundFont preset bank */
|
|
|
|
static int
|
|
|
|
fluid_rampreset_get_banknum (fluid_rampreset_t* preset)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
return preset->bank;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Get a RAM SoundFont preset program */
|
|
|
|
static int
|
|
|
|
fluid_rampreset_get_num (fluid_rampreset_t* preset)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
return preset->num;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Get a RAM SoundFont preset name */
|
2017-09-20 10:55:55 +00:00
|
|
|
static const char *
|
2009-10-15 07:00:30 +00:00
|
|
|
fluid_rampreset_get_name (fluid_rampreset_t* preset)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
return preset->name;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Advance to next preset */
|
|
|
|
static fluid_rampreset_t *
|
|
|
|
fluid_rampreset_next (fluid_rampreset_t* preset)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
return preset->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Add a zone to a RAM SoundFont preset */
|
|
|
|
static int
|
2003-03-11 16:56:45 +00:00
|
|
|
fluid_rampreset_add_zone(fluid_rampreset_t* preset, fluid_preset_zone_t* zone)
|
|
|
|
{
|
|
|
|
if (preset->zone == NULL) {
|
|
|
|
zone->next = NULL;
|
|
|
|
preset->zone = zone;
|
|
|
|
} else {
|
|
|
|
zone->next = preset->zone;
|
|
|
|
preset->zone = zone;
|
|
|
|
}
|
|
|
|
return FLUID_OK;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Add a sample to a RAM SoundFont preset */
|
|
|
|
static int
|
|
|
|
fluid_rampreset_add_sample (fluid_rampreset_t* preset, fluid_sample_t* sample,
|
|
|
|
int lokey, int hikey)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
/* create a new instrument zone, with the given sample */
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* one preset zone */
|
|
|
|
if (preset->zone == NULL) {
|
|
|
|
fluid_preset_zone_t* zone;
|
|
|
|
zone = new_fluid_preset_zone("");
|
|
|
|
if (zone == NULL) {
|
|
|
|
return FLUID_FAILED;
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* its instrument */
|
|
|
|
zone->inst = (fluid_inst_t*) new_fluid_inst();
|
|
|
|
if (zone->inst == NULL) {
|
|
|
|
delete_fluid_preset_zone(zone);
|
|
|
|
return FLUID_FAILED;
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
fluid_rampreset_add_zone(preset, zone);
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* add an instrument zone for each sample */
|
|
|
|
{
|
|
|
|
fluid_inst_t* inst = fluid_preset_zone_get_inst(preset->zone);
|
|
|
|
fluid_inst_zone_t* izone = new_fluid_inst_zone("");
|
|
|
|
if (izone == NULL) {
|
|
|
|
return FLUID_FAILED;
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
if (fluid_inst_add_zone(inst, izone) != FLUID_OK) {
|
|
|
|
delete_fluid_inst_zone(izone);
|
|
|
|
return FLUID_FAILED;
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
izone->sample = sample;
|
|
|
|
izone->keylo = lokey;
|
|
|
|
izone->keyhi = hikey;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
// give the preset the name of the sample
|
|
|
|
FLUID_MEMCPY(preset->name, sample->name, 20);
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
return FLUID_OK;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Find an instrument zone with the given sample */
|
|
|
|
static fluid_inst_zone_t *
|
|
|
|
fluid_rampreset_izoneforsample (fluid_rampreset_t* preset, fluid_sample_t* sample)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
fluid_inst_t* inst;
|
|
|
|
fluid_inst_zone_t* izone;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
if (preset->zone == NULL) return NULL;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
inst = fluid_preset_zone_get_inst(preset->zone);
|
|
|
|
izone = inst->zone;
|
|
|
|
while (izone) {
|
|
|
|
if (izone->sample == sample)
|
|
|
|
return izone;
|
|
|
|
izone = izone->next;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Set loop of an instrument zone */
|
|
|
|
static int
|
|
|
|
fluid_rampreset_izone_set_loop (fluid_rampreset_t* preset, fluid_sample_t* sample,
|
|
|
|
int on, float loopstart, float loopend)
|
|
|
|
{
|
2003-03-11 16:56:45 +00:00
|
|
|
fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample);
|
|
|
|
short coarse, fine;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
if (izone == NULL)
|
|
|
|
return FLUID_FAILED;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
if (!on) {
|
|
|
|
izone->gen[GEN_SAMPLEMODE].flags = GEN_SET;
|
|
|
|
izone->gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED;
|
2003-05-14 00:37:55 +00:00
|
|
|
fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_UNLOOPED);
|
2003-03-11 16:56:45 +00:00
|
|
|
return FLUID_OK;
|
2009-10-15 07:00:30 +00:00
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
/* NOTE : We should check that (sample->startloop + loopStart <= sample->endloop - loopend - 32) */
|
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* loopstart */
|
|
|
|
if (loopstart > 32767. || loopstart < -32767.) {
|
2003-05-14 00:37:55 +00:00
|
|
|
coarse = (short)(loopstart/32768.);
|
|
|
|
fine = (short)(loopstart - (float)(coarse)*32768.);
|
2003-03-11 16:56:45 +00:00
|
|
|
} else {
|
|
|
|
coarse = 0;
|
|
|
|
fine = (short)loopstart;
|
|
|
|
}
|
|
|
|
izone->gen[GEN_STARTLOOPADDROFS].flags = GEN_SET;
|
|
|
|
izone->gen[GEN_STARTLOOPADDROFS].val = fine;
|
2003-05-14 00:37:55 +00:00
|
|
|
fluid_rampreset_updatevoices(preset, GEN_STARTLOOPADDROFS, fine);
|
2003-03-11 16:56:45 +00:00
|
|
|
if (coarse) {
|
|
|
|
izone->gen[GEN_STARTLOOPADDRCOARSEOFS].flags = GEN_SET;
|
|
|
|
izone->gen[GEN_STARTLOOPADDRCOARSEOFS].val = coarse;
|
|
|
|
} else {
|
|
|
|
izone->gen[GEN_STARTLOOPADDRCOARSEOFS].flags = GEN_UNUSED;
|
|
|
|
}
|
2003-05-14 00:37:55 +00:00
|
|
|
fluid_rampreset_updatevoices(preset, GEN_STARTLOOPADDRCOARSEOFS, coarse);
|
2003-03-11 16:56:45 +00:00
|
|
|
|
|
|
|
/* loopend */
|
|
|
|
if (loopend > 32767. || loopend < -32767.) {
|
2003-05-14 00:37:55 +00:00
|
|
|
coarse = (short)(loopend/32768.);
|
|
|
|
fine = (short)(loopend - (float)(coarse)*32768.);
|
2003-03-11 16:56:45 +00:00
|
|
|
} else {
|
|
|
|
coarse = 0;
|
|
|
|
fine = (short)loopend;
|
|
|
|
}
|
|
|
|
izone->gen[GEN_ENDLOOPADDROFS].flags = GEN_SET;
|
|
|
|
izone->gen[GEN_ENDLOOPADDROFS].val = fine;
|
2003-05-14 00:37:55 +00:00
|
|
|
fluid_rampreset_updatevoices(preset, GEN_ENDLOOPADDROFS, fine);
|
2003-03-11 16:56:45 +00:00
|
|
|
if (coarse) {
|
|
|
|
izone->gen[GEN_ENDLOOPADDRCOARSEOFS].flags = GEN_SET;
|
|
|
|
izone->gen[GEN_ENDLOOPADDRCOARSEOFS].val = coarse;
|
|
|
|
} else {
|
|
|
|
izone->gen[GEN_ENDLOOPADDRCOARSEOFS].flags = GEN_UNUSED;
|
|
|
|
}
|
2003-05-14 00:37:55 +00:00
|
|
|
fluid_rampreset_updatevoices(preset, GEN_ENDLOOPADDRCOARSEOFS, coarse);
|
|
|
|
|
|
|
|
izone->gen[GEN_SAMPLEMODE].flags = GEN_SET;
|
|
|
|
izone->gen[GEN_SAMPLEMODE].val = FLUID_LOOP_DURING_RELEASE;
|
|
|
|
fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_LOOP_DURING_RELEASE);
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* If the loop points are the whole samples, we are supposed to
|
|
|
|
copy the frames around in the margins (the start to the end margin and
|
|
|
|
the end to the start margin), but it works fine without this. Maybe some time
|
2003-05-14 00:37:55 +00:00
|
|
|
it will be needed (see SAMPLE_LOOP_MARGIN) -- Antoie Schmitt May 2003 */
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
return FLUID_OK;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Set a generator on the instrument zone in preset having sample */
|
|
|
|
static int
|
|
|
|
fluid_rampreset_izone_set_gen (fluid_rampreset_t* preset, fluid_sample_t* sample,
|
|
|
|
int gen_type, float value)
|
|
|
|
{
|
2003-03-11 16:56:45 +00:00
|
|
|
fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample);
|
|
|
|
if (izone == NULL)
|
|
|
|
return FLUID_FAILED;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
izone->gen[gen_type].flags = GEN_SET;
|
|
|
|
izone->gen[gen_type].val = value;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
fluid_rampreset_updatevoices(preset, gen_type, value);
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
return FLUID_OK;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Remove the instrument zone from preset having sample */
|
|
|
|
static int
|
|
|
|
fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* sample)
|
|
|
|
{
|
2003-03-11 16:56:45 +00:00
|
|
|
fluid_inst_t* inst;
|
2003-05-14 00:37:55 +00:00
|
|
|
fluid_inst_zone_t* izone, * prev;
|
|
|
|
int found = 0;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
if (preset->zone == NULL) return FLUID_FAILED;
|
|
|
|
inst = fluid_preset_zone_get_inst(preset->zone);
|
|
|
|
izone = inst->zone;
|
|
|
|
prev = NULL;
|
2003-05-14 00:37:55 +00:00
|
|
|
while (izone && !found) {
|
2003-03-11 16:56:45 +00:00
|
|
|
if (izone->sample == sample) {
|
|
|
|
if (prev == NULL) {
|
|
|
|
inst->zone = izone->next;
|
|
|
|
} else {
|
|
|
|
prev->next = izone->next;
|
|
|
|
}
|
|
|
|
izone->next = NULL;
|
|
|
|
delete_fluid_inst_zone(izone);
|
2003-05-14 00:37:55 +00:00
|
|
|
found = 1;
|
|
|
|
} else {
|
|
|
|
prev = izone;
|
|
|
|
izone = izone->next;
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
|
|
|
}
|
2003-05-14 00:37:55 +00:00
|
|
|
if (!found)
|
|
|
|
return FLUID_FAILED;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
// stop all the voices that use this sample, so that
|
|
|
|
// the sample can be cleared up
|
|
|
|
{
|
|
|
|
fluid_list_t *tmp = preset->presetvoices;
|
|
|
|
while (tmp) {
|
|
|
|
fluid_rampreset_voice_t *presetvoice = (fluid_rampreset_voice_t *)(tmp->data);
|
|
|
|
fluid_voice_t *voice = presetvoice->voice;
|
|
|
|
if (fluid_voice_is_playing(voice) && (fluid_voice_get_id(voice) == presetvoice->voiceID)) {
|
|
|
|
// still belongs to the preset
|
|
|
|
if (voice->sample == sample) {
|
|
|
|
// uses this sample : turn it off.
|
|
|
|
// our presetvoices struct will be cleaneup at the next update
|
|
|
|
fluid_voice_off(voice);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FLUID_OK;
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Stores the voice and the its ID in the preset for later update on gen_set */
|
|
|
|
static int
|
|
|
|
fluid_rampreset_remembervoice (fluid_rampreset_t* preset, fluid_voice_t* voice)
|
|
|
|
{
|
|
|
|
fluid_rampreset_voice_t *presetvoice = FLUID_NEW(fluid_rampreset_voice_t);
|
|
|
|
if (presetvoice == NULL) {
|
2007-03-04 16:45:05 +00:00
|
|
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
2003-05-14 00:37:55 +00:00
|
|
|
return FLUID_FAILED;
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
presetvoice->voice = voice;
|
|
|
|
presetvoice->voiceID = fluid_voice_get_id(voice);
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
preset->presetvoices = fluid_list_append(preset->presetvoices, (void *)presetvoice);
|
|
|
|
if (preset->presetvoices == NULL) {
|
|
|
|
FLUID_FREE(presetvoice);
|
2007-03-04 16:45:05 +00:00
|
|
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
|
|
|
return FLUID_FAILED;
|
2003-05-14 00:37:55 +00:00
|
|
|
}
|
|
|
|
return FLUID_OK;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Update a generator in realtime for a preset */
|
|
|
|
static void
|
|
|
|
fluid_rampreset_updatevoices (fluid_rampreset_t* preset, int gen_type, float val)
|
|
|
|
{
|
2003-05-14 00:37:55 +00:00
|
|
|
fluid_list_t *tmp = preset->presetvoices, *prev = NULL, *next;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* Walk the presetvoice to update them if they are still active and ours.
|
|
|
|
* If their ID has changed or their state is not playing, they are not
|
|
|
|
* ours, so we forget them. */
|
2003-05-14 00:37:55 +00:00
|
|
|
while (tmp) {
|
|
|
|
fluid_rampreset_voice_t *presetvoice = (fluid_rampreset_voice_t *)(tmp->data);
|
|
|
|
fluid_voice_t *voice = presetvoice->voice;
|
|
|
|
if (!fluid_voice_is_playing(voice) || (fluid_voice_get_id(voice) != presetvoice->voiceID)) {
|
|
|
|
/* forget it */
|
|
|
|
FLUID_FREE(presetvoice);
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
/* unlink it */
|
|
|
|
next = tmp->next;
|
|
|
|
FLUID_FREE(tmp);
|
|
|
|
if (prev) {
|
|
|
|
prev->next = next;
|
|
|
|
} else {
|
|
|
|
preset->presetvoices = next;
|
2007-03-04 16:45:05 +00:00
|
|
|
}
|
2003-05-14 00:37:55 +00:00
|
|
|
tmp = next;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
} else {
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
/* update */
|
|
|
|
fluid_voice_gen_set(voice, gen_type, val);
|
2007-03-04 16:45:05 +00:00
|
|
|
fluid_voice_update_param(voice, gen_type);
|
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
/* next */
|
|
|
|
prev = tmp;
|
|
|
|
tmp = tmp->next;
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
2003-05-14 00:37:55 +00:00
|
|
|
}
|
|
|
|
}
|
2003-03-11 16:56:45 +00:00
|
|
|
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/* RAM SoundFont preset note on */
|
|
|
|
static int
|
|
|
|
fluid_rampreset_noteon (fluid_rampreset_t* preset, fluid_synth_t* synth, int chan,
|
|
|
|
int key, int vel)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
fluid_preset_zone_t *preset_zone;
|
|
|
|
fluid_inst_t* inst;
|
2012-09-23 09:08:45 +00:00
|
|
|
fluid_inst_zone_t *inst_zone, *global_inst_zone;
|
2003-03-11 16:56:45 +00:00
|
|
|
fluid_sample_t* sample;
|
|
|
|
fluid_voice_t* voice;
|
|
|
|
fluid_mod_t * mod;
|
|
|
|
fluid_mod_t * mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset modulators */
|
|
|
|
int mod_list_count;
|
|
|
|
int i;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* run thru all the zones of this preset */
|
|
|
|
preset_zone = preset->zone;
|
|
|
|
while (preset_zone != NULL) {
|
|
|
|
|
|
|
|
/* check if the note falls into the key and velocity range of this
|
|
|
|
preset */
|
|
|
|
if (fluid_preset_zone_inside_range(preset_zone, key, vel)) {
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
inst = fluid_preset_zone_get_inst(preset_zone);
|
|
|
|
global_inst_zone = fluid_inst_get_global_zone(inst);
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* run thru all the zones of this instrument */
|
|
|
|
inst_zone = fluid_inst_get_zone(inst);
|
|
|
|
while (inst_zone != NULL) {
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* make sure this instrument zone has a valid sample */
|
|
|
|
sample = fluid_inst_zone_get_sample(inst_zone);
|
2013-07-16 10:46:55 +00:00
|
|
|
if ((sample == NULL) || fluid_sample_in_rom(sample)) {
|
2003-03-11 16:56:45 +00:00
|
|
|
inst_zone = fluid_inst_zone_next(inst_zone);
|
|
|
|
continue;
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* check if the note falls into the key and velocity range of this
|
|
|
|
instrument */
|
|
|
|
|
|
|
|
if (fluid_inst_zone_inside_range(inst_zone, key, vel) && (sample != NULL)) {
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* this is a good zone. allocate a new synthesis process and
|
|
|
|
initialize it */
|
|
|
|
|
|
|
|
voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel);
|
|
|
|
if (voice == NULL) {
|
2007-03-04 16:45:05 +00:00
|
|
|
return FLUID_FAILED;
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
if (fluid_rampreset_remembervoice(preset, voice) != FLUID_OK) {
|
2007-03-04 16:45:05 +00:00
|
|
|
return FLUID_FAILED;
|
2003-05-14 00:37:55 +00:00
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* Instrument level, generators */
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
for (i = 0; i < GEN_LAST; i++) {
|
|
|
|
|
2007-03-04 16:45:05 +00:00
|
|
|
/* SF 2.01 section 9.4 'bullet' 4:
|
2003-03-11 16:56:45 +00:00
|
|
|
*
|
|
|
|
* A generator in a local instrument zone supersedes a
|
|
|
|
* global instrument zone generator. Both cases supersede
|
|
|
|
* the default generator -> voice_gen_set */
|
|
|
|
|
|
|
|
if (inst_zone->gen[i].flags){
|
|
|
|
fluid_voice_gen_set(voice, i, inst_zone->gen[i].val);
|
|
|
|
|
|
|
|
} else if (global_inst_zone != NULL && global_inst_zone->gen[i].flags){
|
2007-03-04 16:45:05 +00:00
|
|
|
fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val);
|
2003-03-11 16:56:45 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
/* The generator has not been defined in this instrument.
|
|
|
|
* Do nothing, leave it at the default.
|
|
|
|
*/
|
|
|
|
};
|
|
|
|
|
|
|
|
}; /* for all generators */
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* global instrument zone, modulators: Put them all into a
|
|
|
|
* list. */
|
|
|
|
|
|
|
|
mod_list_count = 0;
|
|
|
|
|
|
|
|
if (global_inst_zone){
|
|
|
|
mod = global_inst_zone->mod;
|
|
|
|
while (mod){
|
|
|
|
mod_list[mod_list_count++] = mod;
|
|
|
|
mod = mod->next;
|
|
|
|
};
|
|
|
|
};
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* local instrument zone, modulators.
|
|
|
|
* Replace modulators with the same definition in the list:
|
|
|
|
* SF 2.01 page 69, 'bullet' 8
|
|
|
|
*/
|
|
|
|
mod = inst_zone->mod;
|
|
|
|
|
|
|
|
while (mod){
|
|
|
|
|
|
|
|
/* 'Identical' modulators will be deleted by setting their
|
|
|
|
* list entry to NULL. The list length is known, NULL
|
|
|
|
* entries will be ignored later. SF2.01 section 9.5.1
|
|
|
|
* page 69, 'bullet' 3 defines 'identical'. */
|
|
|
|
|
|
|
|
for (i = 0; i < mod_list_count; i++){
|
|
|
|
if (fluid_mod_test_identity(mod,mod_list[i])){
|
|
|
|
mod_list[i] = NULL;
|
|
|
|
};
|
|
|
|
};
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* Finally add the new modulator to to the list. */
|
|
|
|
mod_list[mod_list_count++] = mod;
|
|
|
|
mod = mod->next;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Add instrument modulators (global / local) to the voice. */
|
|
|
|
for (i = 0; i < mod_list_count; i++){
|
|
|
|
|
|
|
|
mod = mod_list[i];
|
|
|
|
|
|
|
|
if (mod != NULL){ /* disabled modulators CANNOT be skipped. */
|
|
|
|
|
|
|
|
/* Instrument modulators -supersede- existing (default)
|
|
|
|
* modulators. SF 2.01 page 69, 'bullet' 6 */
|
|
|
|
fluid_voice_add_mod(voice, mod, FLUID_VOICE_OVERWRITE);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Preset level, generators */
|
|
|
|
|
|
|
|
for (i = 0; i < GEN_LAST; i++) {
|
|
|
|
|
|
|
|
/* SF 2.01 section 8.5 page 58: If some generators are
|
|
|
|
* encountered at preset level, they should be ignored */
|
2007-03-04 16:45:05 +00:00
|
|
|
if ((i != GEN_STARTADDROFS)
|
|
|
|
&& (i != GEN_ENDADDROFS)
|
|
|
|
&& (i != GEN_STARTLOOPADDROFS)
|
|
|
|
&& (i != GEN_ENDLOOPADDROFS)
|
|
|
|
&& (i != GEN_STARTADDRCOARSEOFS)
|
|
|
|
&& (i != GEN_ENDADDRCOARSEOFS)
|
2003-03-11 16:56:45 +00:00
|
|
|
&& (i != GEN_STARTLOOPADDRCOARSEOFS)
|
|
|
|
&& (i != GEN_KEYNUM)
|
|
|
|
&& (i != GEN_VELOCITY)
|
|
|
|
&& (i != GEN_ENDLOOPADDRCOARSEOFS)
|
|
|
|
&& (i != GEN_SAMPLEMODE)
|
|
|
|
&& (i != GEN_EXCLUSIVECLASS)
|
|
|
|
&& (i != GEN_OVERRIDEROOTKEY)) {
|
|
|
|
|
|
|
|
/* SF 2.01 section 9.4 'bullet' 9: A generator in a
|
|
|
|
* local preset zone supersedes a global preset zone
|
|
|
|
* generator. The effect is -added- to the destination
|
|
|
|
* summing node -> voice_gen_incr */
|
|
|
|
|
|
|
|
if (preset_zone->gen[i].flags){
|
|
|
|
fluid_voice_gen_incr(voice, i, preset_zone->gen[i].val);
|
|
|
|
} else {
|
|
|
|
/* The generator has not been defined in this preset
|
|
|
|
* Do nothing, leave it unchanged.
|
|
|
|
*/
|
|
|
|
};
|
|
|
|
}; /* if available at preset level */
|
|
|
|
}; /* for all generators */
|
2007-03-04 16:45:05 +00:00
|
|
|
|
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* Global preset zone, modulators: put them all into a
|
|
|
|
* list. */
|
|
|
|
mod_list_count = 0;
|
|
|
|
|
|
|
|
/* Process the modulators of the local preset zone. Kick
|
|
|
|
* out all identical modulators from the global preset zone
|
|
|
|
* (SF 2.01 page 69, second-last bullet) */
|
|
|
|
|
|
|
|
mod = preset_zone->mod;
|
|
|
|
while (mod){
|
|
|
|
for (i = 0; i < mod_list_count; i++){
|
|
|
|
if (fluid_mod_test_identity(mod,mod_list[i])){
|
|
|
|
mod_list[i] = NULL;
|
|
|
|
};
|
|
|
|
};
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* Finally add the new modulator to the list. */
|
|
|
|
mod_list[mod_list_count++] = mod;
|
|
|
|
mod = mod->next;
|
|
|
|
};
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* Add preset modulators (global / local) to the voice. */
|
|
|
|
for (i = 0; i < mod_list_count; i++){
|
|
|
|
mod = mod_list[i];
|
|
|
|
if ((mod != NULL) && (mod->amount != 0)) { /* disabled modulators can be skipped. */
|
|
|
|
|
|
|
|
/* Preset modulators -add- to existing instrument /
|
|
|
|
* default modulators. SF2.01 page 70 first bullet on
|
|
|
|
* page */
|
|
|
|
fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD);
|
|
|
|
};
|
2007-03-04 16:45:05 +00:00
|
|
|
};
|
2003-03-11 16:56:45 +00:00
|
|
|
|
|
|
|
/* add the synthesis process to the synthesis loop. */
|
|
|
|
fluid_synth_start_voice(synth, voice);
|
|
|
|
|
|
|
|
/* Store the ID of the first voice that was created by this noteon event.
|
|
|
|
* Exclusive class may only terminate older voices.
|
|
|
|
* That avoids killing voices, which have just been created.
|
|
|
|
* (a noteon event can create several voice processes with the same exclusive
|
|
|
|
* class - for example when using stereo samples)
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
inst_zone = fluid_inst_zone_next(inst_zone);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
preset_zone = fluid_preset_zone_next(preset_zone);
|
|
|
|
}
|
|
|
|
|
|
|
|
return FLUID_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************
|
|
|
|
*
|
|
|
|
* SAMPLE
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/**
|
|
|
|
* Set the name of a RAM SoundFont sample.
|
|
|
|
* @param sample RAM SoundFont sample
|
|
|
|
* @param name Name to assign to sample (20 chars in length, 0 terminated)
|
|
|
|
* @return #FLUID_OK
|
2003-03-11 16:56:45 +00:00
|
|
|
*/
|
|
|
|
int
|
2009-10-28 19:38:10 +00:00
|
|
|
fluid_sample_set_name(fluid_sample_t* sample, const char *name)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
2003-05-14 00:37:55 +00:00
|
|
|
FLUID_MEMCPY(sample->name, name, 20);
|
2003-03-11 16:56:45 +00:00
|
|
|
return FLUID_OK;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/**
|
|
|
|
* Assign sample data to a RAM SoundFont sample.
|
|
|
|
* @param sample RAM SoundFont sample
|
|
|
|
* @param data Buffer containing 16 bit audio sample data
|
|
|
|
* @param nbframes Number of samples in \a data
|
|
|
|
* @param copy_data TRUE to copy the data, FALSE to use it directly
|
|
|
|
* @param rootkey Root MIDI note of sample (0-127)
|
|
|
|
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
|
|
|
|
*
|
|
|
|
* WARNING: If \a copy_data is FALSE, data should have 8 unused frames at start
|
|
|
|
* and 8 unused frames at the end.
|
2003-03-11 16:56:45 +00:00
|
|
|
*/
|
|
|
|
int
|
2009-10-15 07:00:30 +00:00
|
|
|
fluid_sample_set_sound_data (fluid_sample_t* sample, short *data,
|
|
|
|
unsigned int nbframes, short copy_data, int rootkey)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
/* 16 bit mono 44.1KHz data in */
|
|
|
|
/* in all cases, the sample has ownership of the data : it will release it in the end */
|
2003-05-14 00:37:55 +00:00
|
|
|
unsigned int storedNbFrames;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* in case we already have some data */
|
|
|
|
if (sample->data != NULL) {
|
|
|
|
FLUID_FREE(sample->data);
|
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
if (copy_data) {
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
/* nbframes should be >= 48 (SoundFont specs) */
|
|
|
|
storedNbFrames = nbframes;
|
|
|
|
if (storedNbFrames < 48) storedNbFrames = 48;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
sample->data = FLUID_MALLOC(storedNbFrames*2 + 4*SAMPLE_LOOP_MARGIN);
|
2003-03-11 16:56:45 +00:00
|
|
|
if (sample->data == NULL) {
|
|
|
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
|
|
|
return FLUID_FAILED;
|
|
|
|
}
|
2003-05-14 00:37:55 +00:00
|
|
|
FLUID_MEMSET(sample->data, 0, storedNbFrames*2 + 4*SAMPLE_LOOP_MARGIN);
|
|
|
|
FLUID_MEMCPY((char*)(sample->data) + 2*SAMPLE_LOOP_MARGIN, data, nbframes*2);
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* this would do the fill of the margins */
|
|
|
|
FLUID_MEMCPY((char*)(sample->data) + 2*SAMPLE_LOOP_MARGIN + storedNbFrames*2, (char*)data, 2*SAMPLE_LOOP_MARGIN);
|
|
|
|
FLUID_MEMCPY((char*)(sample->data), (char*)data + nbframes*2 - 2*SAMPLE_LOOP_MARGIN, 2*SAMPLE_LOOP_MARGIN);
|
|
|
|
#endif
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-05-14 00:37:55 +00:00
|
|
|
/* pointers */
|
|
|
|
/* all from the start of data */
|
|
|
|
sample->start = SAMPLE_LOOP_MARGIN;
|
|
|
|
sample->end = SAMPLE_LOOP_MARGIN + storedNbFrames;
|
2003-03-11 16:56:45 +00:00
|
|
|
} else {
|
2003-05-14 00:37:55 +00:00
|
|
|
/* we cannot assure the SAMPLE_LOOP_MARGIN */
|
2003-03-11 16:56:45 +00:00
|
|
|
sample->data = data;
|
2003-05-14 00:37:55 +00:00
|
|
|
sample->start = 0;
|
|
|
|
sample->end = nbframes;
|
2003-03-11 16:56:45 +00:00
|
|
|
}
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
/* only used as markers for the LOOP generators : set them on the first real frame */
|
2003-05-14 00:37:55 +00:00
|
|
|
sample->loopstart = sample->start;
|
|
|
|
sample->loopend = sample->end;
|
2007-03-04 16:45:05 +00:00
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
sample->samplerate = 44100;
|
|
|
|
sample->origpitch = rootkey;
|
|
|
|
sample->pitchadj = 0;
|
|
|
|
sample->sampletype = FLUID_SAMPLETYPE_MONO;
|
|
|
|
sample->valid = 1;
|
|
|
|
|
|
|
|
return FLUID_OK;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/**
|
|
|
|
* Create new RAM SoundFont sample.
|
|
|
|
* @return New RAM SoundFont sample or NULL if out of memory
|
2003-03-11 16:56:45 +00:00
|
|
|
*/
|
2009-10-15 07:00:30 +00:00
|
|
|
fluid_sample_t *
|
|
|
|
new_fluid_ramsample (void)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
/* same as new_fluid_sample. Only here so that it is exported */
|
|
|
|
fluid_sample_t* sample = NULL;
|
|
|
|
|
|
|
|
sample = FLUID_NEW(fluid_sample_t);
|
|
|
|
if (sample == NULL) {
|
2007-03-04 16:45:05 +00:00
|
|
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
2003-03-11 16:56:45 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(sample, 0, sizeof(fluid_sample_t));
|
|
|
|
|
|
|
|
return sample;
|
|
|
|
}
|
|
|
|
|
2009-10-15 07:00:30 +00:00
|
|
|
/**
|
|
|
|
* Delete a RAM SoundFont sample.
|
|
|
|
* @param sample Sample to delete
|
|
|
|
* @return #FLUID_OK
|
2003-03-11 16:56:45 +00:00
|
|
|
*/
|
|
|
|
int
|
2009-10-15 07:00:30 +00:00
|
|
|
delete_fluid_ramsample (fluid_sample_t* sample)
|
2003-03-11 16:56:45 +00:00
|
|
|
{
|
|
|
|
/* same as delete_fluid_sample, plus frees the data */
|
|
|
|
if (sample->data != NULL) {
|
|
|
|
FLUID_FREE(sample->data);
|
|
|
|
}
|
|
|
|
sample->data = NULL;
|
|
|
|
FLUID_FREE(sample);
|
|
|
|
return FLUID_OK;
|
|
|
|
}
|