1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License
7  * as published by the Free Software Foundation; either version 2.1 of
8  * the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA
19  */
20 
21 
22 #ifndef _FLUID_RVOICE_H
23 #define _FLUID_RVOICE_H
24 
25 #include "fluidsynth_priv.h"
26 #include "fluid_iir_filter.h"
27 #include "fluid_adsr_env.h"
28 #include "fluid_lfo.h"
29 #include "fluid_phase.h"
30 #include "fluid_sfont.h"
31 
32 typedef struct _fluid_rvoice_envlfo_t fluid_rvoice_envlfo_t;
33 typedef struct _fluid_rvoice_dsp_t fluid_rvoice_dsp_t;
34 typedef struct _fluid_rvoice_buffers_t fluid_rvoice_buffers_t;
35 typedef struct _fluid_rvoice_t fluid_rvoice_t;
36 
37 /* Smallest amplitude that can be perceived (full scale is +/- 0.5)
38  * 16 bits => 96+4=100 dB dynamic range => 0.00001
39  * 24 bits => 144-4 = 140 dB dynamic range => 1.e-7
40  * 1.e-7 * 2 == 2.e-7 :)
41  */
42 #define FLUID_NOISE_FLOOR ((fluid_real_t)2.e-7)
43 
44 enum fluid_loop
45 {
46     FLUID_UNLOOPED = 0,
47     FLUID_LOOP_DURING_RELEASE = 1,
48     FLUID_NOTUSED = 2,
49     FLUID_LOOP_UNTIL_RELEASE = 3
50 };
51 
52 /*
53  * rvoice ticks-based parameters
54  * These parameters must be updated even if the voice is currently quiet.
55  */
56 struct _fluid_rvoice_envlfo_t
57 {
58     /* Note-off minimum length */
59     unsigned int ticks;
60     unsigned int noteoff_ticks;
61 
62     /* vol env */
63     fluid_adsr_env_t volenv;
64 
65     /* mod env */
66     fluid_adsr_env_t modenv;
67     fluid_real_t modenv_to_fc;
68     fluid_real_t modenv_to_pitch;
69 
70     /* mod lfo */
71     fluid_lfo_t modlfo;
72     fluid_real_t modlfo_to_fc;
73     fluid_real_t modlfo_to_pitch;
74     fluid_real_t modlfo_to_vol;
75 
76     /* vib lfo */
77     fluid_lfo_t viblfo;
78     fluid_real_t viblfo_to_pitch;
79 };
80 
81 /*
82  * rvoice parameters needed for dsp interpolation
83  */
84 struct _fluid_rvoice_dsp_t
85 {
86     /* interpolation method, as in fluid_interp in fluidsynth.h */
87     enum fluid_interp interp_method;
88     enum fluid_loop samplemode;
89 
90     /* Flag that is set as soon as the first loop is completed. */
91     char has_looped;
92 
93     /* Flag that initiates, that sample-related parameters have to be checked. */
94     char check_sample_sanity_flag;
95 
96     fluid_sample_t *sample;
97 
98     /* sample and loop start and end points (offset in sample memory).  */
99     int start;
100     int end;
101     int loopstart;
102     int loopend;	/* Note: first point following the loop (superimposed on loopstart) */
103 
104     /* Stuff needed for portamento calculations */
105     fluid_real_t pitchoffset;        /* the portamento range in midicents */
106     fluid_real_t pitchinc;           /* the portamento increment in midicents */
107 
108     /* Stuff needed for phase calculations */
109 
110     fluid_real_t pitch;              /* the pitch in midicents */
111     fluid_real_t root_pitch_hz;
112     fluid_real_t output_rate;
113 
114     /* Stuff needed for amplitude calculations */
115 
116     fluid_real_t attenuation;        /* the attenuation in centibels */
117     fluid_real_t prev_attenuation;   /* the previous attenuation in centibels
118 					used by fluid_rvoice_multi_retrigger_attack() */
119     fluid_real_t min_attenuation_cB; /* Estimate on the smallest possible attenuation
120 					  * during the lifetime of the voice */
121     fluid_real_t amplitude_that_reaches_noise_floor_nonloop;
122     fluid_real_t amplitude_that_reaches_noise_floor_loop;
123     fluid_real_t synth_gain; 	/* master gain */
124 
125     /* Dynamic input to the interpolator below */
126 
127     fluid_real_t amp;                /* current linear amplitude */
128     fluid_real_t amp_incr;		/* amplitude increment value for the next FLUID_BUFSIZE samples */
129 
130     fluid_phase_t phase;             /* the phase (current sample offset) of the sample wave */
131     fluid_real_t phase_incr;	/* the phase increment for the next FLUID_BUFSIZE samples */
132 };
133 
134 /* Currently left, right, reverb, chorus. To be changed if we
135    ever add surround positioning, or stereo reverb/chorus */
136 #define FLUID_RVOICE_MAX_BUFS (4)
137 
138 /*
139  * rvoice mixer-related parameters
140  */
141 struct _fluid_rvoice_buffers_t
142 {
143     unsigned int count; /* Number of records in "bufs" */
144     struct
145     {
146         /* the actual, linearly interpolated amplitude with which the dsp sample should be mixed into the buf */
147         fluid_real_t current_amp;
148 
149         /* the desired amplitude [...] mixed into the buf (directly set by e.g. rapidly changing PAN events) */
150         fluid_real_t target_amp;
151 
152         /* Mapping to mixdown buffer index */
153         int mapping;
154     } bufs[FLUID_RVOICE_MAX_BUFS];
155 };
156 
157 
158 /*
159  * Hard real-time parameters needed to synthesize a voice
160  */
161 struct _fluid_rvoice_t
162 {
163     fluid_rvoice_envlfo_t envlfo;
164     fluid_rvoice_dsp_t dsp;
165     fluid_iir_filter_t resonant_filter; /* IIR resonant dsp filter */
166     fluid_iir_filter_t resonant_custom_filter; /* optional custom/general-purpose IIR resonant filter */
167     fluid_rvoice_buffers_t buffers;
168 };
169 
170 
171 int fluid_rvoice_write(fluid_rvoice_t *voice, fluid_real_t *dsp_buf);
172 
173 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_amp);
174 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_mapping);
175 
176 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_noteoff);
177 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_voiceoff);
178 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_reset);
179 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_multi_retrigger_attack);
180 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_portamento);
181 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_output_rate);
182 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_interp_method);
183 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_root_pitch_hz);
184 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_pitch);
185 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_attenuation);
186 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_min_attenuation_cB);
187 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_viblfo_to_pitch);
188 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_pitch);
189 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_vol);
190 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_fc);
191 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modenv_to_fc);
192 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modenv_to_pitch);
193 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_synth_gain);
194 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_start);
195 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_end);
196 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_loopstart);
197 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_loopend);
198 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_samplemode);
199 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_sample);
200 
201 /* defined in fluid_rvoice_dsp.c */
202 void fluid_rvoice_dsp_config(void);
203 int fluid_rvoice_dsp_interpolate_none(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping);
204 int fluid_rvoice_dsp_interpolate_linear(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping);
205 int fluid_rvoice_dsp_interpolate_4th_order(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping);
206 int fluid_rvoice_dsp_interpolate_7th_order(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping);
207 
208 
209 /*
210  * Combines the most significant 16 bit part of a sample with a potentially present
211  * least sig. 8 bit part in order to create a 24 bit sample.
212  */
213 static FLUID_INLINE int32_t
fluid_rvoice_get_sample(const short int * dsp_msb,const char * dsp_lsb,unsigned int idx)214 fluid_rvoice_get_sample(const short int *dsp_msb, const char *dsp_lsb, unsigned int idx)
215 {
216     /* cast sample to unsigned type, so we can safely shift and bitwise or
217      * without relying on undefined behaviour (should never happen anyway ofc...) */
218     uint32_t msb = (uint32_t)dsp_msb[idx];
219     uint8_t lsb = 0U;
220 
221     /* most soundfonts have 16 bit samples, assume that it's unlikely we
222      * experience 24 bit samples here */
223     if(FLUID_UNLIKELY(dsp_lsb != NULL))
224     {
225         lsb = (uint8_t)dsp_lsb[idx];
226     }
227 
228     return (int32_t)((msb << 8) | lsb);
229 }
230 
231 #endif
232