13
0

Update Fluidsynth to v2.0.2

This commit is contained in:
Robin Gareus 2018-11-23 14:36:52 +01:00
parent f28b03c305
commit 8c4c97d1e2
34 changed files with 16320 additions and 648 deletions

View File

@ -1,7 +1,7 @@
This is a stripped down version of fluidsynth (library only)
from git://github.com/FluidSynth/fluidsynth.git
rev. v2.0.1-5-gebc177f Oct/2018
rev. v2.0.2 (6e9d84f02a7a0f7e436c2adffc4a065608f490ba)
fluidsynth is licensed in terms of the LGPL-2+, see individual source
files for (C) holders.

View File

@ -1,10 +1,10 @@
#ifndef CONFIG_H
#define CONFIG_H
#define FLUIDSYNTH_VERSION_MAJOR 1
#define FLUIDSYNTH_VERSION_MINOR 1
#define FLUIDSYNTH_VERSION_MICRO 6
#define FLUIDSYNTH_VERSION "1.1.6"
#define FLUIDSYNTH_VERSION_MAJOR 2
#define FLUIDSYNTH_VERSION_MINOR 0
#define FLUIDSYNTH_VERSION_MICRO 2
#define FLUIDSYNTH_VERSION "2.0.2"
/* Define to enable ALSA driver */
/* #undef ALSA_SUPPORT */

View File

