mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-12-03 17:42:21 +00:00
commit
578f3ccbbe
15 changed files with 369 additions and 203 deletions
|
@ -360,3 +360,13 @@ else ( MACOSX_FRAMEWORK )
|
|||
install ( FILES ${public_main_HEADER} DESTINATION ${INCLUDE_INSTALL_DIR} )
|
||||
endif ( MACOSX_FRAMEWORK )
|
||||
|
||||
# ******* Auto Generated Lookup Tables ******
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(gentables
|
||||
DOWNLOAD_COMMAND ""
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/gentables
|
||||
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/gentables
|
||||
INSTALL_COMMAND ${CMAKE_CURRENT_BINARY_DIR}/gentables/make_tables${CMAKE_EXECUTABLE_SUFFIX} "${CMAKE_BINARY_DIR}/"
|
||||
)
|
||||
add_dependencies(libfluidsynth-OBJ gentables)
|
||||
|
|
27
src/gentables/CMakeLists.txt
Normal file
27
src/gentables/CMakeLists.txt
Normal file
|
@ -0,0 +1,27 @@
|
|||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
# remove $CC from the current environment and by that force cmake to look for a (working) C compiler,
|
||||
# which hopefully will be the host compiler
|
||||
unset(ENV{CC})
|
||||
|
||||
project (gentables C)
|
||||
|
||||
set ( CMAKE_BUILD_TYPE Debug )
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../)
|
||||
|
||||
# Add the executable that generates the table
|
||||
add_executable( make_tables
|
||||
make_tables.c
|
||||
gen_conv.c
|
||||
gen_rvoice_dsp.c)
|
||||
|
||||
if ( WIN32 )
|
||||
add_definitions ( -D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS )
|
||||
else ( WIN32 )
|
||||
target_link_libraries (make_tables "m")
|
||||
endif ()
|
81
src/gentables/gen_conv.c
Normal file
81
src/gentables/gen_conv.c
Normal file
|
@ -0,0 +1,81 @@
|
|||
|
||||
#include "utils/fluid_conv_tables.h"
|
||||
#include "make_tables.h"
|
||||
|
||||
|
||||
/* conversion tables */
|
||||
static double fluid_ct2hz_tab[FLUID_CENTS_HZ_SIZE];
|
||||
static double fluid_cb2amp_tab[FLUID_CB_AMP_SIZE];
|
||||
static double fluid_concave_tab[FLUID_VEL_CB_SIZE];
|
||||
static double fluid_convex_tab[FLUID_VEL_CB_SIZE];
|
||||
static double fluid_pan_tab[FLUID_PAN_SIZE];
|
||||
|
||||
/*
|
||||
* void fluid_synth_init
|
||||
*
|
||||
* Does all the initialization for this module.
|
||||
*/
|
||||
static void fluid_conversion_config(void)
|
||||
{
|
||||
int i;
|
||||
double x;
|
||||
|
||||
for(i = 0; i < FLUID_CENTS_HZ_SIZE; i++)
|
||||
{
|
||||
fluid_ct2hz_tab[i] = 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] = 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((double)(i * i) / ((FLUID_VEL_CB_SIZE - 1) * (FLUID_VEL_CB_SIZE - 1))) / M_LN10;
|
||||
fluid_convex_tab[i] = (1.0 - x);
|
||||
fluid_concave_tab[(FLUID_VEL_CB_SIZE - 1) - i] = 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] = sin(i * x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gen_conv_table(FILE *fp)
|
||||
{
|
||||
/* Calculate the values */
|
||||
fluid_conversion_config();
|
||||
|
||||
/* fluid_ct2hz_tab */
|
||||
EMIT_ARRAY(fp, fluid_ct2hz_tab);
|
||||
EMIT_ARRAY(fp, fluid_cb2amp_tab);
|
||||
EMIT_ARRAY(fp, fluid_concave_tab);
|
||||
EMIT_ARRAY(fp, fluid_convex_tab);
|
||||
EMIT_ARRAY(fp, fluid_pan_tab);
|
||||
}
|
||||
|
81
src/gentables/gen_rvoice_dsp.c
Normal file
81
src/gentables/gen_rvoice_dsp.c
Normal file
|
@ -0,0 +1,81 @@
|
|||
|
||||
#include "rvoice/fluid_rvoice_dsp_tables.h"
|
||||
#include "make_tables.h"
|
||||
|
||||
/* Linear interpolation table (2 coefficients centered on 1st) */
|
||||
static double interp_coeff_linear[FLUID_INTERP_MAX][2];
|
||||
|
||||
/* 4th order (cubic) interpolation table (4 coefficients centered on 2nd) */
|
||||
static double interp_coeff[FLUID_INTERP_MAX][4];
|
||||
|
||||
/* 7th order interpolation (7 coefficients centered on 3rd) */
|
||||
static double sinc_table7[FLUID_INTERP_MAX][SINC_INTERP_ORDER];
|
||||
|
||||
static double cb_interp_coeff_linear(int y, int x) { return interp_coeff_linear[y][x]; }
|
||||
static double cb_interp_coeff (int y, int x) { return interp_coeff[y][x]; }
|
||||
static double cb_sinc_table7 (int y, int x) { return sinc_table7[y][x]; }
|
||||
|
||||
/* 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] = (x * (-0.5 + x * (1 - 0.5 * x)));
|
||||
interp_coeff[i][1] = (1.0 + x * x * (1.5 * x - 2.5));
|
||||
interp_coeff[i][2] = (x * (0.5 + x * (2.0 - 1.5 * x)));
|
||||
interp_coeff[i][3] = (0.5 * x * x * (x - 1.0));
|
||||
|
||||
interp_coeff_linear[i][0] = (1.0 - x);
|
||||
interp_coeff_linear[i][1] = 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 = sin(arg) / (arg);
|
||||
/* Hanning window */
|
||||
v *= 0.5 * (1.0 + cos(2.0 * arg / (double)SINC_INTERP_ORDER));
|
||||
}
|
||||
else
|
||||
{
|
||||
v = 1.0;
|
||||
}
|
||||
|
||||
sinc_table7[FLUID_INTERP_MAX - i2 - 1][i] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gen_rvoice_table_dsp (FILE *fp)
|
||||
{
|
||||
/* Calculate the values */
|
||||
fluid_rvoice_dsp_config();
|
||||
|
||||
/* Emit the matrices */
|
||||
emit_matrix(fp, "interp_coeff_linear", cb_interp_coeff_linear, FLUID_INTERP_MAX, 2);
|
||||
emit_matrix(fp, "interp_coeff", cb_interp_coeff, FLUID_INTERP_MAX, 4);
|
||||
emit_matrix(fp, "sinc_table7", cb_sinc_table7, FLUID_INTERP_MAX, 7);
|
||||
}
|
84
src/gentables/make_tables.c
Normal file
84
src/gentables/make_tables.c
Normal file
|
@ -0,0 +1,84 @@
|
|||
|
||||
#include "make_tables.h"
|
||||
|
||||
static void write_value(FILE *fp, double val, int i)
|
||||
{
|
||||
fprintf(fp, " %.15e%c /* %d */\n",
|
||||
val,
|
||||
',',
|
||||
i
|
||||
);
|
||||
}
|
||||
|
||||
/* Emit an array of real numbers */
|
||||
void emit_array(FILE *fp, const char *tblname, const double *tbl, int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(fp, "static const fluid_real_t %s[%d] = {\n", tblname, size);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
write_value(fp, tbl[i], i);
|
||||
}
|
||||
fprintf(fp, "};\n\n");
|
||||
}
|
||||
|
||||
/* Emit a matrix of real numbers */
|
||||
void emit_matrix(FILE *fp, const char *tblname, emit_matrix_cb tbl_cb, int sizeh, int sizel)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
fprintf(fp, "static const fluid_real_t %s[%d][%d] = {\n {\n", tblname, sizeh, sizel);
|
||||
|
||||
for (i = 0; i < sizeh; i++)
|
||||
{
|
||||
for (j = 0; j < sizel; j++)
|
||||
{
|
||||
write_value(fp, tbl_cb(i, j), i*sizel+j);
|
||||
}
|
||||
|
||||
|
||||
if (i < (sizeh-1))
|
||||
fprintf(fp, " }, {\n");
|
||||
else
|
||||
fprintf(fp, " }\n};\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void open_table(FILE**fp, const char* dir, const char* file)
|
||||
{
|
||||
char buf[2048] = {0};
|
||||
|
||||
strcat(buf, dir);
|
||||
strcat(buf, file);
|
||||
|
||||
/* open the output file */
|
||||
*fp = fopen(buf, "w");
|
||||
if (*fp == NULL)
|
||||
{
|
||||
exit(-2);
|
||||
}
|
||||
|
||||
/* Emit warning header */
|
||||
fprintf(*fp, "/* THIS FILE HAS BEEN AUTOMATICALLY GENERATED. DO NOT EDIT. */\n\n");
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
// make sure we have enough arguments
|
||||
if (argc < 2)
|
||||
return -1;
|
||||
|
||||
open_table(&fp, argv[1], "fluid_conv_tables.c");
|
||||
gen_conv_table(fp);
|
||||
fclose(fp);
|
||||
|
||||
open_table(&fp, argv[1], "fluid_rvoice_dsp_tables.c");
|
||||
gen_rvoice_table_dsp(fp);
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
21
src/gentables/make_tables.h
Normal file
21
src/gentables/make_tables.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define EMIT_ARRAY(__fp__, __arr__) emit_array(__fp__, #__arr__, __arr__, sizeof(__arr__)/sizeof(*__arr__))
|
||||
|
||||
/* callback for general access to matrices */
|
||||
typedef double (*emit_matrix_cb)(int y, int x);
|
||||
|
||||
/* Generators */
|
||||
void gen_rvoice_table_dsp(FILE *fp);
|
||||
void gen_conv_table(FILE *fp);
|
||||
|
||||
/* Emit an array of real numbers */
|
||||
void emit_array(FILE *fp, const char *tblname, const double *tbl, int size);
|
||||
|
||||
/* Emit a matrix of real numbers */
|
||||
void emit_matrix(FILE *fp, const char *tblname, emit_matrix_cb tbl_cb, int sizeh, int sizel);
|
||||
|
|
@ -2225,7 +2225,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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
8
src/rvoice/fluid_rvoice_dsp_tables.h
Normal file
8
src/rvoice/fluid_rvoice_dsp_tables.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
#ifndef _FLUID_RVOICE_DSP_TABLES_H
|
||||
#define _FLUID_RVOICE_DSP_TABLES_H
|
||||
|
||||
#define FLUID_INTERP_MAX 256
|
||||
#define SINC_INTERP_ORDER 7 /* 7th order constant */
|
||||
|
||||
#endif
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -285,10 +285,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.
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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 "utils/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);
|
||||
|
|
41
src/utils/fluid_conv_tables.h
Normal file
41
src/utils/fluid_conv_tables.h
Normal 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
|
Loading…
Reference in a new issue