mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2025-03-03 07:51:45 +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} )
|
install ( FILES ${public_main_HEADER} DESTINATION ${INCLUDE_INSTALL_DIR} )
|
||||||
endif ( MACOSX_FRAMEWORK )
|
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)
|
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
|
#ifndef _FLUID_PHASE_H
|
||||||
#define _FLUID_PHASE_H
|
#define _FLUID_PHASE_H
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* phase
|
* phase
|
||||||
*/
|
*/
|
||||||
|
@ -31,7 +29,7 @@
|
||||||
#define FLUID_INTERP_BITS 8
|
#define FLUID_INTERP_BITS 8
|
||||||
#define FLUID_INTERP_BITS_MASK 0xff000000
|
#define FLUID_INTERP_BITS_MASK 0xff000000
|
||||||
#define FLUID_INTERP_BITS_SHIFT 24
|
#define FLUID_INTERP_BITS_SHIFT 24
|
||||||
#define FLUID_INTERP_MAX 256
|
|
||||||
|
|
||||||
#define FLUID_FRACT_MAX ((double)4294967296.0)
|
#define FLUID_FRACT_MAX ((double)4294967296.0)
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "fluid_phase.h"
|
#include "fluid_phase.h"
|
||||||
#include "fluid_rvoice.h"
|
#include "fluid_rvoice.h"
|
||||||
#include "fluid_sys.h"
|
#include "fluid_sys.h"
|
||||||
|
#include "fluid_rvoice_dsp_tables.c"
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
*
|
*
|
||||||
|
@ -47,85 +48,6 @@
|
||||||
|
|
||||||
/* Interpolation (find a value between two samples of the original waveform) */
|
/* 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
|
static FLUID_INLINE fluid_real_t
|
||||||
fluid_rvoice_get_float_sample(const short int *dsp_msb, const char *dsp_lsb, unsigned int idx)
|
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 fluid_gen_scale_nrpn(int gen, int data)
|
||||||
{
|
{
|
||||||
fluid_real_t value = (float) data - 8192.0f;
|
data = data - 8192;
|
||||||
fluid_clip(value, -8192, 8192);
|
fluid_clip(data, -8192, 8192);
|
||||||
return value * (float) fluid_gen_info[gen].nrpn_scale;
|
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);
|
feenableexcept(FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fluid_conversion_config();
|
|
||||||
|
|
||||||
fluid_rvoice_dsp_config();
|
|
||||||
|
|
||||||
init_dither();
|
init_dither();
|
||||||
|
|
||||||
/* custom_breath2att_mod is not a default modulator specified in SF2.01.
|
/* custom_breath2att_mod is not a default modulator specified in SF2.01.
|
||||||
|
|
|
@ -19,74 +19,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fluid_conv.h"
|
#include "fluid_conv.h"
|
||||||
|
#include "fluid_conv_tables.c"
|
||||||
#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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_ct2hz
|
* fluid_ct2hz
|
||||||
|
@ -299,6 +232,13 @@ fluid_tc2sec_release(fluid_real_t tc)
|
||||||
* fluid_act2hz
|
* fluid_act2hz
|
||||||
*
|
*
|
||||||
* Convert from absolute cents to Hertz
|
* 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_real_t
|
||||||
fluid_act2hz(fluid_real_t c)
|
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));
|
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
|
* fluid_pan
|
||||||
*/
|
*/
|
||||||
|
@ -407,3 +336,4 @@ fluid_convex(fluid_real_t val)
|
||||||
|
|
||||||
return fluid_convex_tab[(int) val];
|
return fluid_convex_tab[(int) val];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,39 +22,7 @@
|
||||||
#define _FLUID_CONV_H
|
#define _FLUID_CONV_H
|
||||||
|
|
||||||
#include "fluidsynth_priv.h"
|
#include "fluidsynth_priv.h"
|
||||||
|
#include "utils/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
|
|
||||||
|
|
||||||
void fluid_conversion_config(void);
|
|
||||||
|
|
||||||
fluid_real_t fluid_ct2hz_real(fluid_real_t cents);
|
fluid_real_t fluid_ct2hz_real(fluid_real_t cents);
|
||||||
fluid_real_t fluid_ct2hz(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_attack(fluid_real_t tc);
|
||||||
fluid_real_t fluid_tc2sec_release(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_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_pan(fluid_real_t c, int left);
|
||||||
fluid_real_t fluid_balance(fluid_real_t balance, int left);
|
fluid_real_t fluid_balance(fluid_real_t balance, int left);
|
||||||
fluid_real_t fluid_concave(fluid_real_t val);
|
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