Merge pull request #301 from FluidSynth/sm24

add 24 bit sample support
This commit is contained in:
Tom M 2017-12-14 16:47:04 +01:00 committed by GitHub
commit af0301ae3b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 256 additions and 130 deletions

1
TODO
View file

@ -1,6 +1,5 @@
New features
------------
- 24 bit sample support
- Non-realtime MIDI file rendering
- Sample streaming, load/unload sample on demand
- Synth sample rate change after initial creation

View file

@ -114,6 +114,7 @@ Changes in FluidSynth 2.0.0 concerning developers:
- add seek support to midi-player, see fluid_player_seek()
- expose functions to manipulate the ladspa effects unit (see ladspa.h)
- add support for text and lyrics midi events, see fluid_midi_event_set_lyrics() and fluid_midi_event_set_text()
- add 24 bit sample support, see _fluid_sample_t::data24
\section NewIn1_1_9 Whats new in 1.1.9?

View file

@ -297,7 +297,8 @@ struct _fluid_sample_t
int pitchadj; /**< Fine pitch adjustment (+/- 99 cents) */
int sampletype; /**< Specifies the type of this sample as indicated by the #fluid_sample_type enum */
int valid; /**< Should be TRUE if sample data is valid, FALSE otherwise (in which case it will not be synthesized) */
short* data; /**< Pointer to the sample's data */
short* data; /**< Pointer to the sample's 16 bit PCM data */
char* data24; /**< If not NULL, pointer to the least significant byte counterparts of each sample data point in order to create 24 bit audio samples */
int amplitude_that_reaches_noise_floor_is_valid; /**< Indicates if \a amplitude_that_reaches_noise_floor is valid (TRUE), set to FALSE initially to calculate. */
double amplitude_that_reaches_noise_floor; /**< The amplitude at which the sample's loop will be below the noise floor. For voice off optimization, calculated automatically. */

View file