@ -233,7 +233,7 @@ FLUIDSYNTH_API int fluid_synth_tuning_dump(fluid_synth_t *synth, int bank, int p
/* Misc */
FLUIDSYNTH_API double fluid_synth_get_cpu_load(fluid_synth_t *synth);
FLUIDSYNTH_API const char *fluid_synth_error(fluid_synth_t *synth);
const char *fluid_synth_error(fluid_synth_t *synth);
/* Default modulators */

View File

@ -383,7 +383,7 @@ fluid_chorus_set(fluid_chorus_t *chorus, int set, int nr, fluid_real_t level,
}
void fluid_chorus_processmix(fluid_chorus_t *chorus, fluid_real_t *in,
void fluid_chorus_processmix(fluid_chorus_t *chorus, const fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out)
{
int sample_index;
@ -456,7 +456,7 @@ void fluid_chorus_processmix(fluid_chorus_t *chorus, fluid_real_t *in,
}
/* Duplication of code ... (replaces sample data instead of mixing) */
void fluid_chorus_processreplace(fluid_chorus_t *chorus, fluid_real_t *in,
void fluid_chorus_processreplace(fluid_chorus_t *chorus, const fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out)
{
int sample_index;

View File

@ -55,9 +55,9 @@ void fluid_chorus_reset(fluid_chorus_t *chorus);
void fluid_chorus_set(fluid_chorus_t *chorus, int set, int nr, fluid_real_t level,
fluid_real_t speed, fluid_real_t depth_ms, int type);
void fluid_chorus_processmix(fluid_chorus_t *chorus, fluid_real_t *in,
void fluid_chorus_processmix(fluid_chorus_t *chorus, const fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out);
void fluid_chorus_processreplace(fluid_chorus_t *chorus, fluid_real_t *in,
void fluid_chorus_processreplace(fluid_chorus_t *chorus, const fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out);

View File

@ -19,74 +19,7 @@
*/
#include "fluid_conv.h"
#define FLUID_CENTS_HZ_SIZE 1200
#define FLUID_VEL_CB_SIZE 128
#define FLUID_CB_AMP_SIZE 1441
#define FLUID_PAN_SIZE 1002
/* conversion tables */
static fluid_real_t fluid_ct2hz_tab[FLUID_CENTS_HZ_SIZE];
static fluid_real_t fluid_cb2amp_tab[FLUID_CB_AMP_SIZE];
static fluid_real_t fluid_concave_tab[FLUID_VEL_CB_SIZE];
static fluid_real_t fluid_convex_tab[FLUID_VEL_CB_SIZE];
static fluid_real_t fluid_pan_tab[FLUID_PAN_SIZE];
/*
* void fluid_synth_init
*
* Does all the initialization for this module.
*/
void
fluid_conversion_config(void)
{
int i;
double x;
for(i = 0; i < FLUID_CENTS_HZ_SIZE; i++)
{
fluid_ct2hz_tab[i] = (fluid_real_t) pow(2.0, (double) i / 1200.0);
}
/* centibels to amplitude conversion
* Note: SF2.01 section 8.1.3: Initial attenuation range is
* between 0 and 144 dB. Therefore a negative attenuation is
* not allowed.
*/
for(i = 0; i < FLUID_CB_AMP_SIZE; i++)
{
fluid_cb2amp_tab[i] = (fluid_real_t) pow(10.0, (double) i / -200.0);
}
/* initialize the conversion tables (see fluid_mod.c
fluid_mod_get_value cases 4 and 8) */
/* concave unipolar positive transform curve */
fluid_concave_tab[0] = 0.0;
fluid_concave_tab[FLUID_VEL_CB_SIZE - 1] = 1.0;
/* convex unipolar positive transform curve */
fluid_convex_tab[0] = 0;
fluid_convex_tab[FLUID_VEL_CB_SIZE - 1] = 1.0;
/* There seems to be an error in the specs. The equations are
implemented according to the pictures on SF2.01 page 73. */
for(i = 1; i < FLUID_VEL_CB_SIZE - 1; i++)
{
x = (-200.0 / FLUID_PEAK_ATTENUATION) * log((i * i) / (fluid_real_t)((FLUID_VEL_CB_SIZE - 1) * (FLUID_VEL_CB_SIZE - 1))) / M_LN10;
fluid_convex_tab[i] = (fluid_real_t)(1.0 - x);
fluid_concave_tab[(FLUID_VEL_CB_SIZE - 1) - i] = (fluid_real_t) x;
}
/* initialize the pan conversion table */
x = M_PI / 2.0 / (FLUID_PAN_SIZE - 1.0);
for(i = 0; i < FLUID_PAN_SIZE; i++)
{
fluid_pan_tab[i] = (fluid_real_t) sin(i * x);
}
}
#include "fluid_conv_tables.c"
/*
* fluid_ct2hz
@ -299,6 +232,13 @@ fluid_tc2sec_release(fluid_real_t tc)
* fluid_act2hz
*
* Convert from absolute cents to Hertz
*
* The inverse operation, converting from Hertz to cents, was unused and implemented as
*
fluid_hz2ct(fluid_real_t f)
{
return (fluid_real_t)(6900 + (1200 / M_LN2) * log(f / 440.0));
}
*/
fluid_real_t
fluid_act2hz(fluid_real_t c)
@ -306,17 +246,6 @@ fluid_act2hz(fluid_real_t c)
return (fluid_real_t)(8.176 * pow(2.0, (double) c / 1200.0));
}
/*
* fluid_hz2ct
*
* Convert from Hertz to cents
*/
fluid_real_t
fluid_hz2ct(fluid_real_t f)
{
return (fluid_real_t)(6900 + 1200 * log(f / 440.0) / M_LN2);
}
/*
* fluid_pan
*/
@ -407,3 +336,4 @@ fluid_convex(fluid_real_t val)
return fluid_convex_tab[(int) val];
}

View File

@ -22,39 +22,7 @@
#define _FLUID_CONV_H
#include "fluidsynth_priv.h"
/*
Attenuation range in centibels.
Attenuation range is the dynamic range of the volume envelope generator
from 0 to the end of attack segment.
fluidsynth is a 24 bit synth, it could (should??) be 144 dB of attenuation.
However the spec makes no distinction between 16 or 24 bit synths, so use
96 dB here.
Note about usefulness of 24 bits:
1)Even fluidsynth is a 24 bit synth, this format is only relevant if
the sample format coming from the soundfont is 24 bits and the audio sample format
choosen by the application (audio.sample.format) is not 16 bits.
2)When the sample soundfont is 16 bits, the internal 24 bits number have
16 bits msb and lsb to 0. Consequently, at the DAC output, the dynamic range of
this 24 bit sample is reduced to the the dynamic of a 16 bits sample (ie 90 db)
even if this sample is produced by the audio driver using an audio sample format
compatible for a 24 bit DAC.
3)When the audio sample format settings is 16 bits (audio.sample.format), the
audio driver will make use of a 16 bit DAC, and the dynamic will be reduced to 96 dB
even if the initial sample comes from a 24 bits soundfont.
In both cases (2) or (3), the real dynamic range is only 96 dB.
Other consideration for FLUID_NOISE_FLOOR related to case (1),(2,3):
- for case (1), FLUID_NOISE_FLOOR should be the noise floor for 24 bits (i.e -138 dB).
- for case (2) or (3), FLUID_NOISE_FLOOR should be the noise floor for 16 bits (i.e -90 dB).
*/
#define FLUID_PEAK_ATTENUATION 960.0f
void fluid_conversion_config(void);
#include "fluid_conv_tables.h"
fluid_real_t fluid_ct2hz_real(fluid_real_t cents);
fluid_real_t fluid_ct2hz(fluid_real_t cents);
@ -64,7 +32,6 @@ fluid_real_t fluid_tc2sec_delay(fluid_real_t tc);
fluid_real_t fluid_tc2sec_attack(fluid_real_t tc);
fluid_real_t fluid_tc2sec_release(fluid_real_t tc);
fluid_real_t fluid_act2hz(fluid_real_t c);
fluid_real_t fluid_hz2ct(fluid_real_t c);
fluid_real_t fluid_pan(fluid_real_t c, int left);
fluid_real_t fluid_balance(fluid_real_t balance, int left);
fluid_real_t fluid_concave(fluid_real_t val);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
#ifndef _FLUID_CONV_TABLES_H
#define _FLUID_CONV_TABLES_H
/*
Attenuation range in centibels.
Attenuation range is the dynamic range of the volume envelope generator
from 0 to the end of attack segment.
fluidsynth is a 24 bit synth, it could (should??) be 144 dB of attenuation.
However the spec makes no distinction between 16 or 24 bit synths, so use
96 dB here.
Note about usefulness of 24 bits:
1)Even fluidsynth is a 24 bit synth, this format is only relevant if
the sample format coming from the soundfont is 24 bits and the audio sample format
choosen by the application (audio.sample.format) is not 16 bits.
2)When the sample soundfont is 16 bits, the internal 24 bits number have
16 bits msb and lsb to 0. Consequently, at the DAC output, the dynamic range of
this 24 bit sample is reduced to the the dynamic of a 16 bits sample (ie 90 db)
even if this sample is produced by the audio driver using an audio sample format
compatible for a 24 bit DAC.
3)When the audio sample format settings is 16 bits (audio.sample.format), the
audio driver will make use of a 16 bit DAC, and the dynamic will be reduced to 96 dB
even if the initial sample comes from a 24 bits soundfont.
In both cases (2) or (3), the real dynamic range is only 96 dB.
Other consideration for FLUID_NOISE_FLOOR related to case (1),(2,3):
- for case (1), FLUID_NOISE_FLOOR should be the noise floor for 24 bits (i.e -138 dB).
- for case (2) or (3), FLUID_NOISE_FLOOR should be the noise floor for 16 bits (i.e -90 dB).
*/
#define FLUID_PEAK_ATTENUATION 960.0f
#define FLUID_CENTS_HZ_SIZE 1200
#define FLUID_VEL_CB_SIZE 128
#define FLUID_CB_AMP_SIZE 1441
#define FLUID_PAN_SIZE 1002
#endif

View File

@ -1,83 +0,0 @@
/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
#ifndef _FLUID_EVENT_PRIV_H
#define _FLUID_EVENT_PRIV_H
#include "fluidsynth.h"
#include "fluid_sys.h"
/* Private data for event */
/* ?? should be optimized in size, using unions */
struct _fluid_event_t {
unsigned int time;
int type;
short src;
short dest;
int channel;
short key;
short vel;
short control;
short value;
short id; //?? unused ?
int pitch;
unsigned int duration;
void* data;
};
unsigned int fluid_event_get_time(fluid_event_t* evt);
void fluid_event_set_time(fluid_event_t* evt, unsigned int time);
void fluid_event_clear(fluid_event_t* evt);
/* private data for sorter + heap */
enum fluid_evt_entry_type {
FLUID_EVT_ENTRY_INSERT = 0,
FLUID_EVT_ENTRY_REMOVE
};
typedef struct _fluid_evt_entry fluid_evt_entry;
struct _fluid_evt_entry {
fluid_evt_entry *next;
short entryType;
fluid_event_t evt;
};
#define HEAP_WITH_DYNALLOC 1
/* #undef HEAP_WITH_DYNALLOC */
typedef struct _fluid_evt_heap_t {
#ifdef HEAP_WITH_DYNALLOC
fluid_evt_entry* freelist;
fluid_mutex_t mutex;
#else
fluid_evt_entry* head;
fluid_evt_entry* tail;
fluid_evt_entry pool;
#endif
} fluid_evt_heap_t;
fluid_evt_heap_t* _fluid_evt_heap_init(int nbEvents);
void _fluid_evt_heap_free(fluid_evt_heap_t* heap);
fluid_evt_entry* _fluid_seq_heap_get_free(fluid_evt_heap_t* heap);
void _fluid_seq_heap_set_free(fluid_evt_heap_t* heap, fluid_evt_entry* evt);
#endif /* _FLUID_EVENT_PRIV_H */

View File

@ -1,195 +0,0 @@
/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
#ifndef _FLUID_EVENT_QUEUE_H
#define _FLUID_EVENT_QUEUE_H
#include "fluid_sys.h"
#include "fluid_midi.h"
#include "fluid_ringbuffer.h"
/**
* Type of queued event.
*/
enum fluid_event_queue_elem
{
FLUID_EVENT_QUEUE_ELEM_MIDI, /**< MIDI event. Uses midi field of event value */
FLUID_EVENT_QUEUE_ELEM_UPDATE_GAIN, /**< Update synthesizer gain. No payload value */
FLUID_EVENT_QUEUE_ELEM_POLYPHONY, /**< Synth polyphony event. No payload value */
FLUID_EVENT_QUEUE_ELEM_GEN, /**< Generator event. Uses gen field of event value */
FLUID_EVENT_QUEUE_ELEM_PRESET, /**< Preset set event. Uses preset field of event value */
FLUID_EVENT_QUEUE_ELEM_STOP_VOICES, /**< Stop voices event. Uses ival field of event value */
FLUID_EVENT_QUEUE_ELEM_FREE_PRESET, /**< Free preset return event. Uses pval field of event value */
FLUID_EVENT_QUEUE_ELEM_SET_TUNING, /**< Set tuning event. Uses set_tuning field of event value */
FLUID_EVENT_QUEUE_ELEM_REPL_TUNING, /**< Replace tuning event. Uses repl_tuning field of event value */
FLUID_EVENT_QUEUE_ELEM_UNREF_TUNING /**< Unref tuning return event. Uses unref_tuning field of event value */
};
/**
* SoundFont generator set event structure.
*/
typedef struct
{
int channel; /**< MIDI channel number */
int param; /**< FluidSynth generator ID */
float value; /**< Value for the generator (absolute or relative) */
int absolute; /**< 1 if value is absolute, 0 if relative */
} fluid_event_gen_t;
/**
* Preset channel assignment event structure.
*/
typedef struct
{
int channel; /**< MIDI channel number */
fluid_preset_t *preset; /**< Preset to assign (synth thread owns) */
} fluid_event_preset_t;
/**
* Tuning assignment event structure.
*/
typedef struct
{
char apply; /**< TRUE to set tuning in realtime */
int channel; /**< MIDI channel number */
fluid_tuning_t *tuning; /**< Tuning to assign */
} fluid_event_set_tuning_t;
/**
* Tuning replacement event structure.
*/
typedef struct
{
char apply; /**< TRUE if tuning change should be applied in realtime */
fluid_tuning_t *old_tuning; /**< Old tuning pointer to replace */
fluid_tuning_t *new_tuning; /**< New tuning to assign */
} fluid_event_repl_tuning_t;
/**
* Tuning unref event structure.
*/
typedef struct
{
fluid_tuning_t *tuning; /**< Tuning to unref */
int count; /**< Number of times to unref */
} fluid_event_unref_tuning_t;
/**
* Structure for an integer parameter sent to a MIDI channel (bank or SoundFont ID for example).
*/
typedef struct
{
int channel;
int val;
} fluid_event_channel_int_t;
/**
* Event queue element structure.
*/
typedef struct
{
char type; /**< fluid_event_queue_elem */
union
{
fluid_midi_event_t midi; /**< If type == FLUID_EVENT_QUEUE_ELEM_MIDI */
fluid_event_gen_t gen; /**< If type == FLUID_EVENT_QUEUE_ELEM_GEN */
fluid_event_preset_t preset; /**< If type == FLUID_EVENT_QUEUE_ELEM_PRESET */
fluid_event_set_tuning_t set_tuning; /**< If type == FLUID_EVENT_QUEUE_ELEM_SET_TUNING */
fluid_event_repl_tuning_t repl_tuning; /**< If type == FLUID_EVENT_QUEUE_ELEM_REPL_TUNING */
fluid_event_unref_tuning_t unref_tuning; /**< If type == FLUID_EVENT_QUEUE_ELEM_UNREF_TUNING */
double dval; /**< A floating point payload value */
int ival; /**< An integer payload value */
void *pval; /**< A pointer payload value */
};
} fluid_event_queue_elem_t;
typedef struct _fluid_ringbuffer_t fluid_event_queue_t;
static FLUID_INLINE fluid_event_queue_t *
fluid_event_queue_new (int count)
{
return (fluid_event_queue_t *) new_fluid_ringbuffer(count, sizeof(fluid_event_queue_elem_t));
}
static FLUID_INLINE void fluid_event_queue_free (fluid_event_queue_t *queue)
{
delete_fluid_ringbuffer(queue);
}
/**
* Get pointer to next input array element in queue.
* @param queue Lockless queue instance
* @return Pointer to array element in queue to store data to or NULL if queue is full
*
* This function along with fluid_queue_next_inptr() form a queue "push"
* operation and is split into 2 functions to avoid an element copy. Note that
* the returned array element pointer may contain the data of a previous element
* if the queue has wrapped around. This can be used to reclaim pointers to
* allocated memory, etc.
*/
static FLUID_INLINE fluid_event_queue_elem_t *
fluid_event_queue_get_inptr (fluid_event_queue_t *queue)
{
return (fluid_event_queue_elem_t *) fluid_ringbuffer_get_inptr(queue, 0);
}
/**
* Advance the input queue index to complete a "push" operation.
* @param queue Lockless queue instance
*
* This function along with fluid_queue_get_inptr() form a queue "push"
* operation and is split into 2 functions to avoid element copy.
*/
static FLUID_INLINE void
fluid_event_queue_next_inptr (fluid_event_queue_t *queue)
{
fluid_ringbuffer_next_inptr(queue, 1);
}
/**
* Get pointer to next output array element in queue.
* @param queue Lockless queue instance
* @return Pointer to array element data in the queue or NULL if empty, can only
* be used up until fluid_queue_next_outptr() is called.
*
* This function along with fluid_queue_next_outptr() form a queue "pop"
* operation and is split into 2 functions to avoid an element copy.
*/
static FLUID_INLINE fluid_event_queue_elem_t *
fluid_event_queue_get_outptr (fluid_event_queue_t *queue)
{
return (fluid_event_queue_elem_t *) fluid_ringbuffer_get_outptr(queue);
}
/**
* Advance the output queue index to complete a "pop" operation.
* @param queue Lockless queue instance
*
* This function along with fluid_queue_get_outptr() form a queue "pop"
* operation and is split into 2 functions to avoid an element copy.
*/
static FLUID_INLINE void
fluid_event_queue_next_outptr (fluid_event_queue_t *queue)
{
fluid_ringbuffer_next_outptr(queue);
}
#endif /* _FLUID_EVENT_QUEUE_H */

View File

@ -150,7 +150,7 @@ fluid_real_t fluid_gen_scale(int gen, float value)
fluid_real_t fluid_gen_scale_nrpn(int gen, int data)
{
fluid_real_t value = (float) data - 8192.0f;
fluid_clip(value, -8192, 8192);
return value * (float) fluid_gen_info[gen].nrpn_scale;
data = data - 8192;
fluid_clip(data, -8192, 8192);
return (fluid_real_t)(data * fluid_gen_info[gen].nrpn_scale);
}

View File

@ -275,8 +275,8 @@ fluid_iir_filter_calculate_coefficients(fluid_iir_filter_t *iir_filter,
* into account for both significant frequency relocation and for
* bandwidth readjustment'. */
fluid_real_t omega = (fluid_real_t)(2.0 * M_PI *
(iir_filter->last_fres / ((float) output_rate)));
fluid_real_t omega = (fluid_real_t)(2.0 * M_PI) *
(iir_filter->last_fres / output_rate);
fluid_real_t sin_coeff = (fluid_real_t) sin(omega);
fluid_real_t cos_coeff = (fluid_real_t) cos(omega);
fluid_real_t alpha_coeff = sin_coeff / (2.0f * iir_filter->q_lin);

View File

@ -2153,7 +2153,7 @@ int fluid_player_set_midi_tempo(fluid_player_t *player, int tempo)
*/
int fluid_player_set_bpm(fluid_player_t *player, int bpm)
{
return fluid_player_set_midi_tempo(player, (int)((double) 60 * 1e6 / bpm));
return fluid_player_set_midi_tempo(player, 60000000L / bpm);
}
/**
@ -2226,7 +2226,7 @@ int fluid_player_get_total_ticks(fluid_player_t *player)
*/
int fluid_player_get_bpm(fluid_player_t *player)
{
return (int)(60e6 / player->miditempo);
return 60000000L / player->miditempo;
}
/**

View File

@ -22,8 +22,6 @@
#ifndef _FLUID_PHASE_H
#define _FLUID_PHASE_H
#include "config.h"
/*
* phase
*/
@ -31,7 +29,7 @@
#define FLUID_INTERP_BITS 8
#define FLUID_INTERP_BITS_MASK 0xff000000
#define FLUID_INTERP_BITS_SHIFT 24
#define FLUID_INTERP_MAX 256
#define FLUID_FRACT_MAX ((double)4294967296.0)

View File

@ -34,7 +34,7 @@
* output. There is a very small turn-on transient response, which should not
* cause problems.
*/
#define DC_OFFSET 1e-8
#define DC_OFFSET ((fluid_real_t)1e-8)
typedef struct _fluid_allpass fluid_allpass;
typedef struct _fluid_comb fluid_comb;
@ -368,7 +368,7 @@ fluid_revmodel_reset(fluid_revmodel_t *rev)
}
void
fluid_revmodel_processreplace(fluid_revmodel_t *rev, fluid_real_t *in,
fluid_revmodel_processreplace(fluid_revmodel_t *rev, const fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out)
{
int i, k = 0;
@ -410,7 +410,7 @@ fluid_revmodel_processreplace(fluid_revmodel_t *rev, fluid_real_t *in,
}
void
fluid_revmodel_processmix(fluid_revmodel_t *rev, fluid_real_t *in,
fluid_revmodel_processmix(fluid_revmodel_t *rev, const fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out)
{
int i, k = 0;

View File

@ -61,10 +61,10 @@ typedef struct _fluid_revmodel_presets_t
fluid_revmodel_t *new_fluid_revmodel(fluid_real_t sample_rate);
void delete_fluid_revmodel(fluid_revmodel_t *rev);
void fluid_revmodel_processmix(fluid_revmodel_t *rev, fluid_real_t *in,
void fluid_revmodel_processmix(fluid_revmodel_t *rev, const fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out);
void fluid_revmodel_processreplace(fluid_revmodel_t *rev, fluid_real_t *in,
void fluid_revmodel_processreplace(fluid_revmodel_t *rev, const fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out);
void fluid_revmodel_reset(fluid_revmodel_t *rev);

View File

@ -592,7 +592,7 @@ fluid_rvoice_noteoff_LOCAL(fluid_rvoice_t *voice, unsigned int min_ticks)
{
fluid_real_t lfo = fluid_lfo_get_val(&voice->envlfo.modlfo) * -voice->envlfo.modlfo_to_vol;
fluid_real_t amp = fluid_adsr_env_get_val(&voice->envlfo.volenv) * fluid_cb2amp(lfo);
fluid_real_t env_value = - ((-200 * log(amp) / log(10.0) - lfo) / FLUID_PEAK_ATTENUATION - 1);
fluid_real_t env_value = - (((-200 / M_LN10) * log(amp) - lfo) / FLUID_PEAK_ATTENUATION - 1);
fluid_clip(env_value, 0.0, 1.0);
fluid_adsr_env_set_val(&voice->envlfo.volenv, env_value);
}

View File

@ -39,7 +39,7 @@ typedef struct _fluid_rvoice_t fluid_rvoice_t;
* 24 bits => 144-4 = 140 dB dynamic range => 1.e-7
* 1.e-7 * 2 == 2.e-7 :)
*/
#define FLUID_NOISE_FLOOR 2.e-7
#define FLUID_NOISE_FLOOR ((fluid_real_t)2.e-7)
enum fluid_loop
{

View File

@ -22,6 +22,7 @@
#include "fluid_phase.h"
#include "fluid_rvoice.h"
#include "fluid_sys.h"
#include "fluid_rvoice_dsp_tables.c"
/* Purpose:
*
@ -47,85 +48,6 @@
/* Interpolation (find a value between two samples of the original waveform) */
/* Linear interpolation table (2 coefficients centered on 1st) */
static fluid_real_t interp_coeff_linear[FLUID_INTERP_MAX][2];
/* 4th order (cubic) interpolation table (4 coefficients centered on 2nd) */
static fluid_real_t interp_coeff[FLUID_INTERP_MAX][4];
/* 7th order interpolation (7 coefficients centered on 3rd) */
static fluid_real_t sinc_table7[FLUID_INTERP_MAX][7];
#define SINC_INTERP_ORDER 7 /* 7th order constant */
/* Initializes interpolation tables */
void fluid_rvoice_dsp_config(void)
{
int i, i2;
double x, v;
double i_shifted;
/* Initialize the coefficients for the interpolation. The math comes
* from a mail, posted by Olli Niemitalo to the music-dsp mailing
* list (I found it in the music-dsp archives
* http://www.smartelectronix.com/musicdsp/). */
for(i = 0; i < FLUID_INTERP_MAX; i++)
{
x = (double) i / (double) FLUID_INTERP_MAX;
interp_coeff[i][0] = (fluid_real_t)(x * (-0.5 + x * (1 - 0.5 * x)));
interp_coeff[i][1] = (fluid_real_t)(1.0 + x * x * (1.5 * x - 2.5));
interp_coeff[i][2] = (fluid_real_t)(x * (0.5 + x * (2.0 - 1.5 * x)));
interp_coeff[i][3] = (fluid_real_t)(0.5 * x * x * (x - 1.0));
interp_coeff_linear[i][0] = (fluid_real_t)(1.0 - x);
interp_coeff_linear[i][1] = (fluid_real_t)x;
}
/* i: Offset in terms of whole samples */
for(i = 0; i < SINC_INTERP_ORDER; i++)
{
/* i2: Offset in terms of fractional samples ('subsamples') */
for(i2 = 0; i2 < FLUID_INTERP_MAX; i2++)
{
/* center on middle of table */
i_shifted = (double)i - ((double)SINC_INTERP_ORDER / 2.0)
+ (double)i2 / (double)FLUID_INTERP_MAX;
/* sinc(0) cannot be calculated straightforward (limit needed for 0/0) */
if(fabs(i_shifted) > 0.000001)
{
double arg = M_PI * i_shifted;
v = (fluid_real_t)sin(arg) / (arg);
/* Hanning window */
v *= (fluid_real_t)0.5 * (1.0 + cos(2.0 * arg / (fluid_real_t)SINC_INTERP_ORDER));
}
else
{
v = 1.0;
}
sinc_table7[FLUID_INTERP_MAX - i2 - 1][i] = v;
}
}
#if 0
for(i = 0; i < FLUID_INTERP_MAX; i++)
{
printf("%d %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f\n",
i, sinc_table7[0][i], sinc_table7[1][i], sinc_table7[2][i],
sinc_table7[3][i], sinc_table7[4][i], sinc_table7[5][i], sinc_table7[6][i]);
}
#endif
fluid_check_fpe("interpolation table calculation");
}
static FLUID_INLINE fluid_real_t
fluid_rvoice_get_float_sample(const short int *dsp_msb, const char *dsp_lsb, unsigned int idx)
{

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,6 @@
#include "fluidsynth_priv.h"
#include "fluid_synth.h"
#undef ENABLE_MIXER_THREADS // Ardour does the multithreading -- synth.cpu-cores defaults to 1
// If less than x voices, the thread overhead is larger than the gain,
// so don't activate the thread(s).
@ -39,13 +38,12 @@ struct _fluid_mixer_buffers_t
fluid_rvoice_mixer_t *mixer; /**< Owner of object */
#if ENABLE_MIXER_THREADS
fluid_thread_t *thread; /**< Thread object */
fluid_atomic_int_t ready; /**< Atomic: buffers are ready for mixing */
#endif
fluid_rvoice_t **finished_voices; /* List of voices who have finished */
int finished_voice_count;
fluid_atomic_int_t ready; /**< Atomic: buffers are ready for mixing */
fluid_real_t *local_buf;
int buf_count;
@ -128,8 +126,8 @@ fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcoun
const int fx_channels_per_unit = mixer->buffers.fx_buf_count / mixer->fx_units;
int i, f;
void (*reverb_process_func)(fluid_revmodel_t *rev, fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);
void (*chorus_process_func)(fluid_chorus_t *chorus, fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);
void (*reverb_process_func)(fluid_revmodel_t *rev, const fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);
void (*chorus_process_func)(fluid_chorus_t *chorus, const fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);
fluid_real_t *out_rev_l, *out_rev_r, *out_ch_l, *out_ch_r;
@ -373,7 +371,7 @@ get_dest_buf(fluid_rvoice_buffers_t *buffers, int index,
*/
static void
fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t *buffers,
fluid_real_t *FLUID_RESTRICT dsp_buf,
const fluid_real_t *FLUID_RESTRICT dsp_buf,
int start_block, int sample_count,
fluid_real_t **dest_bufs, int dest_bufcount)
{

View File

@ -1732,7 +1732,6 @@ fluid_settings_option_concat(fluid_settings_t *settings, const char *name,
const char *separator)
{
fluid_setting_node_t *node;
fluid_str_setting_t *setting;
fluid_list_t *p, *newlist = NULL;
size_t count, len;
char *str, *option;
@ -1755,10 +1754,8 @@ fluid_settings_option_concat(fluid_settings_t *settings, const char *name,
return (NULL);
}
setting = &node->str;
/* Duplicate option list, count options and get total string length */
for(p = setting->options, count = 0, len = 0; p; p = p->next, count++)
for(p = node->str.options, count = 0, len = 0; p; p = p->next)
{
option = fluid_list_get(p);
@ -1766,6 +1763,7 @@ fluid_settings_option_concat(fluid_settings_t *settings, const char *name,
{
newlist = fluid_list_append(newlist, option);
len += FLUID_STRLEN(option);
count++;
}
}

View File

@ -77,9 +77,31 @@ enum
SM24_ID
};
static const char idlist[] = {"RIFFLISTsfbkINFOsdtapdtaifilisngINAMiromiverICRDIENGIPRD"
"ICOPICMTISFTsnamsmplphdrpbagpmodpgeninstibagimodigenshdrsm24"
};
/*
* This declares a char array containing the SF2 chunk identifiers. This
* array is being accessed like an uint32 below to simplify id comparison.
* To make sure it is suitably aligned for uint32 access, we must wrap it
* inside a union along with a uint32 telling the compiler to align it
* for integer access and avoiding undefined behaviour.
* This basically is the C89 equivalent to what is written in C11 as:
* alignas(uint32_t) static const char idlist[] = {};
*
* See: EXP36-C. Do not cast pointers into more strictly aligned pointer
* types - SEI CERT C Coding Standard
*/
static const union fluid_idlist
{
/*
* Cannot be char c[ ], because in C89, arrays wraped in unions
* must have a fixed size. Otherwise the size of the union would depend
* on the initialization of its first member, which results in
* different sizes for different instances of the same union type.
*/
char c[116];
uint32_t i;
} idlist = {"RIFFLISTsfbkINFOsdtapdtaifilisngINAMiromiverICRDIENGIPRD"
"ICOPICMTISFTsnamsmplphdrpbagpmodpgeninstibagimodigenshdrsm24"
};
/* generator types */
@ -183,7 +205,7 @@ static const unsigned short invalid_preset_gen[] =
};
#define CHNKIDSTR(id) &idlist[(id - 1) * 4]
#define CHNKIDSTR(id) &idlist.c[(id - 1) * 4]
/* sfont file chunk sizes */
#define SF_PHDR_SIZE (38)
@ -284,7 +306,7 @@ static int load_shdr(SFData *sf, unsigned int size);
static int fixup_pgen(SFData *sf);
static int fixup_igen(SFData *sf);
static int chunkid(unsigned int id);
static int chunkid(uint32_t id);
static int read_listchunk(SFData *sf, SFChunk *chunk);
static int pdtahelper(SFData *sf, unsigned int expid, unsigned int reclen, SFChunk *chunk, int *size);
static int preset_compare_func(void *a, void *b);
@ -486,14 +508,12 @@ void fluid_sffile_close(SFData *sf)
*/
/* sound font file load functions */
static int chunkid(unsigned int id)
static int chunkid(uint32_t id)
{
unsigned int i;
const unsigned int *p;
const uint32_t *p = &idlist.i;
p = (const unsigned int *)&idlist;
for(i = 0; i < sizeof(idlist) / sizeof(int); i++, p += 1)
for(i = 0; i < sizeof(idlist) / sizeof(idlist.i); i++, p += 1)
{
if(*p == id)
{
@ -987,6 +1007,7 @@ static int load_phdr(SFData *sf, int size)
FLUID_LOG(FLUID_ERR, "Out of memory");
return FALSE;
}
sf->preset = fluid_list_append(sf->preset, preset);
preset->zone = NULL; /* In case of failure, fluid_sffile_close can cleanup */
READSTR(sf, &preset->name); /* possible read failure ^ */
@ -1078,6 +1099,7 @@ static int load_pbag(SFData *sf, int size)
FLUID_LOG(FLUID_ERR, "Out of memory");
return FALSE;
}
p2->data = z;
z->gen = NULL; /* Init gen and mod before possible failure, */
z->mod = NULL; /* to ensure proper cleanup (fluid_sffile_close) */
@ -1211,6 +1233,7 @@ static int load_pmod(SFData *sf, int size)
FLUID_LOG(FLUID_ERR, "Out of memory");
return FALSE;
}
p3->data = m;
READW(sf, m->src);
READW(sf, m->dest);
@ -1367,6 +1390,7 @@ static int load_pgen(SFData *sf, int size)
FLUID_LOG(FLUID_ERR, "Out of memory");
return FALSE;
}
p3->data = g;
g->id = genid;
}
@ -1508,6 +1532,7 @@ static int load_ihdr(SFData *sf, int size)
FLUID_LOG(FLUID_ERR, "Out of memory");
return FALSE;
}
sf->inst = fluid_list_append(sf->inst, p);
p->zone = NULL; /* For proper cleanup if fail (fluid_sffile_close) */
p->idx = i;
@ -1593,6 +1618,7 @@ static int load_ibag(SFData *sf, int size)
FLUID_LOG(FLUID_ERR, "Out of memory");
return FALSE;
}
p2->data = z;
z->gen = NULL; /* In case of failure, */
z->mod = NULL; /* fluid_sffile_close can clean up */
@ -1727,6 +1753,7 @@ static int load_imod(SFData *sf, int size)
FLUID_LOG(FLUID_ERR, "Out of memory");
return FALSE;
}
p3->data = m;
READW(sf, m->src);
READW(sf, m->dest);
@ -1872,6 +1899,7 @@ static int load_igen(SFData *sf, int size)
FLUID_LOG(FLUID_ERR, "Out of memory");
return FALSE;
}
p3->data = g;
g->id = genid;
}
@ -2011,6 +2039,7 @@ static int load_shdr(SFData *sf, unsigned int size)
FLUID_LOG(FLUID_ERR, "Out of memory");
return FALSE;
}
sf->sample = fluid_list_append(sf->sample, p);
READSTR(sf, &p->name);
READD(sf, p->start);
@ -2138,7 +2167,7 @@ static void delete_preset(SFPreset *preset)
}
delete_fluid_list(preset->zone);
FLUID_FREE(preset);
}
@ -2162,7 +2191,7 @@ static void delete_inst(SFInst *inst)
}
delete_fluid_list(inst->zone);
FLUID_FREE(inst);
}

View File

@ -88,15 +88,13 @@ static void fluid_synth_update_presets(fluid_synth_t *synth);
static void fluid_synth_update_gain_LOCAL(fluid_synth_t *synth);
static int fluid_synth_update_polyphony_LOCAL(fluid_synth_t *synth, int new_polyphony);
static void init_dither(void);
static FLUID_INLINE int roundi(float x);
static FLUID_INLINE int16_t round_clip_to_i16(float x);
static int fluid_synth_render_blocks(fluid_synth_t *synth, int blockcount);
static fluid_voice_t *fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t *synth);
static void fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t *synth,
fluid_voice_t *new_voice);
static int fluid_synth_sfunload_callback(void *data, unsigned int msec);
void fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t *synth,
int chan, int key);
static fluid_tuning_t *fluid_synth_get_tuning(fluid_synth_t *synth,
int bank, int prog);
static int fluid_synth_replace_tuning_LOCK(fluid_synth_t *synth,
@ -147,8 +145,6 @@ static int fluid_synth_set_chorus_full_LOCAL(fluid_synth_t *synth, int set, int
/* has the synth module been initialized? */
/* fluid_atomic_int_t may be anything, so init with {0} to catch most cases */
static fluid_atomic_int_t fluid_synth_initialized = {0};
static void fluid_synth_init(void);
static void init_dither(void);
/* default modulators
* SF2.01 page 52 ff:
@ -226,8 +222,12 @@ void fluid_synth_settings(fluid_settings_t *settings)
fluid_settings_register_int(settings, "synth.effects-groups", 1, 1, 128, 0);
fluid_settings_register_num(settings, "synth.sample-rate", 44100.0f, 8000.0f, 96000.0f, 0);
fluid_settings_register_int(settings, "synth.device-id", 0, 0, 126, 0);
#ifdef ENABLE_MIXER_THREADS
fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 256, 0);
#else
fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 1, 0);
#endif
fluid_settings_register_int(settings, "synth.min-note-length", 10, 0, 65535, 0);
fluid_settings_register_int(settings, "synth.threadsafe-api", 1, 0, 1, FLUID_HINT_TOGGLED);
@ -286,10 +286,6 @@ fluid_synth_init(void)
feenableexcept(FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID);
#endif
fluid_conversion_config();
fluid_rvoice_dsp_config();
init_dither();
/* custom_breath2att_mod is not a default modulator specified in SF2.01.
@ -1108,6 +1104,8 @@ delete_fluid_synth(fluid_synth_t *synth)
* @return Pointer to string of last error message. Valid until the same
* calling thread calls another FluidSynth function which fails. String is
* internal and should not be modified or freed.
* @deprecated This function is not thread-safe and does not work with multiple synths.
* It has been deprecated. It may return "" in a future release and will eventually be removed.
*/
/* FIXME - The error messages are not thread-safe, yet. They are still stored
* in a global message buffer (see fluid_sys.c). */
@ -1320,7 +1318,7 @@ fluid_synth_damp_voices_by_sostenuto_LOCAL(fluid_synth_t *synth, int chan)
* @param mod Modulator info (values copied, passed in object can be freed immediately afterwards)
* @param mode Determines how to handle an existing identical modulator (#fluid_synth_add_mod)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*
*
* @note Not realtime safe (due to internal memory allocation) and therefore should not be called
* from synthesis context at the risk of stalling audio output.
*/
@ -1390,7 +1388,7 @@ fluid_synth_add_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod, int mo
* @param synth synth instance
* @param mod The modulator to remove
* @return #FLUID_OK if a matching modulator was found and successfully removed, #FLUID_FAILED otherwise
*
*
* @note Not realtime safe (due to internal memory allocation) and therefore should not be called
* from synthesis context at the risk of stalling audio output.
*/
@ -1515,7 +1513,37 @@ fluid_synth_cc(fluid_synth_t *synth, int chan, int num, int val)
FLUID_API_RETURN(result);
}
/* Local synthesis thread variant of MIDI CC set function. */
/* Local synthesis thread variant of MIDI CC set function.
Most of CC are allowed to modulate but not all. A comment describes if CC num
isn't allowed to modulate.
Following explanations should help to understand both MIDI specifications and
Soundfont specifications in regard to MIDI specs.
MIDI specs:
CC LSB (32 to 63) are LSB contributions to CC MSB (0 to 31).
It's up to the synthesizer to decide to take LSB values into account or not.
Actually Fluidsynth doesn't use CC LSB value inside fluid_voice_update_param()
(once fluid_voice_modulate() has been triggered). This is because actually
fluidsynth needs only 7 bits resolution (and not 14 bits) from these CCs.
So fluidsynth is using only 7 bit MSB (except for portamento time).
In regard to MIDI specs Fluidsynth behaves correctly.
Soundfont specs 2.01 - 8.2.1:
To deal correctly with MIDI CC (regardless if any synth will use CC MSB alone (7 bit)
or both CCs MSB,LSB (14 bits) during synthesis), SF specs recommend not making use of
CC LSB (i.e only CC MSB) in modulator sources to trigger modulation (i.e modulators
with CC LSB connected to sources inputs should be ignored).
These specifics are particularly suited for synths that use 14 bits CCs. In this case,
the MIDI transmitter sends CC LSB first followed by CC MSB. The MIDI synth receives
both CC LSB and CC MSB but only CC MSB will trigger the modulation.
This will produce correct synthesis parameters update from a correct 14 bits CC.
If in SF specs, modulator sources with CC LSB had been accepted, both CC LSB and
CC MSB will triggers 2 modulations. This leads to incorrect synthesis parameters
update followed by correct synthesis parameters update.
However, as long as fluidsynth will use only CC 7 bits resolution, it is safe to ignore
these SF recommendations on CC receive.
*/
static int
fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
{
@ -1527,8 +1555,11 @@ fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
switch(num)
{
case LOCAL_CONTROL: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
break;
/* CC omnioff, omnion, mono, poly */
/* not allowed to modulate (spec SF 2.01 - 8.2.1) */
case POLY_OFF:
case POLY_ON:
case OMNI_OFF:
@ -1583,18 +1614,18 @@ fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
return FLUID_FAILED;
case LEGATO_SWITCH:
case LEGATO_SWITCH: /* not allowed to modulate */
/* handles Poly/mono commutation on Legato pedal On/Off.*/
fluid_channel_cc_legato(chan, value);
break;
case PORTAMENTO_SWITCH:
case PORTAMENTO_SWITCH: /* not allowed to modulate */
/* Special handling of the monophonic list */
/* Invalids the most recent note played in a staccato manner */
fluid_channel_invalid_prev_note_staccato(chan);
break;
case SUSTAIN_SWITCH:
case SUSTAIN_SWITCH: /* not allowed to modulate */
/* Release voices if Sustain switch is released */
if(value < 64) /* Sustain is released */
@ -1604,7 +1635,7 @@ fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
break;
case SOSTENUTO_SWITCH:
case SOSTENUTO_SWITCH: /* not allowed to modulate */
/* Release voices if Sostetuno switch is released */
if(value < 64) /* Sostenuto is released */
@ -1619,28 +1650,31 @@ fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
break;
case BANK_SELECT_MSB:
case BANK_SELECT_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
fluid_channel_set_bank_msb(chan, value & 0x7F);
break;
case BANK_SELECT_LSB:
case BANK_SELECT_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
fluid_channel_set_bank_lsb(chan, value & 0x7F);
break;
case ALL_NOTES_OFF:
case ALL_NOTES_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
fluid_synth_all_notes_off_LOCAL(synth, channum);
break;
case ALL_SOUND_OFF:
case ALL_SOUND_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
fluid_synth_all_sounds_off_LOCAL(synth, channum);
break;
case ALL_CTRL_OFF:
case ALL_CTRL_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
fluid_channel_init_ctrl(chan, 1);
fluid_synth_modulate_voices_all_LOCAL(synth, channum);
break;
case DATA_ENTRY_MSB:
case DATA_ENTRY_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
break;
case DATA_ENTRY_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
{
int data = (value << 7) + fluid_channel_get_cc(chan, DATA_ENTRY_LSB);
@ -1700,13 +1734,13 @@ fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
break;
}
case NRPN_MSB:
case NRPN_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
fluid_channel_set_cc(chan, NRPN_LSB, 0);
chan->nrpn_select = 0;
chan->nrpn_active = 1;
break;
case NRPN_LSB:
case NRPN_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
/* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */
if(fluid_channel_get_cc(chan, NRPN_MSB) == 120)
@ -1732,8 +1766,8 @@ fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
chan->nrpn_active = 1;
break;
case RPN_MSB:
case RPN_LSB:
case RPN_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
case RPN_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
chan->nrpn_active = 0;
break;
@ -1743,7 +1777,14 @@ fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
/* fall-through */
default:
return fluid_synth_modulate_voices_LOCAL(synth, channum, 1, num);
/* CC lsb shouldn't allowed to modulate (spec SF 2.01 - 8.2.1) */
/* However, as long fluidsynth will use only CC 7 bits resolution, it
is safe to ignore these SF recommendations on CC receive. See
explanations above */
/* if (! (32 <= num && num <= 63)) */
{
return fluid_synth_modulate_voices_LOCAL(synth, channum, 1, num);
}
}
return FLUID_OK;
@ -3808,17 +3849,28 @@ init_dither(void)
}
/* A portable replacement for roundf(), seems it may actually be faster too! */
static FLUID_INLINE int
roundi(float x)
static FLUID_INLINE int16_t
round_clip_to_i16(float x)
{
long i;
if(x >= 0.0f)
{
return (int)(x + 0.5f);
i = (long)(x + 0.5f);
if (FLUID_UNLIKELY(i > 32767))
{
i = 32767;
}
}
else
{
return (int)(x - 0.5f);
i = (long)(x - 0.5f);
if (FLUID_UNLIKELY(i < -32768))
{
i = -32768;
}
}
return (int16_t)i;
}
/**
@ -3847,12 +3899,10 @@ fluid_synth_write_s16(fluid_synth_t *synth, int len,
void *rout, int roff, int rincr)
{
int i, j, k, cur;
signed short *left_out = (signed short *) lout;
signed short *right_out = (signed short *) rout;
int16_t *left_out = lout;
int16_t *right_out = rout;
fluid_real_t *left_in;
fluid_real_t *right_in;
fluid_real_t left_sample;
fluid_real_t right_sample;
double time = fluid_utime();
int di;
float cpu_load;
@ -3877,39 +3927,13 @@ fluid_synth_write_s16(fluid_synth_t *synth, int len,
cur = 0;
}
left_sample = roundi(left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[0][di]);
right_sample = roundi(right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[1][di]);
left_out[j] = round_clip_to_i16(left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[0][di]);
right_out[k] = round_clip_to_i16(right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[1][di]);
di++;
if(di >= DITHER_SIZE)
if(++di >= DITHER_SIZE)
{
di = 0;
}
/* digital clipping */
if(left_sample > 32767.0f)
{
left_sample = 32767.0f;
}
if(left_sample < -32768.0f)
{
left_sample = -32768.0f;
}
if(right_sample > 32767.0f)
{
right_sample = 32767.0f;
}
if(right_sample < -32768.0f)
{
right_sample = -32768.0f;
}
left_out[j] = (signed short) left_sample;
right_out[k] = (signed short) right_sample;
}
synth->cur = cur;
@ -3943,54 +3967,25 @@ fluid_synth_write_s16(fluid_synth_t *synth, int len,
* @note Currently private to libfluidsynth.
*/
void
fluid_synth_dither_s16(int *dither_index, int len, float *lin, float *rin,
fluid_synth_dither_s16(int *dither_index, int len, const float *lin, const float *rin,
void *lout, int loff, int lincr,
void *rout, int roff, int rincr)
{
int i, j, k;
signed short *left_out = (signed short *) lout;
signed short *right_out = (signed short *) rout;
fluid_real_t left_sample;
fluid_real_t right_sample;
int16_t *left_out = lout;
int16_t *right_out = rout;
int di = *dither_index;
fluid_profile_ref_var(prof_ref);
for(i = 0, j = loff, k = roff; i < len; i++, j += lincr, k += rincr)
{
left_out[j] = round_clip_to_i16(lin[i] * 32766.0f + rand_table[0][di]);
right_out[k] = round_clip_to_i16(rin[i] * 32766.0f + rand_table[1][di]);
left_sample = roundi(lin[i] * 32766.0f + rand_table[0][di]);
right_sample = roundi(rin[i] * 32766.0f + rand_table[1][di]);
di++;
if(di >= DITHER_SIZE)
if(++di >= DITHER_SIZE)
{
di = 0;
}
/* digital clipping */
if(left_sample > 32767.0f)
{
left_sample = 32767.0f;
}
if(left_sample < -32768.0f)
{
left_sample = -32768.0f;
}
if(right_sample > 32767.0f)
{
right_sample = 32767.0f;
}
if(right_sample < -32768.0f)
{
right_sample = -32768.0f;
}
left_out[j] = (signed short) left_sample;
right_out[k] = (signed short) right_sample;
}
*dither_index = di; /* keep dither buffer continous */

View File

@ -190,7 +190,7 @@ fluid_preset_t *fluid_synth_find_preset(fluid_synth_t *synth,
int prognum);
void fluid_synth_sfont_unref(fluid_synth_t *synth, fluid_sfont_t *sfont);
void fluid_synth_dither_s16(int *dither_index, int len, float *lin, float *rin,
void fluid_synth_dither_s16(int *dither_index, int len, const float *lin, const float *rin,
void *lout, int loff, int lincr,
void *rout, int roff, int rincr);

View File

@ -290,11 +290,6 @@ static char fluid_synth_get_fromkey_portamento_legato(fluid_channel_t *chan,
* Sust.on/off >------------------------->|_______________|
* Sost.on/off
------------------------------------------------------------------------------*/
int fluid_synth_noteoff_monopoly(fluid_synth_t *synth, int chan, int key,
char Mono);
int fluid_synth_noteon_monopoly_legato(fluid_synth_t *synth, int chan,
int fromkey, int tokey, int vel);
/**
* Plays a noteon event for a Synth instance in "monophonic playing" state.

View File

@ -1280,6 +1280,7 @@ fluid_istream_readline(fluid_istream_t in, fluid_ostream_t out, char *prompt,
FLUID_SNPRINTF(buf, len, "%s", line);
buf[len - 1] = 0;
add_history(buf);
free(line);
return 1;
@ -1331,9 +1332,10 @@ fluid_istream_gets(fluid_istream_t in, char *buf, int len)
}
else
{
#ifdef NETWORK_SUPPORT
n = recv(in & ~FLUID_SOCKET_FLAG, &c, 1, 0);
if(n == SOCKET_ERROR)
#endif
{
return -1;
}
@ -1406,10 +1408,13 @@ fluid_ostream_printf(fluid_ostream_t out, const char *format, ...)
return write(out, buf, FLUID_STRLEN(buf));
}
#ifdef NETWORK_SUPPORT
/* Socket */
retval = send(out & ~FLUID_SOCKET_FLAG, buf, FLUID_STRLEN(buf), 0);
return retval != SOCKET_ERROR ? retval : -1;
#else
return -1;
#endif
}
#endif
}

View File

@ -685,7 +685,7 @@ calculate_hold_decay_buffers(fluid_voice_t *voice, int gen_base,
* will cause (60-72)*100=-1200 timecents of time variation.
* The time is cut in half.
*/
timecents = (fluid_voice_gen_value(voice, gen_base) + fluid_voice_gen_value(voice, gen_key2base) * (60.0 - fluid_voice_get_actual_key(voice)));
timecents = (fluid_voice_gen_value(voice, gen_base) + fluid_voice_gen_value(voice, gen_key2base) * (fluid_real_t)(60 - fluid_voice_get_actual_key(voice)));
/* Range checking */
if(is_decay)

View File

@ -134,8 +134,6 @@ typedef guint64 uint64_t;
#include <windows.h>
/* WIN32 special defines */
#define DSOUND_SUPPORT 1
#define WINMIDI_SUPPORT 1
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2

View File

@ -1,7 +1,16 @@
diff --git b/libs/fluidsynth/fluidsynth/synth.h a/libs/fluidsynth/fluidsynth/synth.h
index 1a0046fe1..a4afb9094 100644
index 369a2c261..87826809f 100644
--- b/libs/fluidsynth/fluidsynth/synth.h
+++ a/libs/fluidsynth/fluidsynth/synth.h
@@ -233,7 +233,7 @@ FLUIDSYNTH_API int fluid_synth_tuning_dump(fluid_synth_t *synth, int bank, int p
/* Misc */
FLUIDSYNTH_API double fluid_synth_get_cpu_load(fluid_synth_t *synth);
-FLUID_DEPRECATED FLUIDSYNTH_API const char *fluid_synth_error(fluid_synth_t *synth);
+const char *fluid_synth_error(fluid_synth_t *synth);
/* Default modulators */
@@ -265,7 +265,7 @@ FLUIDSYNTH_API int fluid_synth_write_s16(fluid_synth_t *synth, int len,
FLUIDSYNTH_API int fluid_synth_write_float(fluid_synth_t *synth, int len,
void *lout, int loff, int lincr,
@ -35,6 +44,19 @@ index 47ef18336..5ad29281a 100644
typedef struct _fluid_file_callbacks_t fluid_file_callbacks_t; /**< Callback struct to perform custom file loading of soundfonts */
typedef int fluid_istream_t; /**< Input stream descriptor */
diff --git b/libs/fluidsynth/src/fluid_conv.h a/libs/fluidsynth/src/fluid_conv.h
index 60f441c49..e6455186e 100644
--- b/libs/fluidsynth/src/fluid_conv.h
+++ a/libs/fluidsynth/src/fluid_conv.h
@@ -22,7 +22,7 @@
#define _FLUID_CONV_H
#include "fluidsynth_priv.h"
-#include "utils/fluid_conv_tables.h"
+#include "fluid_conv_tables.h"
fluid_real_t fluid_ct2hz_real(fluid_real_t cents);
fluid_real_t fluid_ct2hz(fluid_real_t cents);
diff --git b/libs/fluidsynth/src/fluid_hash.c a/libs/fluidsynth/src/fluid_hash.c
index 37b0a06a4..b6586895b 100644
--- b/libs/fluidsynth/src/fluid_hash.c
@ -56,7 +78,7 @@ index 37b0a06a4..b6586895b 100644
/*
* fluid_hashtable_foreach_remove_or_steal:
diff --git b/libs/fluidsynth/src/fluid_midi.c a/libs/fluidsynth/src/fluid_midi.c
index c05f994ce..bdf72dd68 100644
index 4795fceb3..b82bfdf61 100644
--- b/libs/fluidsynth/src/fluid_midi.c
+++ a/libs/fluidsynth/src/fluid_midi.c
@@ -75,7 +75,7 @@ static int fluid_midi_file_read_tracklen(fluid_midi_file *mf);
@ -91,7 +113,7 @@ index c05f994ce..bdf72dd68 100644
}
+#endif
diff --git b/libs/fluidsynth/src/fluid_rev.c a/libs/fluidsynth/src/fluid_rev.c
index 8a58d1e85..51b4faa25 100644
index 198a06e58..894afc5a0 100644
--- b/libs/fluidsynth/src/fluid_rev.c
+++ a/libs/fluidsynth/src/fluid_rev.c
@@ -51,7 +51,7 @@ void fluid_allpass_init(fluid_allpass *allpass);
@ -113,22 +135,18 @@ index 8a58d1e85..51b4faa25 100644
{
FLUID_FREE(allpass->buffer);
diff --git b/libs/fluidsynth/src/fluid_rvoice_mixer.c a/libs/fluidsynth/src/fluid_rvoice_mixer.c
index 3b264e4d9..8c5254f26 100644
index af0ef75d1..9e7b164bb 100644
--- b/libs/fluidsynth/src/fluid_rvoice_mixer.c
+++ a/libs/fluidsynth/src/fluid_rvoice_mixer.c
@@ -24,11 +24,9 @@
@@ -24,7 +24,6 @@
#include "fluid_rev.h"
#include "fluid_chorus.h"
#include "fluidsynth_priv.h"
-#include "fluid_ladspa.h"
#include "fluid_synth.h"
-
-#define ENABLE_MIXER_THREADS 1
+#undef ENABLE_MIXER_THREADS // Ardour does the multithreading -- synth.cpu-cores defaults to 1
// If less than x voices, the thread overhead is larger than the gain,
// so don't activate the thread(s).
diff --git b/libs/fluidsynth/src/fluid_rvoice_mixer.h a/libs/fluidsynth/src/fluid_rvoice_mixer.h
index 4ee072e4b..1b3fceb34 100644
--- b/libs/fluidsynth/src/fluid_rvoice_mixer.h
@ -142,7 +160,7 @@ index 4ee072e4b..1b3fceb34 100644
typedef struct _fluid_rvoice_mixer_t fluid_rvoice_mixer_t;
diff --git b/libs/fluidsynth/src/fluid_settings.c a/libs/fluidsynth/src/fluid_settings.c
index d77d5ed79..05423384e 100644
index 02be9a033..9207ab063 100644
--- b/libs/fluidsynth/src/fluid_settings.c
+++ a/libs/fluidsynth/src/fluid_settings.c
@@ -21,9 +21,6 @@
@ -170,7 +188,7 @@ index d77d5ed79..05423384e 100644
static int
diff --git b/libs/fluidsynth/src/fluid_synth.c a/libs/fluidsynth/src/fluid_synth.c
index a40ba2eaa..e8845632f 100644
index faadefb27..79c5a9c87 100644
--- b/libs/fluidsynth/src/fluid_synth.c
+++ a/libs/fluidsynth/src/fluid_synth.c
@@ -267,7 +267,7 @@ void fluid_version(int *major, int *minor, int *micro)
@ -182,7 +200,7 @@ index a40ba2eaa..e8845632f 100644
fluid_version_str(void)
{
return FLUIDSYNTH_VERSION;
@@ -6435,6 +6435,7 @@ int fluid_synth_set_channel_type(fluid_synth_t *synth, int chan, int type)
@@ -6430,6 +6430,7 @@ int fluid_synth_set_channel_type(fluid_synth_t *synth, int chan, int type)
FLUID_API_RETURN(FLUID_OK);
}
@ -190,7 +208,7 @@ index a40ba2eaa..e8845632f 100644
/**
* Return the LADSPA effects instance used by FluidSynth
*
@@ -6447,6 +6448,7 @@ fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth)
@@ -6442,6 +6443,7 @@ fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth)
return synth->ladspa_fx;
}
@ -199,7 +217,7 @@ index a40ba2eaa..e8845632f 100644
/**
* Configure a general-purpose IIR biquad filter.
diff --git b/libs/fluidsynth/src/fluid_synth.h a/libs/fluidsynth/src/fluid_synth.h
index 95e2c2e5f..96dc54574 100644
index 156424af1..58869730c 100644
--- b/libs/fluidsynth/src/fluid_synth.h
+++ a/libs/fluidsynth/src/fluid_synth.h
@@ -33,8 +33,6 @@
@ -222,7 +240,7 @@ index 95e2c2e5f..96dc54574 100644
enum fluid_iir_filter_flags custom_filter_flags; /**< filter type of the user-defined filter currently used for all voices */
};
diff --git b/libs/fluidsynth/src/fluid_sys.c a/libs/fluidsynth/src/fluid_sys.c
index 5a4a2dd93..c9662f778 100644
index 3df88fc23..cce778b3c 100644
--- b/libs/fluidsynth/src/fluid_sys.c
+++ a/libs/fluidsynth/src/fluid_sys.c
@@ -202,9 +202,10 @@ fluid_log(int level, const char *fmt, ...)
@ -252,7 +270,7 @@ index 47cc95c11..d95f6159f 100644
#if defined(__OS2__)
diff --git b/libs/fluidsynth/src/fluidsynth_priv.h a/libs/fluidsynth/src/fluidsynth_priv.h
index 41e398398..d500f6174 100644
index d5dbdf7e9..5de758dc0 100644
--- b/libs/fluidsynth/src/fluidsynth_priv.h
+++ a/libs/fluidsynth/src/fluidsynth_priv.h
@@ -26,10 +26,6 @@
@ -277,4 +295,4 @@ index 41e398398..d500f6174 100644
+#include <windows.h>
/* WIN32 special defines */
#define DSOUND_SUPPORT 1
#define STDIN_FILENO 0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -71,6 +71,7 @@ rsync -auc --info=progress2 \
${FSR}src/synth/fluid_voice.h \
${FSR}src/utils/fluid_conv.c \
${FSR}src/utils/fluid_conv.h \
${FSR}src/utils/fluid_conv_tables.h \
${FSR}src/utils/fluid_hash.c \
${FSR}src/utils/fluid_hash.h \
${FSR}src/utils/fluid_list.c \
@ -102,4 +103,7 @@ rsync -auc --info=progress2 \
"$ASRC/libs/fluidsynth/fluidsynth/"
cd "$ASRC"
patch -p1 < tools/ardour_fluidsynth.diff
patch -p1 < tools/fluid-patches/ardour_fluidsynth.diff
cp tools/fluid-patches/fluid_conv_tables.c libs/fluidsynth/src/
cp tools/fluid-patches/fluid_rvoice_dsp_tables.c libs/fluidsynth/src/