@ -119,6 +119,28 @@ void fluid_rvoice_dsp_config (void)
fluid_check_fpe("interpolation table calculation");
}
/*
* Combines the most significant 16 bit part of a sample with a potentially present
* least sig. 8 bit part in order to create a 24 bit sample.
*/
static FLUID_INLINE fluid_real_t
fluid_rvoice_get_sample(const short int* dsp_msb, const char* dsp_lsb, unsigned int idx)
{
/* cast sample to unsigned type, so we can safely shift and bitwise or
* without relying on undefined behaviour (should never happen anyway ofc...) */
uint32_t msb = (uint32_t)dsp_msb[idx];
uint8_t lsb = 0U;
/* most soundfonts have 16 bit samples, assume that it's unlikely we
* experience 24 bit samples here */
if(G_UNLIKELY(dsp_lsb != NULL))
{
lsb = (uint8_t)dsp_lsb[idx];
}
return (fluid_real_t)((int32_t)((msb << 8) | lsb));
}
/* No interpolation. Just take the sample, which is closest to
* the playback pointer. Questionable quality, but very
* efficient. */
@ -128,6 +150,7 @@ fluid_rvoice_dsp_interpolate_none (fluid_rvoice_dsp_t *voice)
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
char *dsp_data24 = voice->sample->data24;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
@ -151,7 +174,7 @@ fluid_rvoice_dsp_interpolate_none (fluid_rvoice_dsp_t *voice)
/* interpolate sequence of sample points */
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
{
dsp_buf[dsp_i] = dsp_amp * dsp_data[dsp_phase_index];
dsp_buf[dsp_i] = dsp_amp * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -189,13 +212,14 @@ fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice)
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
char *dsp_data24 = voice->sample->data24;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int end_index;
short int point;
fluid_real_t point;
fluid_real_t *coeffs;
int looping;
@ -209,8 +233,8 @@ fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice)
end_index = (looping ? voice->loopend - 1 : voice->end) - 1;
/* 2nd interpolation point to use at end of loop or sample */
if (looping) point = dsp_data[voice->loopstart]; /* loop start */
else point = dsp_data[voice->end]; /* duplicate end for samples no longer looping */
if (looping) point = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopstart); /* loop start */
else point = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->end); /* duplicate end for samples no longer looping */
while (1)
{
@ -220,8 +244,8 @@ fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice)
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
{
coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index]
+ coeffs[1] * dsp_data[dsp_phase_index+1]);
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[1] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+1));
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -238,8 +262,8 @@ fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice)
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index]
+ coeffs[1] * point);
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[1] * point);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -278,13 +302,14 @@ fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice)
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
char *dsp_data24 = voice->sample->data24;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int start_index, end_index;
short int start_point, end_point1, end_point2;
fluid_real_t start_point, end_point1, end_point2;
fluid_real_t *coeffs;
int looping;
@ -300,23 +325,23 @@ fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice)
if (voice->has_looped) /* set start_index and start point if looped or not */
{
start_index = voice->loopstart;
start_point = dsp_data[voice->loopend - 1]; /* last point in loop (wrap around) */
start_point = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopend - 1); /* last point in loop (wrap around) */
}
else
{
start_index = voice->start;
start_point = dsp_data[voice->start]; /* just duplicate the point */
start_point = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->start); /* just duplicate the point */
}
/* get points off the end (loop start if looping, duplicate point if end) */
if (looping)
{
end_point1 = dsp_data[voice->loopstart];
end_point2 = dsp_data[voice->loopstart + 1];
end_point1 = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopstart);
end_point2 = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopstart + 1);
}
else
{
end_point1 = dsp_data[voice->end];
end_point1 = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->end);
end_point2 = end_point1;
}
@ -328,10 +353,11 @@ fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice)
for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * start_point
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * dsp_data[dsp_phase_index+2]);
dsp_buf[dsp_i] = dsp_amp *
( coeffs[0] * start_point
+ coeffs[1] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[2] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+1)
+ coeffs[3] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+2));
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -343,10 +369,11 @@ fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice)
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
{
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * dsp_data[dsp_phase_index+2]);
dsp_buf[dsp_i] = dsp_amp *
( coeffs[0] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-1)
+ coeffs[1] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[2] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+1)
+ coeffs[3] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+2));
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -363,10 +390,11 @@ fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice)
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * end_point1);
dsp_buf[dsp_i] = dsp_amp *
( coeffs[0] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-1)
+ coeffs[1] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[2] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+1)
+ coeffs[3] * end_point1);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -380,10 +408,11 @@ fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice)
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * end_point1
+ coeffs[3] * end_point2);
dsp_buf[dsp_i] = dsp_amp *
( coeffs[0] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-1)
+ coeffs[1] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[2] * end_point1
+ coeffs[3] * end_point2);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -402,7 +431,7 @@ fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice)
{
voice->has_looped = 1;
start_index = voice->loopstart;
start_point = dsp_data[voice->loopend - 1];
start_point = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopend-1);
}
}
@ -428,14 +457,14 @@ fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
char *dsp_data24 = voice->sample->data24;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int start_index, end_index;
short int start_points[3];
short int end_points[3];
fluid_real_t start_points[3], end_points[3];
fluid_real_t *coeffs;
int looping;
@ -455,14 +484,14 @@ fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
if (voice->has_looped) /* set start_index and start point if looped or not */
{
start_index = voice->loopstart;
start_points[0] = dsp_data[voice->loopend - 1];
start_points[1] = dsp_data[voice->loopend - 2];
start_points[2] = dsp_data[voice->loopend - 3];
start_points[0] = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopend - 1);
start_points[1] = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopend - 2);
start_points[2] = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopend - 3);
}
else
{
start_index = voice->start;
start_points[0] = dsp_data[voice->start]; /* just duplicate the start point */
start_points[0] = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->start); /* just duplicate the start point */
start_points[1] = start_points[0];
start_points[2] = start_points[0];
}
@ -470,13 +499,13 @@ fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
/* get the 3 points off the end (loop start if looping, duplicate point if end) */
if (looping)
{
end_points[0] = dsp_data[voice->loopstart];
end_points[1] = dsp_data[voice->loopstart + 1];
end_points[2] = dsp_data[voice->loopstart + 2];
end_points[0] = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopstart);
end_points[1] = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopstart + 1);
end_points[2] = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopstart + 2);
}
else
{
end_points[0] = dsp_data[voice->end];
end_points[0] = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->end);
end_points[1] = end_points[0];
end_points[2] = end_points[0];
}
@ -491,13 +520,13 @@ fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)start_points[2]
+ coeffs[1] * (fluid_real_t)start_points[1]
+ coeffs[2] * (fluid_real_t)start_points[0]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
* (coeffs[0] * start_points[2]
+ coeffs[1] * start_points[1]
+ coeffs[2] * start_points[0]
+ coeffs[3] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+1)
+ coeffs[5] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+2)
+ coeffs[6] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+3));
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -513,13 +542,13 @@ fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)start_points[1]
+ coeffs[1] * (fluid_real_t)start_points[0]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
* (coeffs[0] * start_points[1]
+ coeffs[1] * start_points[0]
+ coeffs[2] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-1)
+ coeffs[3] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+1)
+ coeffs[5] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+2)
+ coeffs[6] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+3));
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -535,13 +564,13 @@ fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)start_points[0]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
* (coeffs[0] * start_points[0]
+ coeffs[1] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-2)
+ coeffs[2] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-1)
+ coeffs[3] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+1)
+ coeffs[5] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+2)
+ coeffs[6] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+3));
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -558,13 +587,13 @@ fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
* (coeffs[0] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-3)
+ coeffs[1] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-2)
+ coeffs[2] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-1)
+ coeffs[3] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+1)
+ coeffs[5] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+2)
+ coeffs[6] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+3));
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -583,13 +612,13 @@ fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)end_points[0]);
* (coeffs[0] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-3)
+ coeffs[1] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-2)
+ coeffs[2] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-1)
+ coeffs[3] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+1)
+ coeffs[5] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+2)
+ coeffs[6] * end_points[0]);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -605,13 +634,13 @@ fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)end_points[0]
+ coeffs[6] * (fluid_real_t)end_points[1]);
* (coeffs[0] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-3)
+ coeffs[1] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-2)
+ coeffs[2] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-1)
+ coeffs[3] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index+1)
+ coeffs[5] * end_points[0]
+ coeffs[6] * end_points[1]);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -627,13 +656,13 @@ fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)end_points[0]
+ coeffs[5] * (fluid_real_t)end_points[1]
+ coeffs[6] * (fluid_real_t)end_points[2]);
* (coeffs[0] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-3)
+ coeffs[1] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-2)
+ coeffs[2] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index-1)
+ coeffs[3] * fluid_rvoice_get_sample(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[4] * end_points[0]
+ coeffs[5] * end_points[1]
+ coeffs[6] * end_points[2]);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
@ -652,9 +681,9 @@ fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
{
voice->has_looped = 1;
start_index = voice->loopstart;
start_points[0] = dsp_data[voice->loopend - 1];
start_points[1] = dsp_data[voice->loopend - 2];
start_points[2] = dsp_data[voice->loopend - 3];
start_points[0] = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopend - 1);
start_points[1] = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopend - 2);
start_points[2] = fluid_rvoice_get_sample(dsp_data, dsp_data24, voice->loopend - 3);
}
}

View file

@ -275,8 +275,11 @@ typedef struct _fluid_cached_sampledata_t {
int num_references;
int mlock;
const short* sampledata;
short* sampledata;
unsigned int samplesize;
char* sample24data;
unsigned int sample24size;
} fluid_cached_sampledata_t;
static fluid_cached_sampledata_t* all_cached_sampledata = NULL;
@ -299,11 +302,19 @@ static int fluid_get_file_modification_time(char *filename, time_t *modification
#endif
}
static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos,
unsigned int samplesize, short **sampledata, int try_mlock, const fluid_file_callbacks_t* fcbs)
static int fluid_cached_sampledata_load(char *filename,
unsigned int samplepos,
unsigned int samplesize,
short **sampledata,
unsigned int sample24pos,
unsigned int sample24size,
char **sample24data,
int try_mlock,
const fluid_file_callbacks_t* fcbs)
{
fluid_file fd = NULL;
short *loaded_sampledata = NULL;
char *loaded_sample24data = NULL;
fluid_cached_sampledata_t* cached_sampledata = NULL;
time_t modification_time;
@ -319,7 +330,7 @@ static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos,
continue;
if (cached_sampledata->modification_time != modification_time)
continue;
if (cached_sampledata->samplesize != samplesize) {
if (cached_sampledata->samplesize != samplesize || cached_sampledata->sample24size != sample24size) {
FLUID_LOG(FLUID_ERR, "Cached size of soundfont doesn't match actual size of soundfont (cached: %u. actual: %u)",
cached_sampledata->samplesize, samplesize);
continue;
@ -330,10 +341,15 @@ static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos,
FLUID_LOG(FLUID_WARN, "Failed to pin the sample data to RAM; swapping is possible.");
else
cached_sampledata->mlock = try_mlock;
if (cached_sampledata->sample24data != NULL)
if(fluid_mlock(cached_sampledata->sample24data, sample24size) != 0)
FLUID_LOG(FLUID_WARN, "Failed to pin the sample24 data to RAM; swapping is possible.");
}
cached_sampledata->num_references++;
loaded_sampledata = (short*) cached_sampledata->sampledata;
loaded_sampledata = cached_sampledata->sampledata;
loaded_sample24data = cached_sampledata->sample24data;
goto success_exit;
}
@ -348,7 +364,6 @@ static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos,
goto error_exit;
}
loaded_sampledata = (short*) FLUID_MALLOC(samplesize);
if (loaded_sampledata == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory");
@ -359,6 +374,25 @@ static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos,
goto error_exit;
}
if(sample24pos > 0)
{
if (fcbs->fseek(fd, sample24pos, SEEK_SET) == FLUID_FAILED) {
perror("error");
FLUID_LOG(FLUID_ERR, "Failed to seek position in data file");
goto error_exit;
}
loaded_sample24data = (char*) FLUID_MALLOC(sample24size);
if (loaded_sample24data == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory when allocating 24bit sample, ignoring");
}
else if (fcbs->fread(loaded_sample24data, sample24size, fd) == FLUID_FAILED) {
FLUID_LOG(FLUID_ERR, "Failed to read sample24 data");
FLUID_FREE(loaded_sample24data);
loaded_sample24data = NULL;
}
}
fcbs->fclose(fd);
fd = NULL;
@ -370,7 +404,7 @@ static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos,
}
/* Lock the memory to disable paging. It's okay if this fails. It
probably means that the user doesn't have to required permission. */
probably means that the user doesn't have the required permission. */
cached_sampledata->mlock = 0;
if (try_mlock) {
if (fluid_mlock(loaded_sampledata, samplesize) != 0)
@ -394,17 +428,18 @@ static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos,
}
}
cached_sampledata->filename = (char*) FLUID_MALLOC(strlen(filename) + 1);
cached_sampledata->filename = FLUID_STRDUP(filename);
if (cached_sampledata->filename == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory.");
goto error_exit;
}
sprintf(cached_sampledata->filename, "%s", filename);
cached_sampledata->modification_time = modification_time;
cached_sampledata->num_references = 1;
cached_sampledata->sampledata = loaded_sampledata;
cached_sampledata->samplesize = samplesize;
cached_sampledata->sample24data = loaded_sample24data;
cached_sampledata->sample24size = sample24size;
cached_sampledata->next = all_cached_sampledata;
all_cached_sampledata = cached_sampledata;
@ -413,25 +448,25 @@ static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos,
success_exit:
fluid_mutex_unlock(cached_sampledata_mutex);
*sampledata = loaded_sampledata;
*sample24data = loaded_sample24data;
return FLUID_OK;
error_exit:
if (fd != NULL) {
fcbs->fclose(fd);
}
if (loaded_sampledata != NULL) {
FLUID_FREE(loaded_sampledata);
}
FLUID_FREE(loaded_sampledata);
FLUID_FREE(loaded_sample24data);
if (cached_sampledata != NULL) {
if (cached_sampledata->filename != NULL) {
FLUID_FREE(cached_sampledata->filename);
}
FLUID_FREE(cached_sampledata);
}
FLUID_FREE(cached_sampledata);
fluid_mutex_unlock(cached_sampledata_mutex);
*sampledata = NULL;
*sample24data = NULL;
return FLUID_FAILED;
}
@ -450,8 +485,12 @@ static int fluid_cached_sampledata_unload(const short *sampledata)
if (cached_sampledata->num_references == 0) {
if (cached_sampledata->mlock)
{
fluid_munlock(cached_sampledata->sampledata, cached_sampledata->samplesize);
FLUID_FREE((short*) cached_sampledata->sampledata);
fluid_munlock(cached_sampledata->sample24data, cached_sampledata->sample24size);
}
FLUID_FREE(cached_sampledata->sampledata);
FLUID_FREE(cached_sampledata->sample24data);
FLUID_FREE(cached_sampledata->filename);
if (prev != NULL) {
@ -504,12 +543,8 @@ fluid_defsfont_t* new_fluid_defsfont(fluid_settings_t* settings)
return NULL;
}
sfont->filename = NULL;
sfont->samplepos = 0;
sfont->samplesize = 0;
sfont->sample = NULL;
sfont->sampledata = NULL;
sfont->preset = NULL;
FLUID_MEMSET(sfont, 0, sizeof(*sfont));
fluid_settings_getint(settings, "synth.lock-memory", &sfont->mlock);
/* Initialise preset cache, so we don't have to call malloc on program changes.
@ -517,7 +552,7 @@ fluid_defsfont_t* new_fluid_defsfont(fluid_settings_t* settings)
so optimise for that case. */
fluid_settings_getint(settings, "synth.midi-channels", &sfont->preset_stack_capacity);
sfont->preset_stack_capacity++;
sfont->preset_stack_size = 0;
sfont->preset_stack = FLUID_ARRAY(fluid_preset_t*, sfont->preset_stack_capacity);
if (!sfont->preset_stack) {
FLUID_LOG(FLUID_ERR, "Out of memory");
@ -627,6 +662,8 @@ int fluid_defsfont_load(fluid_defsfont_t* sfont, const fluid_file_callbacks_t* f
it's loaded separately (and might be unoaded/reloaded in future) */
sfont->samplepos = sfdata->samplepos;
sfont->samplesize = sfdata->samplesize;
sfont->sample24pos = sfdata->sample24pos;
sfont->sample24size = sfdata->sample24size;
/* load sample data in one block */
if (fluid_defsfont_load_sampledata(sfont, fcbs) != FLUID_OK)
@ -725,8 +762,11 @@ int fluid_defsfont_add_preset(fluid_defsfont_t* sfont, fluid_defpreset_t* preset
int
fluid_defsfont_load_sampledata(fluid_defsfont_t* sfont, const fluid_file_callbacks_t* fcbs)
{
return fluid_cached_sampledata_load(sfont->filename, sfont->samplepos,
sfont->samplesize, &sfont->sampledata, sfont->mlock, fcbs);
return fluid_cached_sampledata_load(sfont->filename,
sfont->samplepos, sfont->samplesize, &sfont->sampledata,
sfont->sample24pos, sfont->sample24size, &sfont->sample24data,
sfont->mlock,
fcbs);
}
/*
@ -1936,6 +1976,7 @@ fluid_sample_import_sfont(fluid_sample_t* sample, SFSample* sfsample, fluid_defs
{
FLUID_STRCPY(sample->name, sfsample->name);
sample->data = sfont->sampledata;
sample->data24 = sfont->sample24data;
sample->start = sfsample->start;
sample->end = sfsample->start + sfsample->end;
sample->loopstart = sfsample->start + sfsample->loopstart;
@ -2155,11 +2196,9 @@ static int fixup_sample (SFData * sf);
static const char idlist[] = {
"RIFFLISTsfbkINFOsdtapdtaifilisngINAMiromiverICRDIENGIPRD"
"ICOPICMTISFTsnamsmplphdrpbagpmodpgeninstibagimodigenshdr"
"ICOPICMTISFTsnamsmplphdrpbagpmodpgeninstibagimodigenshdrsm24"
};
static unsigned int sdtachunk_size;
/* sound font file load functions */
static int
chunkid (unsigned int id)
@ -2429,9 +2468,50 @@ process_sdta (unsigned int size, SFData * sf, void * fd, const fluid_file_callba
sf->samplepos = fcbs->ftell (fd);
/* used in fixup_sample() to check validity of sample headers */
sdtachunk_size = chunk.size;
sf->samplesize = chunk.size;
FSKIP (chunk.size, fd, fcbs);
size -= chunk.size;
if(sf->version.major >= 2 && sf->version.minor >= 4)
{
/* any chance to find another chunk here? */
if(size > 8)
{
/* read sub chunk */
READCHUNK (&chunk, fd, fcbs);
size -= 8;
if (chunkid (chunk.id) == SM24_ID)
{
int sm24size, sdtahalfsize;
FLUID_LOG(FLUID_DBG, "Found SM24 chunk");
if (chunk.size > size)
{
FLUID_LOG(FLUID_WARN, "SM24 exeeds SDTA chunk, ignoring SM24");
goto ret; // no error
}
sdtahalfsize = sf->samplesize/2;
/* + 1 byte in the case that half the size of smpl chunk is an odd value */
sdtahalfsize += sdtahalfsize%2;
sm24size = chunk.size;
if (sdtahalfsize != sm24size)
{
FLUID_LOG(FLUID_WARN, "SM24 not equal to half the size of SMPL chunk (0x%X != 0x%X), ignoring SM24", sm24size, sdtahalfsize);
goto ret; // no error
}
/* sample data24 follows */
sf->sample24pos = fcbs->ftell (fd);
sf->sample24size = sm24size;
}
}
}
ret:
FSKIP (size, fd, fcbs);
return (OK);
@ -3352,6 +3432,7 @@ fixup_sample (SFData * sf)
int invalid_loops=FALSE;
int invalid_loopstart;
int invalid_loopend, loopend_end_mismatch;
unsigned int sdtachunk_size = sf->samplesize;
p = sf->sample;
while (p)

View file

@ -143,8 +143,13 @@ typedef struct _SFData
{ /* Sound font data structure */
SFVersion version; /* sound font version */
SFVersion romver; /* ROM version */
unsigned int samplepos; /* position within sffd of the sample chunk */
unsigned int samplesize; /* length within sffd of the sample chunk */
unsigned int sample24pos; /* position within sffd of the sm24 chunk, set to zero if no 24 bit sample support */
unsigned int sample24size; /* length within sffd of the sm24 chunk */
char *fname; /* file name */
FILE *sffd; /* loaded sfont file descriptor */
fluid_list_t *info; /* linked list of info strings (1st byte is ID) */
@ -166,7 +171,8 @@ enum
SNAM_ID, SMPL_ID, /* sample ids */
PHDR_ID, PBAG_ID, PMOD_ID, PGEN_ID, /* preset ids */
IHDR_ID, IBAG_ID, IMOD_ID, IGEN_ID, /* instrument ids */
SHDR_ID /* sample info */
SHDR_ID, /* sample info */
SM24_ID
};
/* generator types */
@ -370,13 +376,17 @@ struct _fluid_defsfont_t
{
char* filename; /* the filename of this soundfont */
unsigned int samplepos; /* the position in the file at which the sample data starts */
unsigned int samplesize; /* the size of the sample data */
unsigned int samplesize; /* the size of the sample data in bytes */
short* sampledata; /* the sample data, loaded in ram */
unsigned int sample24pos; /* position within sffd of the sm24 chunk, set to zero if no 24 bit sample support */
unsigned int sample24size; /* length within sffd of the sm24 chunk */
char* sample24data; /* if not NULL, the least significant byte of the 24bit sample data, loaded in ram */
fluid_list_t* sample; /* the samples in this soundfont */
fluid_defpreset_t* preset; /* the presets of this soundfont */
int mlock; /* Should we try memlock (avoid swapping)? */
fluid_preset_t iter_preset; /* preset interface used in the iteration */
fluid_defpreset_t* iter_cur; /* the current preset in the iteration */
fluid_preset_t** preset_stack; /* List of presets that are available to use */

View file

@ -436,9 +436,14 @@ void fluid_voice_start(fluid_voice_t* voice)
* @param gain The gain value in the range [0.0 ; 1.0]
* @return An amplitude used by rvoice_mixer's buffers
*/
static fluid_real_t fluid_voice_calculate_gain_amplitude(const fluid_voice_t* voice, fluid_real_t gain)
static FLUID_INLINE fluid_real_t
fluid_voice_calculate_gain_amplitude(const fluid_voice_t* voice, fluid_real_t gain)
{
return gain * voice->synth_gain / 32768.0f;
/* we use 24bit samples in fluid_rvoice_dsp. in order to normalize float
* samples to [0.0;1.0] divide samples by the max. value of an int24 and
* amplify them with the gain */
const fluid_real_t INT24_MAX = (1 << (16+8-1)) * 1.0f;
return gain * voice->synth_gain / INT24_MAX;
}
void