Rev 8775 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8752 | terminx | 1 | /* TinySoundFont - v0.8 - SoundFont2 synthesizer - https://github.com/schellingb/TinySoundFont |
2 | no warranty implied; use at your own risk |
||
3 | Do this: |
||
4 | #define TSF_IMPLEMENTATION |
||
5 | before you include this file in *one* C or C++ file to create the implementation. |
||
6 | // i.e. it should look like this: |
||
7 | #include ... |
||
8 | #include ... |
||
9 | #define TSF_IMPLEMENTATION |
||
10 | #include "tsf.h" |
||
11 | |||
12 | [OPTIONAL] #define TSF_NO_STDIO to remove stdio dependency |
||
13 | [OPTIONAL] #define TSF_MALLOC, TSF_REALLOC, and TSF_FREE to avoid stdlib.h |
||
14 | [OPTIONAL] #define TSF_MEMCPY, TSF_MEMSET to avoid string.h |
||
15 | [OPTIONAL] #define TSF_POW, TSF_POWF, TSF_EXPF, TSF_LOG, TSF_TAN, TSF_LOG10, TSF_SQRT to avoid math.h |
||
16 | |||
17 | NOT YET IMPLEMENTED |
||
18 | - Support for ChorusEffectsSend and ReverbEffectsSend generators |
||
19 | - Better low-pass filter without lowering performance too much |
||
20 | - Support for modulators |
||
21 | |||
22 | LICENSE (MIT) |
||
23 | |||
24 | Copyright (C) 2017, 2018 Bernhard Schelling |
||
25 | Based on SFZero, Copyright (C) 2012 Steve Folta (https://github.com/stevefolta/SFZero) |
||
26 | |||
27 | Permission is hereby granted, free of charge, to any person obtaining a copy of this |
||
28 | software and associated documentation files (the "Software"), to deal in the Software |
||
29 | without restriction, including without limitation the rights to use, copy, modify, merge, |
||
30 | publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons |
||
31 | to whom the Software is furnished to do so, subject to the following conditions: |
||
32 | |||
33 | The above copyright notice and this permission notice shall be included in all |
||
34 | copies or substantial portions of the Software. |
||
35 | |||
36 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
||
37 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
||
38 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||
39 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
||
40 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
||
41 | USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
42 | |||
43 | */ |
||
44 | |||
45 | #ifndef TSF_INCLUDE_TSF_INL |
||
46 | #define TSF_INCLUDE_TSF_INL |
||
47 | |||
48 | #ifdef __cplusplus |
||
49 | extern "C" { |
||
50 | # define CPP_DEFAULT0 = 0 |
||
51 | #else |
||
52 | # define CPP_DEFAULT0 |
||
53 | #endif |
||
54 | |||
55 | //define this if you want the API functions to be static |
||
56 | #ifdef TSF_STATIC |
||
57 | #define TSFDEF static |
||
58 | #else |
||
59 | #define TSFDEF extern |
||
60 | #endif |
||
61 | |||
62 | // The load functions will return a pointer to a struct tsf which all functions |
||
63 | // thereafter take as the first parameter. |
||
64 | // On error the tsf_load* functions will return NULL most likely due to invalid |
||
65 | // data (or if the file did not exist in tsf_load_filename). |
||
66 | typedef struct tsf tsf; |
||
67 | |||
68 | #ifndef TSF_NO_STDIO |
||
69 | // Directly load a SoundFont from a .sf2 file path |
||
70 | TSFDEF tsf* tsf_load_filename(const char* filename); |
||
71 | #endif |
||
72 | |||
73 | // Load a SoundFont from a block of memory |
||
74 | TSFDEF tsf* tsf_load_memory(const void* buffer, int size); |
||
75 | |||
76 | // Stream structure for the generic loading |
||
77 | struct tsf_stream |
||
78 | { |
||
79 | // Custom data given to the functions as the first parameter |
||
80 | void* data; |
||
81 | |||
82 | // Function pointer will be called to read 'size' bytes into ptr (returns number of read bytes) |
||
83 | int (*read)(void* data, void* ptr, unsigned int size); |
||
84 | |||
85 | // Function pointer will be called to skip ahead over 'count' bytes (returns 1 on success, 0 on error) |
||
86 | int (*skip)(void* data, unsigned int count); |
||
87 | }; |
||
88 | |||
89 | // Generic SoundFont loading method using the stream structure above |
||
90 | TSFDEF tsf* tsf_load(struct tsf_stream* stream); |
||
91 | |||
92 | // Free the memory related to this tsf instance |
||
93 | TSFDEF void tsf_close(tsf* f); |
||
94 | |||
95 | // Stop all playing notes immediatly and reset all channel parameters |
||
96 | TSFDEF void tsf_reset(tsf* f); |
||
97 | |||
98 | // Returns the preset index from a bank and preset number, or -1 if it does not exist in the loaded SoundFont |
||
99 | TSFDEF int tsf_get_presetindex(const tsf* f, int bank, int preset_number); |
||
100 | |||
101 | // Returns the number of presets in the loaded SoundFont |
||
102 | TSFDEF int tsf_get_presetcount(const tsf* f); |
||
103 | |||
104 | // Returns the name of a preset index >= 0 and < tsf_get_presetcount() |
||
105 | TSFDEF const char* tsf_get_presetname(const tsf* f, int preset_index); |
||
106 | |||
107 | // Returns the name of a preset by bank and preset number |
||
108 | TSFDEF const char* tsf_bank_get_presetname(const tsf* f, int bank, int preset_number); |
||
109 | |||
110 | // Supported output modes by the render methods |
||
111 | enum TSFOutputMode |
||
112 | { |
||
113 | // Two channels with single left/right samples one after another |
||
114 | TSF_STEREO_INTERLEAVED, |
||
115 | // Two channels with all samples for the left channel first then right |
||
116 | TSF_STEREO_UNWEAVED, |
||
117 | // A single channel (stereo instruments are mixed into center) |
||
118 | TSF_MONO, |
||
119 | }; |
||
120 | |||
121 | // Thread safety: |
||
122 | // Your audio output which calls the tsf_render* functions will most likely |
||
123 | // run on a different thread than where the playback tsf_note* functions |
||
124 | // are called. In which case some sort of concurrency control like a |
||
125 | // mutex needs to be used so they are not called at the same time. |
||
126 | |||
127 | // Setup the parameters for the voice render methods |
||
128 | // outputmode: if mono or stereo and how stereo channel data is ordered |
||
129 | // samplerate: the number of samples per second (output frequency) |
||
130 | // global_gain_db: volume gain in decibels (>0 means higher, <0 means lower) |
||
131 | TSFDEF void tsf_set_output(tsf* f, enum TSFOutputMode outputmode, int samplerate, float global_gain_db CPP_DEFAULT0); |
||
132 | |||
133 | // Start playing a note |
||
134 | // preset_index: preset index >= 0 and < tsf_get_presetcount() |
||
135 | // key: note value between 0 and 127 (60 being middle C) |
||
136 | // vel: velocity as a float between 0.0 (equal to note off) and 1.0 (full) |
||
137 | // bank: instrument bank number (alternative to preset_index) |
||
138 | // preset_number: preset number (alternative to preset_index) |
||
139 | // (bank_note_on returns 0 if preset does not exist, otherwise 1) |
||
140 | TSFDEF void tsf_note_on(tsf* f, int preset_index, int key, float vel); |
||
141 | TSFDEF int tsf_bank_note_on(tsf* f, int bank, int preset_number, int key, float vel); |
||
142 | |||
143 | // Stop playing a note |
||
144 | // (bank_note_off returns 0 if preset does not exist, otherwise 1) |
||
145 | TSFDEF void tsf_note_off(tsf* f, int preset_index, int key); |
||
146 | TSFDEF int tsf_bank_note_off(tsf* f, int bank, int preset_number, int key); |
||
147 | |||
148 | // Stop playing all notes (end with sustain and release) |
||
149 | TSFDEF void tsf_note_off_all(tsf* f); |
||
150 | |||
151 | // Returns the number of active voices |
||
152 | TSFDEF int tsf_active_voice_count(tsf* f); |
||
153 | |||
154 | // Render output samples into a buffer |
||
155 | // You can either render as signed 16-bit values (tsf_render_short) or |
||
156 | // as 32-bit float values (tsf_render_float) |
||
157 | // buffer: target buffer of size samples * output_channels * sizeof(type) |
||
158 | // samples: number of samples to render |
||
159 | // flag_mixing: if 0 clear the buffer first, otherwise mix into existing data |
||
160 | TSFDEF void tsf_render_short(tsf* f, short* buffer, int samples, int flag_mixing CPP_DEFAULT0); |
||
161 | TSFDEF void tsf_render_float(tsf* f, float* buffer, int samples, int flag_mixing CPP_DEFAULT0); |
||
162 | |||
163 | // Higher level channel based functions, set up channel parameters |
||
164 | // channel: channel number |
||
165 | // preset_index: preset index >= 0 and < tsf_get_presetcount() |
||
166 | // preset_number: preset number (alternative to preset_index) |
||
167 | // flag_mididrums: 0 for normal channels, otherwise apply MIDI drum channel rules |
||
168 | // bank: instrument bank number (alternative to preset_index) |
||
169 | // pan: stereo panning value from 0.0 (left) to 1.0 (right) (default 0.5 center) |
||
170 | // volume: linear volume scale factor (default 1.0 full) |
||
171 | // pitch_wheel: pitch wheel position 0 to 16383 (default 8192 unpitched) |
||
172 | // pitch_range: range of the pitch wheel in semitones (default 2.0, total +/- 2 semitones) |
||
173 | // tuning: tuning of all playing voices in semitones (default 0.0, standard (A440) tuning) |
||
174 | // (set_preset_number and set_bank_preset return 0 if preset does not exist, otherwise 1) |
||
175 | TSFDEF void tsf_channel_set_presetindex(tsf* f, int channel, int preset_index); |
||
176 | TSFDEF int tsf_channel_set_presetnumber(tsf* f, int channel, int preset_number, int flag_mididrums CPP_DEFAULT0); |
||
177 | TSFDEF void tsf_channel_set_bank(tsf* f, int channel, int bank); |
||
178 | TSFDEF int tsf_channel_set_bank_preset(tsf* f, int channel, int bank, int preset_number); |
||
179 | TSFDEF void tsf_channel_set_pan(tsf* f, int channel, float pan); |
||
180 | TSFDEF void tsf_channel_set_volume(tsf* f, int channel, float volume); |
||
181 | TSFDEF void tsf_channel_set_pitchwheel(tsf* f, int channel, int pitch_wheel); |
||
182 | TSFDEF void tsf_channel_set_pitchrange(tsf* f, int channel, float pitch_range); |
||
183 | TSFDEF void tsf_channel_set_tuning(tsf* f, int channel, float tuning); |
||
184 | |||
185 | // Start or stop playing notes on a channel (needs channel preset to be set) |
||
186 | // channel: channel number |
||
187 | // key: note value between 0 and 127 (60 being middle C) |
||
188 | // vel: velocity as a float between 0.0 (equal to note off) and 1.0 (full) |
||
189 | TSFDEF void tsf_channel_note_on(tsf* f, int channel, int key, float vel); |
||
190 | TSFDEF void tsf_channel_note_off(tsf* f, int channel, int key); |
||
191 | TSFDEF void tsf_channel_note_off_all(tsf* f, int channel); //end with sustain and release |
||
192 | TSFDEF void tsf_channel_sounds_off_all(tsf* f, int channel); //end immediatly |
||
193 | |||
194 | // Apply a MIDI control change to the channel (not all controllers are supported!) |
||
195 | TSFDEF void tsf_channel_midi_control(tsf* f, int channel, int controller, int control_value); |
||
196 | |||
197 | // Get current values set on the channels |
||
198 | TSFDEF int tsf_channel_get_preset_index(tsf* f, int channel); |
||
199 | TSFDEF int tsf_channel_get_preset_bank(tsf* f, int channel); |
||
200 | TSFDEF int tsf_channel_get_preset_number(tsf* f, int channel); |
||
201 | TSFDEF float tsf_channel_get_pan(tsf* f, int channel); |
||
202 | TSFDEF float tsf_channel_get_volume(tsf* f, int channel); |
||
203 | TSFDEF int tsf_channel_get_pitchwheel(tsf* f, int channel); |
||
204 | TSFDEF float tsf_channel_get_pitchrange(tsf* f, int channel); |
||
205 | TSFDEF float tsf_channel_get_tuning(tsf* f, int channel); |
||
206 | |||
207 | #ifdef __cplusplus |
||
208 | # undef CPP_DEFAULT0 |
||
209 | } |
||
210 | #endif |
||
211 | |||
212 | // end header |
||
213 | // --------------------------------------------------------------------------------------------------------- |
||
214 | #endif //TSF_INCLUDE_TSF_INL |
||
215 | |||
216 | #ifdef TSF_IMPLEMENTATION |
||
217 | |||
218 | // The lower this block size is the more accurate the effects are. |
||
219 | // Increasing the value significantly lowers the CPU usage of the voice rendering. |
||
220 | // If LFO affects the low-pass filter it can be hearable even as low as 8. |
||
221 | #ifndef TSF_RENDER_EFFECTSAMPLEBLOCK |
||
222 | #define TSF_RENDER_EFFECTSAMPLEBLOCK 64 |
||
223 | #endif |
||
224 | |||
225 | // Grace release time for quick voice off (avoid clicking noise) |
||
226 | #define TSF_FASTRELEASETIME 0.01f |
||
227 | |||
228 | #if !defined(TSF_MALLOC) || !defined(TSF_FREE) || !defined(TSF_REALLOC) |
||
229 | # include <stdlib.h> |
||
230 | # define TSF_MALLOC malloc |
||
231 | # define TSF_FREE free |
||
232 | # define TSF_REALLOC realloc |
||
233 | #endif |
||
234 | |||
235 | #if !defined(TSF_MEMCPY) || !defined(TSF_MEMSET) |
||
236 | # include <string.h> |
||
237 | # define TSF_MEMCPY memcpy |
||
238 | # define TSF_MEMSET memset |
||
239 | #endif |
||
240 | |||
241 | #if !defined(TSF_POW) || !defined(TSF_POWF) || !defined(TSF_EXPF) || !defined(TSF_LOG) || !defined(TSF_TAN) || !defined(TSF_LOG10) || !defined(TSF_SQRT) |
||
242 | # include <math.h> |
||
243 | # if !defined(__cplusplus) && !defined(NAN) && !defined(powf) && !defined(expf) && !defined(sqrtf) |
||
244 | # define powf (float)pow // deal with old math.h |
||
245 | # define expf (float)exp // files that come without |
||
246 | # define sqrtf (float)sqrt // powf, expf and sqrtf |
||
247 | # endif |
||
248 | # define TSF_POW pow |
||
249 | # define TSF_POWF powf |
||
250 | # define TSF_EXPF expf |
||
251 | # define TSF_LOG log |
||
252 | # define TSF_TAN tan |
||
253 | # define TSF_LOG10 log10 |
||
254 | # define TSF_SQRTF sqrtf |
||
255 | #endif |
||
256 | |||
257 | #ifndef TSF_NO_STDIO |
||
258 | # include <stdio.h> |
||
259 | #endif |
||
260 | |||
261 | #define TSF_TRUE 1 |
||
262 | #define TSF_FALSE 0 |
||
263 | #define TSF_BOOL char |
||
264 | #define TSF_PI 3.14159265358979323846264338327950288 |
||
265 | #define TSF_NULL 0 |
||
266 | |||
267 | #ifdef __cplusplus |
||
268 | extern "C" { |
||
269 | #endif |
||
270 | |||
271 | typedef char tsf_fourcc[4]; |
||
272 | typedef signed char tsf_s8; |
||
273 | typedef unsigned char tsf_u8; |
||
274 | typedef unsigned short tsf_u16; |
||
275 | typedef signed short tsf_s16; |
||
276 | typedef unsigned int tsf_u32; |
||
277 | typedef char tsf_char20[20]; |
||
278 | |||
279 | #define TSF_FourCCEquals(value1, value2) (value1[0] == value2[0] && value1[1] == value2[1] && value1[2] == value2[2] && value1[3] == value2[3]) |
||
280 | |||
281 | struct tsf |
||
282 | { |
||
283 | struct tsf_preset* presets; |
||
284 | float* fontSamples; |
||
285 | struct tsf_voice* voices; |
||
286 | struct tsf_channels* channels; |
||
287 | float* outputSamples; |
||
288 | |||
289 | int presetNum; |
||
290 | int voiceNum; |
||
291 | int outputSampleSize; |
||
292 | unsigned int voicePlayIndex; |
||
293 | |||
294 | enum TSFOutputMode outputmode; |
||
295 | float outSampleRate; |
||
296 | float globalGainDB; |
||
297 | }; |
||
298 | |||
299 | #ifndef TSF_NO_STDIO |
||
300 | static int tsf_stream_stdio_read(FILE* f, void* ptr, unsigned int size) { return (int)fread(ptr, 1, size, f); } |
||
301 | static int tsf_stream_stdio_skip(FILE* f, unsigned int count) { return !fseek(f, count, SEEK_CUR); } |
||
302 | TSFDEF tsf* tsf_load_filename(const char* filename) |
||
303 | { |
||
304 | tsf* res; |
||
305 | struct tsf_stream stream = { TSF_NULL, (int(*)(void*,void*,unsigned int))&tsf_stream_stdio_read, (int(*)(void*,unsigned int))&tsf_stream_stdio_skip }; |
||
306 | #if __STDC_WANT_SECURE_LIB__ |
||
307 | FILE* f = TSF_NULL; fopen_s(&f, filename, "rb"); |
||
308 | #else |
||
309 | FILE* f = fopen(filename, "rb"); |
||
310 | #endif |
||
311 | if (!f) |
||
312 | { |
||
313 | //if (e) *e = TSF_FILENOTFOUND; |
||
314 | return TSF_NULL; |
||
315 | } |
||
316 | stream.data = f; |
||
317 | res = tsf_load(&stream); |
||
318 | fclose(f); |
||
319 | return res; |
||
320 | } |
||
321 | #endif |
||
322 | |||
323 | struct tsf_stream_memory { const char* buffer; unsigned int total, pos; }; |
||
324 | static int tsf_stream_memory_read(struct tsf_stream_memory* m, void* ptr, unsigned int size) { if (size > m->total - m->pos) size = m->total - m->pos; TSF_MEMCPY(ptr, m->buffer+m->pos, size); m->pos += size; return size; } |
||
325 | static int tsf_stream_memory_skip(struct tsf_stream_memory* m, unsigned int count) { if (m->pos + count > m->total) return 0; m->pos += count; return 1; } |
||
326 | TSFDEF tsf* tsf_load_memory(const void* buffer, int size) |
||
327 | { |
||
328 | struct tsf_stream stream = { TSF_NULL, (int(*)(void*,void*,unsigned int))&tsf_stream_memory_read, (int(*)(void*,unsigned int))&tsf_stream_memory_skip }; |
||
329 | struct tsf_stream_memory f = { 0, 0, 0 }; |
||
330 | f.buffer = (const char*)buffer; |
||
331 | f.total = size; |
||
332 | stream.data = &f; |
||
333 | return tsf_load(&stream); |
||
334 | } |
||
335 | |||
336 | enum { TSF_LOOPMODE_NONE, TSF_LOOPMODE_CONTINUOUS, TSF_LOOPMODE_SUSTAIN }; |
||
337 | |||
338 | enum { TSF_SEGMENT_NONE, TSF_SEGMENT_DELAY, TSF_SEGMENT_ATTACK, TSF_SEGMENT_HOLD, TSF_SEGMENT_DECAY, TSF_SEGMENT_SUSTAIN, TSF_SEGMENT_RELEASE, TSF_SEGMENT_DONE }; |
||
339 | |||
340 | struct tsf_hydra |
||
341 | { |
||
342 | struct tsf_hydra_phdr *phdrs; struct tsf_hydra_pbag *pbags; struct tsf_hydra_pmod *pmods; |
||
343 | struct tsf_hydra_pgen *pgens; struct tsf_hydra_inst *insts; struct tsf_hydra_ibag *ibags; |
||
344 | struct tsf_hydra_imod *imods; struct tsf_hydra_igen *igens; struct tsf_hydra_shdr *shdrs; |
||
345 | int phdrNum, pbagNum, pmodNum, pgenNum, instNum, ibagNum, imodNum, igenNum, shdrNum; |
||
346 | }; |
||
347 | |||
348 | union tsf_hydra_genamount { struct { tsf_u8 lo, hi; } range; tsf_s16 shortAmount; tsf_u16 wordAmount; }; |
||
349 | struct tsf_hydra_phdr { tsf_char20 presetName; tsf_u16 preset, bank, presetBagNdx; tsf_u32 library, genre, morphology; }; |
||
350 | struct tsf_hydra_pbag { tsf_u16 genNdx, modNdx; }; |
||
351 | struct tsf_hydra_pmod { tsf_u16 modSrcOper, modDestOper; tsf_s16 modAmount; tsf_u16 modAmtSrcOper, modTransOper; }; |
||
352 | struct tsf_hydra_pgen { tsf_u16 genOper; union tsf_hydra_genamount genAmount; }; |
||
353 | struct tsf_hydra_inst { tsf_char20 instName; tsf_u16 instBagNdx; }; |
||
354 | struct tsf_hydra_ibag { tsf_u16 instGenNdx, instModNdx; }; |
||
355 | struct tsf_hydra_imod { tsf_u16 modSrcOper, modDestOper; tsf_s16 modAmount; tsf_u16 modAmtSrcOper, modTransOper; }; |
||
356 | struct tsf_hydra_igen { tsf_u16 genOper; union tsf_hydra_genamount genAmount; }; |
||
357 | struct tsf_hydra_shdr { tsf_char20 sampleName; tsf_u32 start, end, startLoop, endLoop, sampleRate; tsf_u8 originalPitch; tsf_s8 pitchCorrection; tsf_u16 sampleLink, sampleType; }; |
||
358 | |||
359 | #define TSFR(FIELD) stream->read(stream->data, &i->FIELD, sizeof(i->FIELD)); |
||
360 | static void tsf_hydra_read_phdr(struct tsf_hydra_phdr* i, struct tsf_stream* stream) { TSFR(presetName) TSFR(preset) TSFR(bank) TSFR(presetBagNdx) TSFR(library) TSFR(genre) TSFR(morphology) } |
||
361 | static void tsf_hydra_read_pbag(struct tsf_hydra_pbag* i, struct tsf_stream* stream) { TSFR(genNdx) TSFR(modNdx) } |
||
362 | static void tsf_hydra_read_pmod(struct tsf_hydra_pmod* i, struct tsf_stream* stream) { TSFR(modSrcOper) TSFR(modDestOper) TSFR(modAmount) TSFR(modAmtSrcOper) TSFR(modTransOper) } |
||
363 | static void tsf_hydra_read_pgen(struct tsf_hydra_pgen* i, struct tsf_stream* stream) { TSFR(genOper) TSFR(genAmount) } |
||
364 | static void tsf_hydra_read_inst(struct tsf_hydra_inst* i, struct tsf_stream* stream) { TSFR(instName) TSFR(instBagNdx) } |
||
365 | static void tsf_hydra_read_ibag(struct tsf_hydra_ibag* i, struct tsf_stream* stream) { TSFR(instGenNdx) TSFR(instModNdx) } |
||
366 | static void tsf_hydra_read_imod(struct tsf_hydra_imod* i, struct tsf_stream* stream) { TSFR(modSrcOper) TSFR(modDestOper) TSFR(modAmount) TSFR(modAmtSrcOper) TSFR(modTransOper) } |
||
367 | static void tsf_hydra_read_igen(struct tsf_hydra_igen* i, struct tsf_stream* stream) { TSFR(genOper) TSFR(genAmount) } |
||
368 | static void tsf_hydra_read_shdr(struct tsf_hydra_shdr* i, struct tsf_stream* stream) { TSFR(sampleName) TSFR(start) TSFR(end) TSFR(startLoop) TSFR(endLoop) TSFR(sampleRate) TSFR(originalPitch) TSFR(pitchCorrection) TSFR(sampleLink) TSFR(sampleType) } |
||
369 | #undef TSFR |
||
370 | |||
371 | struct tsf_riffchunk { tsf_fourcc id; tsf_u32 size; }; |
||
372 | struct tsf_envelope { float delay, attack, hold, decay, sustain, release, keynumToHold, keynumToDecay; }; |
||
373 | struct tsf_voice_envelope { float level, slope; int samplesUntilNextSegment; short segment, midiVelocity; struct tsf_envelope parameters; TSF_BOOL segmentIsExponential, isAmpEnv; }; |
||
374 | struct tsf_voice_lowpass { double QInv, a0, a1, b1, b2, z1, z2; TSF_BOOL active; }; |
||
375 | struct tsf_voice_lfo { int samplesUntil; float level, delta; }; |
||
376 | |||
377 | struct tsf_region |
||
378 | { |
||
379 | int loop_mode; |
||
380 | unsigned int sample_rate; |
||
381 | unsigned char lokey, hikey, lovel, hivel; |
||
382 | unsigned int group, offset, end, loop_start, loop_end; |
||
383 | int transpose, tune, pitch_keycenter, pitch_keytrack; |
||
384 | float attenuation, pan; |
||
385 | struct tsf_envelope ampenv, modenv; |
||
386 | int initialFilterQ, initialFilterFc; |
||
387 | int modEnvToPitch, modEnvToFilterFc, modLfoToFilterFc, modLfoToVolume; |
||
388 | float delayModLFO; |
||
389 | int freqModLFO, modLfoToPitch; |
||
390 | float delayVibLFO; |
||
391 | int freqVibLFO, vibLfoToPitch; |
||
392 | }; |
||
393 | |||
394 | struct tsf_preset |
||
395 | { |
||
396 | tsf_char20 presetName; |
||
397 | tsf_u16 preset, bank; |
||
398 | struct tsf_region* regions; |
||
399 | int regionNum; |
||
400 | }; |
||
401 | |||
402 | struct tsf_voice |
||
403 | { |
||
404 | int playingPreset, playingKey, playingChannel; |
||
405 | struct tsf_region* region; |
||
406 | double pitchInputTimecents, pitchOutputFactor; |
||
407 | double sourceSamplePosition; |
||
408 | float noteGainDB, panFactorLeft, panFactorRight; |
||
409 | unsigned int playIndex, loopStart, loopEnd; |
||
410 | struct tsf_voice_envelope ampenv, modenv; |
||
411 | struct tsf_voice_lowpass lowpass; |
||
412 | struct tsf_voice_lfo modlfo, viblfo; |
||
413 | }; |
||
414 | |||
415 | struct tsf_channel |
||
416 | { |
||
417 | unsigned short presetIndex, bank, pitchWheel, midiPan, midiVolume, midiExpression, midiRPN, midiData; |
||
418 | float panOffset, gainDB, pitchRange, tuning; |
||
419 | }; |
||
420 | |||
421 | struct tsf_channels |
||
422 | { |
||
423 | void (*setupVoice)(tsf* f, struct tsf_voice* voice); |
||
424 | struct tsf_channel* channels; |
||
425 | int channelNum, activeChannel; |
||
426 | }; |
||
427 | |||
428 | static double tsf_timecents2Secsd(double timecents) { return TSF_POW(2.0, timecents / 1200.0); } |
||
429 | static float tsf_timecents2Secsf(float timecents) { return TSF_POWF(2.0f, timecents / 1200.0f); } |
||
430 | static float tsf_cents2Hertz(float cents) { return 8.176f * TSF_POWF(2.0f, cents / 1200.0f); } |
||
431 | static float tsf_decibelsToGain(float db) { return (db > -100.f ? TSF_POWF(10.0f, db * 0.05f) : 0); } |
||
432 | static float tsf_gainToDecibels(float gain) { return (gain <= .00001f ? -100.f : (float)(20.0 * TSF_LOG10(gain))); } |
||
433 | |||
434 | static TSF_BOOL tsf_riffchunk_read(struct tsf_riffchunk* parent, struct tsf_riffchunk* chunk, struct tsf_stream* stream) |
||
435 | { |
||
436 | TSF_BOOL IsRiff, IsList; |
||
437 | if (parent && sizeof(tsf_fourcc) + sizeof(tsf_u32) > parent->size) return TSF_FALSE; |
||
438 | if (!stream->read(stream->data, &chunk->id, sizeof(tsf_fourcc)) || *chunk->id <= ' ' || *chunk->id >= 'z') return TSF_FALSE; |
||
439 | if (!stream->read(stream->data, &chunk->size, sizeof(tsf_u32))) return TSF_FALSE; |
||
440 | if (parent && sizeof(tsf_fourcc) + sizeof(tsf_u32) + chunk->size > parent->size) return TSF_FALSE; |
||
441 | if (parent) parent->size -= sizeof(tsf_fourcc) + sizeof(tsf_u32) + chunk->size; |
||
442 | IsRiff = TSF_FourCCEquals(chunk->id, "RIFF"), IsList = TSF_FourCCEquals(chunk->id, "LIST"); |
||
443 | if (IsRiff && parent) return TSF_FALSE; //not allowed |
||
444 | if (!IsRiff && !IsList) return TSF_TRUE; //custom type without sub type |
||
445 | if (!stream->read(stream->data, &chunk->id, sizeof(tsf_fourcc)) || *chunk->id <= ' ' || *chunk->id >= 'z') return TSF_FALSE; |
||
446 | chunk->size -= sizeof(tsf_fourcc); |
||
447 | return TSF_TRUE; |
||
448 | } |
||
449 | |||
450 | static void tsf_region_clear(struct tsf_region* i, TSF_BOOL for_relative) |
||
451 | { |
||
452 | TSF_MEMSET(i, 0, sizeof(struct tsf_region)); |
||
453 | i->hikey = i->hivel = 127; |
||
454 | i->pitch_keycenter = 60; // C4 |
||
455 | if (for_relative) return; |
||
456 | |||
457 | i->pitch_keytrack = 100; |
||
458 | |||
459 | i->pitch_keycenter = -1; |
||
460 | |||
461 | // SF2 defaults in timecents. |
||
462 | i->ampenv.delay = i->ampenv.attack = i->ampenv.hold = i->ampenv.decay = i->ampenv.release = -12000.0f; |
||
463 | i->modenv.delay = i->modenv.attack = i->modenv.hold = i->modenv.decay = i->modenv.release = -12000.0f; |
||
464 | |||
465 | i->initialFilterFc = 13500; |
||
466 | |||
467 | i->delayModLFO = -12000.0f; |
||
468 | i->delayVibLFO = -12000.0f; |
||
469 | } |
||
470 | |||
8775 | terminx | 471 | static void tsf_region_operator(struct tsf_region* region, tsf_u16 genOper, union tsf_hydra_genamount* amount, struct tsf_region* merge_region) |
8752 | terminx | 472 | { |
473 | enum |
||
474 | { |
||
8775 | terminx | 475 | _GEN_TYPE_MASK = 0x0F, |
476 | GEN_FLOAT = 0x01, |
||
477 | GEN_INT = 0x02, |
||
478 | GEN_UINT_ADD = 0x03, |
||
479 | GEN_UINT_ADD15 = 0x04, |
||
480 | GEN_KEYRANGE = 0x05, |
||
481 | GEN_VELRANGE = 0x06, |
||
482 | GEN_LOOPMODE = 0x07, |
||
483 | GEN_GROUP = 0x08, |
||
484 | GEN_KEYCENTER = 0x09, |
||
485 | |||
486 | _GEN_LIMIT_MASK = 0xF0, |
||
487 | GEN_INT_LIMIT12K = 0x10, //min -12000, max 12000 |
||
488 | GEN_INT_LIMITFC = 0x20, //min 1500, max 13500 |
||
489 | GEN_INT_LIMITQ = 0x30, //min 0, max 960 |
||
490 | GEN_INT_LIMIT960 = 0x40, //min -960, max 960 |
||
491 | GEN_INT_LIMIT16K4500 = 0x50, //min -16000, max 4500 |
||
492 | GEN_FLOAT_LIMIT12K5K = 0x60, //min -12000, max 5000 |
||
493 | GEN_FLOAT_LIMIT12K8K = 0x70, //min -12000, max 8000 |
||
494 | GEN_FLOAT_LIMIT1200 = 0x80, //min -1200, max 1200 |
||
495 | GEN_FLOAT_LIMITPAN = 0x90, //* .001f, min -.5f, max .5f, |
||
496 | GEN_FLOAT_LIMITATTN = 0xA0, //* .1f, min 0, max 144.0 |
||
497 | GEN_FLOAT_MAX1000 = 0xB0, //min 0, max 1000 |
||
498 | GEN_FLOAT_MAX1440 = 0xC0, //min 0, max 1440 |
||
499 | |||
500 | _GEN_MAX = 59, |
||
8752 | terminx | 501 | }; |
8775 | terminx | 502 | #define _TSFREGIONOFFSET(TYPE, FIELD) (unsigned char)(((TYPE*)&((struct tsf_region*)0)->FIELD) - (TYPE*)0) |
503 | #define _TSFREGIONENVOFFSET(TYPE, ENV, FIELD) (unsigned char)(((TYPE*)&((&(((struct tsf_region*)0)->ENV))->FIELD)) - (TYPE*)0) |
||
504 | static const struct { unsigned char mode, offset; } genMetas[_GEN_MAX] = |
||
8752 | terminx | 505 | { |
8775 | terminx | 506 | { GEN_UINT_ADD , _TSFREGIONOFFSET(unsigned int, offset ) }, // 0 StartAddrsOffset |
507 | { GEN_UINT_ADD , _TSFREGIONOFFSET(unsigned int, end ) }, // 1 EndAddrsOffset |
||
508 | { GEN_UINT_ADD , _TSFREGIONOFFSET(unsigned int, loop_start ) }, // 2 StartloopAddrsOffset |
||
509 | { GEN_UINT_ADD , _TSFREGIONOFFSET(unsigned int, loop_end ) }, // 3 EndloopAddrsOffset |
||
510 | { GEN_UINT_ADD15 , _TSFREGIONOFFSET(unsigned int, offset ) }, // 4 StartAddrsCoarseOffset |
||
511 | { GEN_INT | GEN_INT_LIMIT12K , _TSFREGIONOFFSET( int, modLfoToPitch ) }, // 5 ModLfoToPitch |
||
512 | { GEN_INT | GEN_INT_LIMIT12K , _TSFREGIONOFFSET( int, vibLfoToPitch ) }, // 6 VibLfoToPitch |
||
513 | { GEN_INT | GEN_INT_LIMIT12K , _TSFREGIONOFFSET( int, modEnvToPitch ) }, // 7 ModEnvToPitch |
||
514 | { GEN_INT | GEN_INT_LIMITFC , _TSFREGIONOFFSET( int, initialFilterFc ) }, // 8 InitialFilterFc |
||
515 | { GEN_INT | GEN_INT_LIMITQ , _TSFREGIONOFFSET( int, initialFilterQ ) }, // 9 InitialFilterQ |
||
516 | { GEN_INT | GEN_INT_LIMIT12K , _TSFREGIONOFFSET( int, modLfoToFilterFc ) }, //10 ModLfoToFilterFc |
||
517 | { GEN_INT | GEN_INT_LIMIT12K , _TSFREGIONOFFSET( int, modEnvToFilterFc ) }, //11 ModEnvToFilterFc |
||
518 | { GEN_UINT_ADD15 , _TSFREGIONOFFSET(unsigned int, end ) }, //12 EndAddrsCoarseOffset |
||
519 | { GEN_INT | GEN_INT_LIMIT960 , _TSFREGIONOFFSET( int, modLfoToVolume ) }, //13 ModLfoToVolume |
||
520 | { 0 , (0 ) }, // Unused |
||
521 | { 0 , (0 ) }, //15 ChorusEffectsSend (unsupported) |
||
522 | { 0 , (0 ) }, //16 ReverbEffectsSend (unsupported) |
||
523 | { GEN_FLOAT | GEN_FLOAT_LIMITPAN , _TSFREGIONOFFSET( float, pan ) }, //17 Pan |
||
524 | { 0 , (0 ) }, // Unused |
||
525 | { 0 , (0 ) }, // Unused |
||
526 | { 0 , (0 ) }, // Unused |
||
527 | { GEN_FLOAT | GEN_FLOAT_LIMIT12K5K , _TSFREGIONOFFSET( float, delayModLFO ) }, //21 DelayModLFO |
||
528 | { GEN_INT | GEN_INT_LIMIT16K4500 , _TSFREGIONOFFSET( int, freqModLFO ) }, //22 FreqModLFO |
||
529 | { GEN_FLOAT | GEN_FLOAT_LIMIT12K5K , _TSFREGIONOFFSET( float, delayVibLFO ) }, //23 DelayVibLFO |
||
530 | { GEN_INT | GEN_INT_LIMIT16K4500 , _TSFREGIONOFFSET( int, freqVibLFO ) }, //24 FreqVibLFO |
||
531 | { GEN_FLOAT | GEN_FLOAT_LIMIT12K5K , _TSFREGIONENVOFFSET( float, modenv, delay ) }, //25 DelayModEnv |
||
532 | { GEN_FLOAT | GEN_FLOAT_LIMIT12K8K , _TSFREGIONENVOFFSET( float, modenv, attack ) }, //26 AttackModEnv |
||
533 | { GEN_FLOAT | GEN_FLOAT_LIMIT12K5K , _TSFREGIONENVOFFSET( float, modenv, hold ) }, //27 HoldModEnv |
||
534 | { GEN_FLOAT | GEN_FLOAT_LIMIT12K8K , _TSFREGIONENVOFFSET( float, modenv, decay ) }, //28 DecayModEnv |
||
535 | { GEN_FLOAT | GEN_FLOAT_MAX1000 , _TSFREGIONENVOFFSET( float, modenv, sustain ) }, //29 SustainModEnv |
||
536 | { GEN_FLOAT | GEN_FLOAT_LIMIT12K8K , _TSFREGIONENVOFFSET( float, modenv, release ) }, //30 ReleaseModEnv |
||
537 | { GEN_FLOAT | GEN_FLOAT_LIMIT1200 , _TSFREGIONENVOFFSET( float, modenv, keynumToHold ) }, //31 KeynumToModEnvHold |
||
538 | { GEN_FLOAT | GEN_FLOAT_LIMIT1200 , _TSFREGIONENVOFFSET( float, modenv, keynumToDecay) }, //32 KeynumToModEnvDecay |
||
539 | { GEN_FLOAT | GEN_FLOAT_LIMIT12K5K , _TSFREGIONENVOFFSET( float, ampenv, delay ) }, //33 DelayVolEnv |
||
540 | { GEN_FLOAT | GEN_FLOAT_LIMIT12K8K , _TSFREGIONENVOFFSET( float, ampenv, attack ) }, //34 AttackVolEnv |
||
541 | { GEN_FLOAT | GEN_FLOAT_LIMIT12K5K , _TSFREGIONENVOFFSET( float, ampenv, hold ) }, //35 HoldVolEnv |
||
542 | { GEN_FLOAT | GEN_FLOAT_LIMIT12K8K , _TSFREGIONENVOFFSET( float, ampenv, decay ) }, //36 DecayVolEnv |
||
543 | { GEN_FLOAT | GEN_FLOAT_MAX1440 , _TSFREGIONENVOFFSET( float, ampenv, sustain ) }, //37 SustainVolEnv |
||
544 | { GEN_FLOAT | GEN_FLOAT_LIMIT12K8K , _TSFREGIONENVOFFSET( float, ampenv, release ) }, //38 ReleaseVolEnv |
||
545 | { GEN_FLOAT | GEN_FLOAT_LIMIT1200 , _TSFREGIONENVOFFSET( float, ampenv, keynumToHold ) }, //39 KeynumToVolEnvHold |
||
546 | { GEN_FLOAT | GEN_FLOAT_LIMIT1200 , _TSFREGIONENVOFFSET( float, ampenv, keynumToDecay) }, //40 KeynumToVolEnvDecay |
||
547 | { 0 , (0 ) }, // Instrument (special) |
||
548 | { 0 , (0 ) }, // Reserved |
||
549 | { GEN_KEYRANGE , (0 ) }, //43 KeyRange |
||
550 | { GEN_VELRANGE , (0 ) }, //44 VelRange |
||
551 | { GEN_UINT_ADD15 , _TSFREGIONOFFSET(unsigned int, loop_start ) }, //45 StartloopAddrsCoarseOffset |
||
552 | { 0 , (0 ) }, //46 Keynum (special) |
||
553 | { 0 , (0 ) }, //47 Velocity (special) |
||
554 | { GEN_FLOAT | GEN_FLOAT_LIMITATTN , _TSFREGIONOFFSET( float, attenuation ) }, //48 InitialAttenuation |
||
555 | { 0 , (0 ) }, // Reserved |
||
556 | { GEN_UINT_ADD15 , _TSFREGIONOFFSET(unsigned int, loop_end ) }, //50 EndloopAddrsCoarseOffset |
||
557 | { GEN_INT , _TSFREGIONOFFSET( int, transpose ) }, //51 CoarseTune |
||
558 | { GEN_INT , _TSFREGIONOFFSET( int, tune ) }, //52 FineTune |
||
559 | { 0 , (0 ) }, // SampleID (special) |
||
560 | { GEN_LOOPMODE , _TSFREGIONOFFSET( int, loop_mode ) }, //54 SampleModes |
||
561 | { 0 , (0 ) }, // Reserved |
||
562 | { GEN_INT , _TSFREGIONOFFSET( int, pitch_keytrack ) }, //56 ScaleTuning |
||
563 | { GEN_GROUP , _TSFREGIONOFFSET(unsigned int, group ) }, //57 ExclusiveClass |
||
564 | { GEN_KEYCENTER , _TSFREGIONOFFSET( int, pitch_keycenter ) }, //58 OverridingRootKey |
||
565 | }; |
||
566 | #undef _TSFREGIONOFFSET |
||
567 | #undef _TSFREGIONENVOFFSET |
||
568 | if (amount) |
||
569 | { |
||
570 | int offset; |
||
571 | if (genOper >= _GEN_MAX) return; |
||
572 | offset = genMetas[genOper].offset; |
||
573 | switch (genMetas[genOper].mode & _GEN_TYPE_MASK) |
||
574 | { |
||
575 | case GEN_FLOAT: (( float*)region)[offset] = amount->shortAmount; return; |
||
576 | case GEN_INT: (( int*)region)[offset] = amount->shortAmount; return; |
||
577 | case GEN_UINT_ADD: ((unsigned int*)region)[offset] += amount->shortAmount; return; |
||
578 | case GEN_UINT_ADD15: ((unsigned int*)region)[offset] += amount->shortAmount<<15; return; |
||
579 | case GEN_KEYRANGE: region->lokey = amount->range.lo; region->hikey = amount->range.hi; return; |
||
580 | case GEN_VELRANGE: region->lovel = amount->range.lo; region->hivel = amount->range.hi; return; |
||
581 | case GEN_LOOPMODE: region->loop_mode = ((amount->wordAmount&3) == 3 ? TSF_LOOPMODE_SUSTAIN : ((amount->wordAmount&3) == 1 ? TSF_LOOPMODE_CONTINUOUS : TSF_LOOPMODE_NONE)); return; |
||
582 | case GEN_GROUP: region->group = amount->wordAmount; return; |
||
583 | case GEN_KEYCENTER: region->pitch_keycenter = amount->shortAmount; return; |
||
584 | } |
||
8752 | terminx | 585 | } |
8775 | terminx | 586 | else //merge regions and clamp values |
587 | { |
||
588 | for (genOper = 0; genOper != _GEN_MAX; genOper++) |
||
589 | { |
||
590 | int offset = genMetas[genOper].offset; |
||
591 | switch (genMetas[genOper].mode & _GEN_TYPE_MASK) |
||
592 | { |
||
593 | case GEN_FLOAT: |
||
594 | { |
||
595 | float *val = &((float*)region)[offset], vfactor, vmin, vmax; |
||
596 | *val += ((float*)merge_region)[offset]; |
||
597 | switch (genMetas[genOper].mode & _GEN_LIMIT_MASK) |
||
598 | { |
||
599 | case GEN_FLOAT_LIMIT12K5K: vfactor = 1.0f; vmin = -12000.0f; vmax = 5000.0f; break; |
||
600 | case GEN_FLOAT_LIMIT12K8K: vfactor = 1.0f; vmin = -12000.0f; vmax = 8000.0f; break; |
||
601 | case GEN_FLOAT_LIMIT1200: vfactor = 1.0f; vmin = -1200.0f; vmax = 1200.0f; break; |
||
602 | case GEN_FLOAT_LIMITPAN: vfactor = 0.001f; vmin = -0.5f; vmax = 0.5f; break; |
||
603 | case GEN_FLOAT_LIMITATTN: vfactor = 0.1f; vmin = 0.0f; vmax = 144.0f; break; |
||
604 | case GEN_FLOAT_MAX1000: vfactor = 1.0f; vmin = 0.0f; vmax = 1000.0f; break; |
||
605 | case GEN_FLOAT_MAX1440: vfactor = 1.0f; vmin = 0.0f; vmax = 1440.0f; break; |
||
606 | default: continue; |
||
607 | } |
||
608 | *val *= vfactor; |
||
609 | if (*val < vmin) *val = vmin; |
||
610 | else if (*val > vmax) *val = vmax; |
||
611 | continue; |
||
612 | } |
||
613 | case GEN_INT: |
||
614 | { |
||
615 | int *val = &((int*)region)[offset], vmin, vmax; |
||
616 | *val += ((int*)merge_region)[offset]; |
||
617 | switch (genMetas[genOper].mode & _GEN_LIMIT_MASK) |
||
618 | { |
||
619 | case GEN_INT_LIMIT12K: vmin = -12000; vmax = 12000; break; |
||
620 | case GEN_INT_LIMITFC: vmin = 1500; vmax = 13500; break; |
||
621 | case GEN_INT_LIMITQ: vmin = 0; vmax = 960; break; |
||
622 | case GEN_INT_LIMIT960: vmin = -960; vmax = 960; break; |
||
623 | case GEN_INT_LIMIT16K4500: vmin = -16000; vmax = 4500; break; |
||
624 | default: continue; |
||
625 | } |
||
626 | if (*val < vmin) *val = vmin; |
||
627 | else if (*val > vmax) *val = vmax; |
||
628 | continue; |
||
629 | } |
||
630 | case GEN_UINT_ADD: |
||
631 | { |
||
632 | ((unsigned int*)region)[offset] += ((unsigned int*)merge_region)[offset]; |
||
633 | continue; |
||
634 | } |
||
635 | } |
||
636 | } |
||
637 | } |
||
8752 | terminx | 638 | } |
639 | |||
640 | static void tsf_region_envtosecs(struct tsf_envelope* p, TSF_BOOL sustainIsGain) |
||
641 | { |
||
642 | // EG times need to be converted from timecents to seconds. |
||
643 | // Pin very short EG segments. Timecents don't get to zero, and our EG is |
||
644 | // happier with zero values. |
||
645 | p->delay = (p->delay < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->delay)); |
||
646 | p->attack = (p->attack < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->attack)); |
||
647 | p->release = (p->release < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->release)); |
||
648 | |||
649 | // If we have dynamic hold or decay times depending on key number we need |
||
650 | // to keep the values in timecents so we can calculate it during startNote |
||
651 | if (!p->keynumToHold) p->hold = (p->hold < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->hold)); |
||
652 | if (!p->keynumToDecay) p->decay = (p->decay < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->decay)); |
||
653 | |||
654 | if (p->sustain < 0.0f) p->sustain = 0.0f; |
||
655 | else if (sustainIsGain) p->sustain = tsf_decibelsToGain(-p->sustain / 10.0f); |
||
656 | else p->sustain = 1.0f - (p->sustain / 1000.0f); |
||
657 | } |
||
658 | |||
659 | static void tsf_load_presets(tsf* res, struct tsf_hydra *hydra, unsigned int fontSampleCount) |
||
660 | { |
||
661 | enum { GenInstrument = 41, GenKeyRange = 43, GenVelRange = 44, GenSampleID = 53 }; |
||
662 | // Read each preset. |
||
663 | struct tsf_hydra_phdr *pphdr, *pphdrMax; |
||
664 | for (pphdr = hydra->phdrs, pphdrMax = pphdr + hydra->phdrNum - 1; pphdr != pphdrMax; pphdr++) |
||
665 | { |
||
666 | int sortedIndex = 0, region_index = 0; |
||
667 | struct tsf_hydra_phdr *otherphdr; |
||
668 | struct tsf_preset* preset; |
||
669 | struct tsf_hydra_pbag *ppbag, *ppbagEnd; |
||
670 | struct tsf_region globalRegion; |
||
671 | for (otherphdr = hydra->phdrs; otherphdr != pphdrMax; otherphdr++) |
||
672 | { |
||
673 | if (otherphdr == pphdr || otherphdr->bank > pphdr->bank) continue; |
||
674 | else if (otherphdr->bank < pphdr->bank) sortedIndex++; |
||
675 | else if (otherphdr->preset > pphdr->preset) continue; |
||
676 | else if (otherphdr->preset < pphdr->preset) sortedIndex++; |
||
677 | else if (otherphdr < pphdr) sortedIndex++; |
||
678 | } |
||
679 | |||
680 | preset = &res->presets[sortedIndex]; |
||
681 | TSF_MEMCPY(preset->presetName, pphdr->presetName, sizeof(preset->presetName)); |
||
682 | preset->presetName[sizeof(preset->presetName)-1] = '\0'; //should be zero terminated in source file but make sure |
||
683 | preset->bank = pphdr->bank; |
||
684 | preset->preset = pphdr->preset; |
||
685 | preset->regionNum = 0; |
||
686 | |||
687 | //count regions covered by this preset |
||
688 | for (ppbag = hydra->pbags + pphdr->presetBagNdx, ppbagEnd = hydra->pbags + pphdr[1].presetBagNdx; ppbag != ppbagEnd; ppbag++) |
||
689 | { |
||
690 | unsigned char plokey = 0, phikey = 127, plovel = 0, phivel = 127; |
||
691 | struct tsf_hydra_pgen *ppgen, *ppgenEnd; struct tsf_hydra_inst *pinst; struct tsf_hydra_ibag *pibag, *pibagEnd; struct tsf_hydra_igen *pigen, *pigenEnd; |
||
692 | for (ppgen = hydra->pgens + ppbag->genNdx, ppgenEnd = hydra->pgens + ppbag[1].genNdx; ppgen != ppgenEnd; ppgen++) |
||
693 | { |
||
694 | if (ppgen->genOper == GenKeyRange) { plokey = ppgen->genAmount.range.lo; phikey = ppgen->genAmount.range.hi; continue; } |
||
695 | if (ppgen->genOper == GenVelRange) { plovel = ppgen->genAmount.range.lo; phivel = ppgen->genAmount.range.hi; continue; } |
||
696 | if (ppgen->genOper != GenInstrument) continue; |
||
697 | if (ppgen->genAmount.wordAmount >= hydra->instNum) continue; |
||
698 | pinst = hydra->insts + ppgen->genAmount.wordAmount; |
||
699 | for (pibag = hydra->ibags + pinst->instBagNdx, pibagEnd = hydra->ibags + pinst[1].instBagNdx; pibag != pibagEnd; pibag++) |
||
700 | { |
||
701 | unsigned char ilokey = 0, ihikey = 127, ilovel = 0, ihivel = 127; |
||
702 | for (pigen = hydra->igens + pibag->instGenNdx, pigenEnd = hydra->igens + pibag[1].instGenNdx; pigen != pigenEnd; pigen++) |
||
703 | { |
||
704 | if (pigen->genOper == GenKeyRange) { ilokey = pigen->genAmount.range.lo; ihikey = pigen->genAmount.range.hi; continue; } |
||
705 | if (pigen->genOper == GenVelRange) { ilovel = pigen->genAmount.range.lo; ihivel = pigen->genAmount.range.hi; continue; } |
||
706 | if (pigen->genOper == GenSampleID && ihikey >= plokey && ilokey <= phikey && ihivel >= plovel && ilovel <= phivel) preset->regionNum++; |
||
707 | } |
||
708 | } |
||
709 | } |
||
710 | } |
||
711 | |||
712 | preset->regions = (struct tsf_region*)TSF_MALLOC(preset->regionNum * sizeof(struct tsf_region)); |
||
713 | tsf_region_clear(&globalRegion, TSF_TRUE); |
||
714 | |||
715 | // Zones. |
||
716 | for (ppbag = hydra->pbags + pphdr->presetBagNdx, ppbagEnd = hydra->pbags + pphdr[1].presetBagNdx; ppbag != ppbagEnd; ppbag++) |
||
717 | { |
||
718 | struct tsf_hydra_pgen *ppgen, *ppgenEnd; struct tsf_hydra_inst *pinst; struct tsf_hydra_ibag *pibag, *pibagEnd; struct tsf_hydra_igen *pigen, *pigenEnd; |
||
719 | struct tsf_region presetRegion = globalRegion; |
||
720 | int hadGenInstrument = 0; |
||
721 | |||
722 | // Generators. |
||
723 | for (ppgen = hydra->pgens + ppbag->genNdx, ppgenEnd = hydra->pgens + ppbag[1].genNdx; ppgen != ppgenEnd; ppgen++) |
||
724 | { |
||
725 | // Instrument. |
||
726 | if (ppgen->genOper == GenInstrument) |
||
727 | { |
||
728 | struct tsf_region instRegion; |
||
729 | tsf_u16 whichInst = ppgen->genAmount.wordAmount; |
||
730 | if (whichInst >= hydra->instNum) continue; |
||
731 | |||
732 | tsf_region_clear(&instRegion, TSF_FALSE); |
||
733 | pinst = &hydra->insts[whichInst]; |
||
734 | for (pibag = hydra->ibags + pinst->instBagNdx, pibagEnd = hydra->ibags + pinst[1].instBagNdx; pibag != pibagEnd; pibag++) |
||
735 | { |
||
736 | // Generators. |
||
737 | struct tsf_region zoneRegion = instRegion; |
||
738 | int hadSampleID = 0; |
||
739 | for (pigen = hydra->igens + pibag->instGenNdx, pigenEnd = hydra->igens + pibag[1].instGenNdx; pigen != pigenEnd; pigen++) |
||
740 | { |
||
741 | if (pigen->genOper == GenSampleID) |
||
742 | { |
||
743 | struct tsf_hydra_shdr* pshdr; |
||
744 | |||
745 | //preset region key and vel ranges are a filter for the zone regions |
||
746 | if (zoneRegion.hikey < presetRegion.lokey || zoneRegion.lokey > presetRegion.hikey) continue; |
||
747 | if (zoneRegion.hivel < presetRegion.lovel || zoneRegion.lovel > presetRegion.hivel) continue; |
||
748 | if (presetRegion.lokey > zoneRegion.lokey) zoneRegion.lokey = presetRegion.lokey; |
||
749 | if (presetRegion.hikey < zoneRegion.hikey) zoneRegion.hikey = presetRegion.hikey; |
||
750 | if (presetRegion.lovel > zoneRegion.lovel) zoneRegion.lovel = presetRegion.lovel; |
||
751 | if (presetRegion.hivel < zoneRegion.hivel) zoneRegion.hivel = presetRegion.hivel; |
||
752 | |||
753 | //sum regions |
||
8775 | terminx | 754 | tsf_region_operator(&zoneRegion, 0, TSF_NULL, &presetRegion); |
8752 | terminx | 755 | |
756 | // EG times need to be converted from timecents to seconds. |
||
757 | tsf_region_envtosecs(&zoneRegion.ampenv, TSF_TRUE); |
||
758 | tsf_region_envtosecs(&zoneRegion.modenv, TSF_FALSE); |
||
759 | |||
760 | // LFO times need to be converted from timecents to seconds. |
||
761 | zoneRegion.delayModLFO = (zoneRegion.delayModLFO < -11950.0f ? 0.0f : tsf_timecents2Secsf(zoneRegion.delayModLFO)); |
||
762 | zoneRegion.delayVibLFO = (zoneRegion.delayVibLFO < -11950.0f ? 0.0f : tsf_timecents2Secsf(zoneRegion.delayVibLFO)); |
||
763 | |||
8775 | terminx | 764 | // Fixup sample positions |
8752 | terminx | 765 | pshdr = &hydra->shdrs[pigen->genAmount.wordAmount]; |
766 | zoneRegion.offset += pshdr->start; |
||
767 | zoneRegion.end += pshdr->end; |
||
768 | zoneRegion.loop_start += pshdr->startLoop; |
||
769 | zoneRegion.loop_end += pshdr->endLoop; |
||
770 | if (pshdr->endLoop > 0) zoneRegion.loop_end -= 1; |
||
771 | if (zoneRegion.pitch_keycenter == -1) zoneRegion.pitch_keycenter = pshdr->originalPitch; |
||
772 | zoneRegion.tune += pshdr->pitchCorrection; |
||
773 | zoneRegion.sample_rate = pshdr->sampleRate; |
||
774 | if (zoneRegion.end && zoneRegion.end < fontSampleCount) zoneRegion.end++; |
||
775 | else zoneRegion.end = fontSampleCount; |
||
776 | |||
777 | preset->regions[region_index] = zoneRegion; |
||
778 | region_index++; |
||
779 | hadSampleID = 1; |
||
780 | } |
||
8775 | terminx | 781 | else tsf_region_operator(&zoneRegion, pigen->genOper, &pigen->genAmount, TSF_NULL); |
8752 | terminx | 782 | } |
783 | |||
784 | // Handle instrument's global zone. |
||
785 | if (pibag == hydra->ibags + pinst->instBagNdx && !hadSampleID) |
||
786 | instRegion = zoneRegion; |
||
787 | |||
788 | // Modulators (TODO) |
||
789 | //if (ibag->instModNdx < ibag[1].instModNdx) addUnsupportedOpcode("any modulator"); |
||
790 | } |
||
791 | hadGenInstrument = 1; |
||
792 | } |
||
8775 | terminx | 793 | else tsf_region_operator(&presetRegion, ppgen->genOper, &ppgen->genAmount, TSF_NULL); |
8752 | terminx | 794 | } |
795 | |||
796 | // Modulators (TODO) |
||
797 | //if (pbag->modNdx < pbag[1].modNdx) addUnsupportedOpcode("any modulator"); |
||
798 | |||
799 | // Handle preset's global zone. |
||
800 | if (ppbag == hydra->pbags + pphdr->presetBagNdx && !hadGenInstrument) |
||
801 | globalRegion = presetRegion; |
||
802 | } |
||
803 | } |
||
804 | } |
||
805 | |||
806 | static void tsf_load_samples(float** fontSamples, unsigned int* fontSampleCount, struct tsf_riffchunk *chunkSmpl, struct tsf_stream* stream) |
||
807 | { |
||
808 | // Read sample data into float format buffer. |
||
809 | float* out; unsigned int samplesLeft, samplesToRead, samplesToConvert; |
||
810 | samplesLeft = *fontSampleCount = chunkSmpl->size / sizeof(short); |
||
811 | out = *fontSamples = (float*)TSF_MALLOC(samplesLeft * sizeof(float)); |
||
812 | for (; samplesLeft; samplesLeft -= samplesToRead) |
||
813 | { |
||
814 | short sampleBuffer[1024], *in = sampleBuffer;; |
||
815 | samplesToRead = (samplesLeft > 1024 ? 1024 : samplesLeft); |
||
816 | stream->read(stream->data, sampleBuffer, samplesToRead * sizeof(short)); |
||
817 | |||
818 | // Convert from signed 16-bit to float. |
||
819 | for (samplesToConvert = samplesToRead; samplesToConvert > 0; --samplesToConvert) |
||
820 | // If we ever need to compile for big-endian platforms, we'll need to byte-swap here. |
||
821 | *out++ = (float)(*in++ / 32767.0); |
||
822 | } |
||
823 | } |
||
824 | |||
825 | static void tsf_voice_envelope_nextsegment(struct tsf_voice_envelope* e, short active_segment, float outSampleRate) |
||
826 | { |
||
827 | switch (active_segment) |
||
828 | { |
||
829 | case TSF_SEGMENT_NONE: |
||
830 | e->samplesUntilNextSegment = (int)(e->parameters.delay * outSampleRate); |
||
831 | if (e->samplesUntilNextSegment > 0) |
||
832 | { |
||
833 | e->segment = TSF_SEGMENT_DELAY; |
||
834 | e->segmentIsExponential = TSF_FALSE; |
||
835 | e->level = 0.0; |
||
836 | e->slope = 0.0; |
||
837 | return; |
||
838 | } |
||
839 | /* fall through */ |
||
840 | case TSF_SEGMENT_DELAY: |
||
841 | e->samplesUntilNextSegment = (int)(e->parameters.attack * outSampleRate); |
||
842 | if (e->samplesUntilNextSegment > 0) |
||
843 | { |
||
844 | if (!e->isAmpEnv) |
||
845 | { |
||
846 | //mod env attack duration scales with velocity (velocity of 1 is full duration, max velocity is 0.125 times duration) |
||
847 | e->samplesUntilNextSegment = (int)(e->parameters.attack * ((145 - e->midiVelocity) / 144.0f) * outSampleRate); |
||
848 | } |
||
849 | e->segment = TSF_SEGMENT_ATTACK; |
||
850 | e->segmentIsExponential = TSF_FALSE; |
||
851 | e->level = 0.0f; |
||
852 | e->slope = 1.0f / e->samplesUntilNextSegment; |
||
853 | return; |
||
854 | } |
||
855 | /* fall through */ |
||
856 | case TSF_SEGMENT_ATTACK: |
||
857 | e->samplesUntilNextSegment = (int)(e->parameters.hold * outSampleRate); |
||
858 | if (e->samplesUntilNextSegment > 0) |
||
859 | { |
||
860 | e->segment = TSF_SEGMENT_HOLD; |
||
861 | e->segmentIsExponential = TSF_FALSE; |
||
862 | e->level = 1.0f; |
||
863 | e->slope = 0.0f; |
||
864 | return; |
||
865 | } |
||
866 | /* fall through */ |
||
867 | case TSF_SEGMENT_HOLD: |
||
868 | e->samplesUntilNextSegment = (int)(e->parameters.decay * outSampleRate); |
||
869 | if (e->samplesUntilNextSegment > 0) |
||
870 | { |
||
871 | e->segment = TSF_SEGMENT_DECAY; |
||
872 | e->level = 1.0f; |
||
873 | if (e->isAmpEnv) |
||
874 | { |
||
875 | // I don't truly understand this; just following what LinuxSampler does. |
||
876 | float mysterySlope = -9.226f / e->samplesUntilNextSegment; |
||
877 | e->slope = TSF_EXPF(mysterySlope); |
||
878 | e->segmentIsExponential = TSF_TRUE; |
||
879 | if (e->parameters.sustain > 0.0f) |
||
880 | { |
||
881 | // Again, this is following LinuxSampler's example, which is similar to |
||
882 | // SF2-style decay, where "decay" specifies the time it would take to |
||
883 | // get to zero, not to the sustain level. The SFZ spec is not that |
||
884 | // specific about what "decay" means, so perhaps it's really supposed |
||
885 | // to specify the time to reach the sustain level. |
||
886 | e->samplesUntilNextSegment = (int)(TSF_LOG(e->parameters.sustain) / mysterySlope); |
||
887 | } |
||
888 | } |
||
889 | else |
||
890 | { |
||
891 | e->slope = -1.0f / e->samplesUntilNextSegment; |
||
892 | e->samplesUntilNextSegment = (int)(e->parameters.decay * (1.0f - e->parameters.sustain) * outSampleRate); |
||
893 | e->segmentIsExponential = TSF_FALSE; |
||
894 | } |
||
895 | return; |
||
896 | } |
||
897 | /* fall through */ |
||
898 | case TSF_SEGMENT_DECAY: |
||
899 | e->segment = TSF_SEGMENT_SUSTAIN; |
||
900 | e->level = e->parameters.sustain; |
||
901 | e->slope = 0.0f; |
||
902 | e->samplesUntilNextSegment = 0x7FFFFFFF; |
||
903 | e->segmentIsExponential = TSF_FALSE; |
||
904 | return; |
||
905 | case TSF_SEGMENT_SUSTAIN: |
||
906 | e->segment = TSF_SEGMENT_RELEASE; |
||
907 | e->samplesUntilNextSegment = (int)((e->parameters.release <= 0 ? TSF_FASTRELEASETIME : e->parameters.release) * outSampleRate); |
||
908 | if (e->isAmpEnv) |
||
909 | { |
||
910 | // I don't truly understand this; just following what LinuxSampler does. |
||
911 | float mysterySlope = -9.226f / e->samplesUntilNextSegment; |
||
912 | e->slope = TSF_EXPF(mysterySlope); |
||
913 | e->segmentIsExponential = TSF_TRUE; |
||
914 | } |
||
915 | else |
||
916 | { |
||
917 | e->slope = -e->level / e->samplesUntilNextSegment; |
||
918 | e->segmentIsExponential = TSF_FALSE; |
||
919 | } |
||
920 | return; |
||
921 | case TSF_SEGMENT_RELEASE: |
||
922 | default: |
||
923 | e->segment = TSF_SEGMENT_DONE; |
||
924 | e->segmentIsExponential = TSF_FALSE; |
||
925 | e->level = e->slope = 0.0f; |
||
926 | e->samplesUntilNextSegment = 0x7FFFFFF; |
||
927 | } |
||
928 | } |
||
929 | |||
930 | static void tsf_voice_envelope_setup(struct tsf_voice_envelope* e, struct tsf_envelope* new_parameters, int midiNoteNumber, short midiVelocity, TSF_BOOL isAmpEnv, float outSampleRate) |
||
931 | { |
||
932 | e->parameters = *new_parameters; |
||
933 | if (e->parameters.keynumToHold) |
||
934 | { |
||
935 | e->parameters.hold += e->parameters.keynumToHold * (60.0f - midiNoteNumber); |
||
936 | e->parameters.hold = (e->parameters.hold < -10000.0f ? 0.0f : tsf_timecents2Secsf(e->parameters.hold)); |
||
937 | } |
||
938 | if (e->parameters.keynumToDecay) |
||
939 | { |
||
940 | e->parameters.decay += e->parameters.keynumToDecay * (60.0f - midiNoteNumber); |
||
941 | e->parameters.decay = (e->parameters.decay < -10000.0f ? 0.0f : tsf_timecents2Secsf(e->parameters.decay)); |
||
942 | } |
||
943 | e->midiVelocity = midiVelocity; |
||
944 | e->isAmpEnv = isAmpEnv; |
||
945 | tsf_voice_envelope_nextsegment(e, TSF_SEGMENT_NONE, outSampleRate); |
||
946 | } |
||
947 | |||
948 | static void tsf_voice_envelope_process(struct tsf_voice_envelope* e, int numSamples, float outSampleRate) |
||
949 | { |
||
950 | if (e->slope) |
||
951 | { |
||
952 | if (e->segmentIsExponential) e->level *= TSF_POWF(e->slope, (float)numSamples); |
||
953 | else e->level += (e->slope * numSamples); |
||
954 | } |
||
955 | if ((e->samplesUntilNextSegment -= numSamples) <= 0) |
||
956 | tsf_voice_envelope_nextsegment(e, e->segment, outSampleRate); |
||
957 | } |
||
958 | |||
959 | static void tsf_voice_lowpass_setup(struct tsf_voice_lowpass* e, float Fc) |
||
960 | { |
||
961 | // Lowpass filter from http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/ |
||
962 | double K = TSF_TAN(TSF_PI * Fc), KK = K * K; |
||
963 | double norm = 1 / (1 + K * e->QInv + KK); |
||
964 | e->a0 = KK * norm; |
||
965 | e->a1 = 2 * e->a0; |
||
966 | e->b1 = 2 * (KK - 1) * norm; |
||
967 | e->b2 = (1 - K * e->QInv + KK) * norm; |
||
968 | } |
||
969 | |||
970 | static float tsf_voice_lowpass_process(struct tsf_voice_lowpass* e, double In) |
||
971 | { |
||
972 | double Out = In * e->a0 + e->z1; e->z1 = In * e->a1 + e->z2 - e->b1 * Out; e->z2 = In * e->a0 - e->b2 * Out; return (float)Out; |
||
973 | } |
||
974 | |||
975 | static void tsf_voice_lfo_setup(struct tsf_voice_lfo* e, float delay, int freqCents, float outSampleRate) |
||
976 | { |
||
977 | e->samplesUntil = (int)(delay * outSampleRate); |
||
978 | e->delta = (4.0f * tsf_cents2Hertz((float)freqCents) / outSampleRate); |
||
979 | e->level = 0; |
||
980 | } |
||
981 | |||
982 | static void tsf_voice_lfo_process(struct tsf_voice_lfo* e, int blockSamples) |
||
983 | { |
||
984 | if (e->samplesUntil > blockSamples) { e->samplesUntil -= blockSamples; return; } |
||
985 | e->level += e->delta * blockSamples; |
||
986 | if (e->level > 1.0f) { e->delta = -e->delta; e->level = 2.0f - e->level; } |
||
987 | else if (e->level < -1.0f) { e->delta = -e->delta; e->level = -2.0f - e->level; } |
||
988 | } |
||
989 | |||
990 | static void tsf_voice_kill(struct tsf_voice* v) |
||
991 | { |
||
992 | v->playingPreset = -1; |
||
993 | } |
||
994 | |||
995 | static void tsf_voice_end(struct tsf_voice* v, float outSampleRate) |
||
996 | { |
||
997 | tsf_voice_envelope_nextsegment(&v->ampenv, TSF_SEGMENT_SUSTAIN, outSampleRate); |
||
998 | tsf_voice_envelope_nextsegment(&v->modenv, TSF_SEGMENT_SUSTAIN, outSampleRate); |
||
999 | if (v->region->loop_mode == TSF_LOOPMODE_SUSTAIN) |
||
1000 | { |
||
1001 | // Continue playing, but stop looping. |
||
1002 | v->loopEnd = v->loopStart; |
||
1003 | } |
||
1004 | } |
||
1005 | |||
1006 | static void tsf_voice_endquick(struct tsf_voice* v, float outSampleRate) |
||
1007 | { |
||
1008 | v->ampenv.parameters.release = 0.0f; tsf_voice_envelope_nextsegment(&v->ampenv, TSF_SEGMENT_SUSTAIN, outSampleRate); |
||
1009 | v->modenv.parameters.release = 0.0f; tsf_voice_envelope_nextsegment(&v->modenv, TSF_SEGMENT_SUSTAIN, outSampleRate); |
||
1010 | } |
||
1011 | |||
1012 | static void tsf_voice_calcpitchratio(struct tsf_voice* v, float pitchShift, float outSampleRate) |
||
1013 | { |
||
1014 | double note = v->playingKey + v->region->transpose + v->region->tune / 100.0; |
||
1015 | double adjustedPitch = v->region->pitch_keycenter + (note - v->region->pitch_keycenter) * (v->region->pitch_keytrack / 100.0); |
||
1016 | if (pitchShift) adjustedPitch += pitchShift; |
||
1017 | v->pitchInputTimecents = adjustedPitch * 100.0; |
||
1018 | v->pitchOutputFactor = v->region->sample_rate / (tsf_timecents2Secsd(v->region->pitch_keycenter * 100.0) * outSampleRate); |
||
1019 | } |
||
1020 | |||
1021 | static void tsf_voice_render(tsf* f, struct tsf_voice* v, float* outputBuffer, int numSamples) |
||
1022 | { |
||
1023 | struct tsf_region* region = v->region; |
||
1024 | float* input = f->fontSamples; |
||
1025 | float* outL = outputBuffer; |
||
1026 | float* outR = (f->outputmode == TSF_STEREO_UNWEAVED ? outL + numSamples : TSF_NULL); |
||
1027 | |||
1028 | // Cache some values, to give them at least some chance of ending up in registers. |
||
1029 | TSF_BOOL updateModEnv = (region->modEnvToPitch || region->modEnvToFilterFc); |
||
1030 | TSF_BOOL updateModLFO = (v->modlfo.delta && (region->modLfoToPitch || region->modLfoToFilterFc || region->modLfoToVolume)); |
||
1031 | TSF_BOOL updateVibLFO = (v->viblfo.delta && (region->vibLfoToPitch)); |
||
1032 | TSF_BOOL isLooping = (v->loopStart < v->loopEnd); |
||
1033 | unsigned int tmpLoopStart = v->loopStart, tmpLoopEnd = v->loopEnd; |
||
1034 | double tmpSampleEndDbl = (double)region->end, tmpLoopEndDbl = (double)tmpLoopEnd + 1.0; |
||
1035 | double tmpSourceSamplePosition = v->sourceSamplePosition; |
||
1036 | struct tsf_voice_lowpass tmpLowpass = v->lowpass; |
||
1037 | |||
1038 | TSF_BOOL dynamicLowpass = (region->modLfoToFilterFc || region->modEnvToFilterFc); |
||
8784 | terminx | 1039 | float tmpSampleRate = f->outSampleRate, tmpInitialFilterFc, tmpModLfoToFilterFc, tmpModEnvToFilterFc; |
8752 | terminx | 1040 | |
1041 | TSF_BOOL dynamicPitchRatio = (region->modLfoToPitch || region->modEnvToPitch || region->vibLfoToPitch); |
||
1042 | double pitchRatio; |
||
1043 | float tmpModLfoToPitch, tmpVibLfoToPitch, tmpModEnvToPitch; |
||
1044 | |||
1045 | TSF_BOOL dynamicGain = (region->modLfoToVolume != 0); |
||
1046 | float noteGain = 0, tmpModLfoToVolume; |
||
1047 | |||
8784 | terminx | 1048 | if (dynamicLowpass) tmpInitialFilterFc = (float)region->initialFilterFc, tmpModLfoToFilterFc = (float)region->modLfoToFilterFc, tmpModEnvToFilterFc = (float)region->modEnvToFilterFc; |
1049 | else tmpInitialFilterFc = 0, tmpModLfoToFilterFc = 0, tmpModEnvToFilterFc = 0; |
||
8752 | terminx | 1050 | |
1051 | if (dynamicPitchRatio) pitchRatio = 0, tmpModLfoToPitch = (float)region->modLfoToPitch, tmpVibLfoToPitch = (float)region->vibLfoToPitch, tmpModEnvToPitch = (float)region->modEnvToPitch; |
||
1052 | else pitchRatio = tsf_timecents2Secsd(v->pitchInputTimecents) * v->pitchOutputFactor, tmpModLfoToPitch = 0, tmpVibLfoToPitch = 0, tmpModEnvToPitch = 0; |
||
1053 | |||
1054 | if (dynamicGain) tmpModLfoToVolume = (float)region->modLfoToVolume * 0.1f; |
||
1055 | else noteGain = tsf_decibelsToGain(v->noteGainDB), tmpModLfoToVolume = 0; |
||
1056 | |||
1057 | while (numSamples) |
||
1058 | { |
||
1059 | float gainMono, gainLeft, gainRight; |
||
1060 | int blockSamples = (numSamples > TSF_RENDER_EFFECTSAMPLEBLOCK ? TSF_RENDER_EFFECTSAMPLEBLOCK : numSamples); |
||
1061 | numSamples -= blockSamples; |
||
1062 | |||
1063 | if (dynamicLowpass) |
||
1064 | { |
||
1065 | float fres = tmpInitialFilterFc + v->modlfo.level * tmpModLfoToFilterFc + v->modenv.level * tmpModEnvToFilterFc; |
||
8775 | terminx | 1066 | float lowpassFc = (fres <= 13500 ? tsf_cents2Hertz(fres) / tmpSampleRate : 1.0f); |
8770 | terminx | 1067 | tmpLowpass.active = (lowpassFc < 0.499f); |
1068 | if (tmpLowpass.active) tsf_voice_lowpass_setup(&tmpLowpass, lowpassFc); |
||
8752 | terminx | 1069 | } |
1070 | |||
1071 | if (dynamicPitchRatio) |
||
1072 | pitchRatio = tsf_timecents2Secsd(v->pitchInputTimecents + (v->modlfo.level * tmpModLfoToPitch + v->viblfo.level * tmpVibLfoToPitch + v->modenv.level * tmpModEnvToPitch)) * v->pitchOutputFactor; |
||
1073 | |||
1074 | if (dynamicGain) |
||
1075 | noteGain = tsf_decibelsToGain(v->noteGainDB + (v->modlfo.level * tmpModLfoToVolume)); |
||
1076 | |||
1077 | gainMono = noteGain * v->ampenv.level; |
||
1078 | |||
1079 | // Update EG. |
||
8775 | terminx | 1080 | tsf_voice_envelope_process(&v->ampenv, blockSamples, tmpSampleRate); |
1081 | if (updateModEnv) tsf_voice_envelope_process(&v->modenv, blockSamples, tmpSampleRate); |
||
8752 | terminx | 1082 | |
1083 | // Update LFOs. |
||
1084 | if (updateModLFO) tsf_voice_lfo_process(&v->modlfo, blockSamples); |
||
1085 | if (updateVibLFO) tsf_voice_lfo_process(&v->viblfo, blockSamples); |
||
1086 | |||
1087 | switch (f->outputmode) |
||
1088 | { |
||
1089 | case TSF_STEREO_INTERLEAVED: |
||
1090 | gainLeft = gainMono * v->panFactorLeft, gainRight = gainMono * v->panFactorRight; |
||
1091 | while (blockSamples-- && tmpSourceSamplePosition < tmpSampleEndDbl) |
||
1092 | { |
||
1093 | unsigned int pos = (unsigned int)tmpSourceSamplePosition, nextPos = (pos >= tmpLoopEnd && isLooping ? tmpLoopStart : pos + 1); |
||
1094 | |||
1095 | // Simple linear interpolation. |
||
1096 | float alpha = (float)(tmpSourceSamplePosition - pos), val = (input[pos] * (1.0f - alpha) + input[nextPos] * alpha); |
||
1097 | |||
1098 | // Low-pass filter. |
||
1099 | if (tmpLowpass.active) val = tsf_voice_lowpass_process(&tmpLowpass, val); |
||
1100 | |||
1101 | *outL++ += val * gainLeft; |
||
1102 | *outL++ += val * gainRight; |
||
1103 | |||
1104 | // Next sample. |
||
1105 | tmpSourceSamplePosition += pitchRatio; |
||
1106 | if (tmpSourceSamplePosition >= tmpLoopEndDbl && isLooping) tmpSourceSamplePosition -= (tmpLoopEnd - tmpLoopStart + 1.0); |
||
1107 | } |
||
1108 | break; |
||
1109 | |||
1110 | case TSF_STEREO_UNWEAVED: |
||
1111 | gainLeft = gainMono * v->panFactorLeft, gainRight = gainMono * v->panFactorRight; |
||
1112 | while (blockSamples-- && tmpSourceSamplePosition < tmpSampleEndDbl) |
||
1113 | { |
||
1114 | unsigned int pos = (unsigned int)tmpSourceSamplePosition, nextPos = (pos >= tmpLoopEnd && isLooping ? tmpLoopStart : pos + 1); |
||
1115 | |||
1116 | // Simple linear interpolation. |
||
1117 | float alpha = (float)(tmpSourceSamplePosition - pos), val = (input[pos] * (1.0f - alpha) + input[nextPos] * alpha); |
||
1118 | |||
1119 | // Low-pass filter. |
||
1120 | if (tmpLowpass.active) val = tsf_voice_lowpass_process(&tmpLowpass, val); |
||
1121 | |||
1122 | *outL++ += val * gainLeft; |
||
1123 | *outR++ += val * gainRight; |
||
1124 | |||
1125 | // Next sample. |
||
1126 | tmpSourceSamplePosition += pitchRatio; |
||
1127 | if (tmpSourceSamplePosition >= tmpLoopEndDbl && isLooping) tmpSourceSamplePosition -= (tmpLoopEnd - tmpLoopStart + 1.0); |
||
1128 | } |
||
1129 | break; |
||
1130 | |||
1131 | case TSF_MONO: |
||
1132 | while (blockSamples-- && tmpSourceSamplePosition < tmpSampleEndDbl) |
||
1133 | { |
||
1134 | unsigned int pos = (unsigned int)tmpSourceSamplePosition, nextPos = (pos >= tmpLoopEnd && isLooping ? tmpLoopStart : pos + 1); |
||
1135 | |||
1136 | // Simple linear interpolation. |
||
1137 | float alpha = (float)(tmpSourceSamplePosition - pos), val = (input[pos] * (1.0f - alpha) + input[nextPos] * alpha); |
||
1138 | |||
1139 | // Low-pass filter. |
||
1140 | if (tmpLowpass.active) val = tsf_voice_lowpass_process(&tmpLowpass, val); |
||
1141 | |||
1142 | *outL++ += val * gainMono; |
||
1143 | |||
1144 | // Next sample. |
||
1145 | tmpSourceSamplePosition += pitchRatio; |
||
1146 | if (tmpSourceSamplePosition >= tmpLoopEndDbl && isLooping) tmpSourceSamplePosition -= (tmpLoopEnd - tmpLoopStart + 1.0); |
||
1147 | } |
||
1148 | break; |
||
1149 | } |
||
1150 | |||
1151 | if (tmpSourceSamplePosition >= tmpSampleEndDbl || v->ampenv.segment == TSF_SEGMENT_DONE) |
||
1152 | { |
||
1153 | tsf_voice_kill(v); |
||
1154 | return; |
||
1155 | } |
||
1156 | } |
||
1157 | |||
1158 | v->sourceSamplePosition = tmpSourceSamplePosition; |
||
1159 | if (tmpLowpass.active || dynamicLowpass) v->lowpass = tmpLowpass; |
||
1160 | } |
||
1161 | |||
1162 | TSFDEF tsf* tsf_load(struct tsf_stream* stream) |
||
1163 | { |
||
1164 | tsf* res = TSF_NULL; |
||
1165 | struct tsf_riffchunk chunkHead; |
||
1166 | struct tsf_riffchunk chunkList; |
||
1167 | struct tsf_hydra hydra; |
||
1168 | float* fontSamples = TSF_NULL; |
||
1169 | unsigned int fontSampleCount = 0; |
||
1170 | |||
1171 | if (!tsf_riffchunk_read(TSF_NULL, &chunkHead, stream) || !TSF_FourCCEquals(chunkHead.id, "sfbk")) |
||
1172 | { |
||
1173 | //if (e) *e = TSF_INVALID_NOSF2HEADER; |
||
1174 | return res; |
||
1175 | } |
||
1176 | |||
1177 | // Read hydra and locate sample data. |
||
1178 | TSF_MEMSET(&hydra, 0, sizeof(hydra)); |
||
1179 | while (tsf_riffchunk_read(&chunkHead, &chunkList, stream)) |
||
1180 | { |
||
1181 | struct tsf_riffchunk chunk; |
||
1182 | if (TSF_FourCCEquals(chunkList.id, "pdta")) |
||
1183 | { |
||
1184 | while (tsf_riffchunk_read(&chunkList, &chunk, stream)) |
||
1185 | { |
||
1186 | #define HandleChunk(chunkName) (TSF_FourCCEquals(chunk.id, #chunkName) && !(chunk.size % chunkName##SizeInFile)) \ |
||
1187 | { \ |
||
1188 | int num = chunk.size / chunkName##SizeInFile, i; \ |
||
1189 | hydra.chunkName##Num = num; \ |
||
1190 | hydra.chunkName##s = (struct tsf_hydra_##chunkName*)TSF_MALLOC(num * sizeof(struct tsf_hydra_##chunkName)); \ |
||
1191 | for (i = 0; i < num; ++i) tsf_hydra_read_##chunkName(&hydra.chunkName##s[i], stream); \ |
||
1192 | } |
||
1193 | enum |
||
1194 | { |
||
1195 | phdrSizeInFile = 38, pbagSizeInFile = 4, pmodSizeInFile = 10, |
||
1196 | pgenSizeInFile = 4, instSizeInFile = 22, ibagSizeInFile = 4, |
||
1197 | imodSizeInFile = 10, igenSizeInFile = 4, shdrSizeInFile = 46 |
||
1198 | }; |
||
1199 | if HandleChunk(phdr) else if HandleChunk(pbag) else if HandleChunk(pmod) |
||
1200 | else if HandleChunk(pgen) else if HandleChunk(inst) else if HandleChunk(ibag) |
||
1201 | else if HandleChunk(imod) else if HandleChunk(igen) else if HandleChunk(shdr) |
||
1202 | else stream->skip(stream->data, chunk.size); |
||
1203 | #undef HandleChunk |
||
1204 | } |
||
1205 | } |
||
1206 | else if (TSF_FourCCEquals(chunkList.id, "sdta")) |
||
1207 | { |
||
1208 | while (tsf_riffchunk_read(&chunkList, &chunk, stream)) |
||
1209 | { |
||
1210 | if (TSF_FourCCEquals(chunk.id, "smpl")) |
||
1211 | { |
||
1212 | tsf_load_samples(&fontSamples, &fontSampleCount, &chunk, stream); |
||
1213 | } |
||
1214 | else stream->skip(stream->data, chunk.size); |
||
1215 | } |
||
1216 | } |
||
1217 | else stream->skip(stream->data, chunkList.size); |
||
1218 | } |
||
1219 | if (!hydra.phdrs || !hydra.pbags || !hydra.pmods || !hydra.pgens || !hydra.insts || !hydra.ibags || !hydra.imods || !hydra.igens || !hydra.shdrs) |
||
1220 | { |
||
1221 | //if (e) *e = TSF_INVALID_INCOMPLETE; |
||
1222 | } |
||
1223 | else if (fontSamples == TSF_NULL) |
||
1224 | { |
||
1225 | //if (e) *e = TSF_INVALID_NOSAMPLEDATA; |
||
1226 | } |
||
1227 | else |
||
1228 | { |
||
1229 | res = (tsf*)TSF_MALLOC(sizeof(tsf)); |
||
1230 | TSF_MEMSET(res, 0, sizeof(tsf)); |
||
1231 | res->presetNum = hydra.phdrNum - 1; |
||
1232 | res->presets = (struct tsf_preset*)TSF_MALLOC(res->presetNum * sizeof(struct tsf_preset)); |
||
1233 | res->fontSamples = fontSamples; |
||
1234 | res->outSampleRate = 44100.0f; |
||
1235 | fontSamples = TSF_NULL; //don't free below |
||
1236 | tsf_load_presets(res, &hydra, fontSampleCount); |
||
1237 | } |
||
1238 | TSF_FREE(hydra.phdrs); TSF_FREE(hydra.pbags); TSF_FREE(hydra.pmods); |
||
1239 | TSF_FREE(hydra.pgens); TSF_FREE(hydra.insts); TSF_FREE(hydra.ibags); |
||
1240 | TSF_FREE(hydra.imods); TSF_FREE(hydra.igens); TSF_FREE(hydra.shdrs); |
||
1241 | TSF_FREE(fontSamples); |
||
1242 | return res; |
||
1243 | } |
||
1244 | |||
1245 | TSFDEF void tsf_close(tsf* f) |
||
1246 | { |
||
1247 | struct tsf_preset *preset, *presetEnd; |
||
1248 | if (!f) return; |
||
1249 | for (preset = f->presets, presetEnd = preset + f->presetNum; preset != presetEnd; preset++) |
||
1250 | TSF_FREE(preset->regions); |
||
1251 | TSF_FREE(f->presets); |
||
1252 | TSF_FREE(f->fontSamples); |
||
1253 | TSF_FREE(f->voices); |
||
1254 | if (f->channels) { TSF_FREE(f->channels->channels); TSF_FREE(f->channels); } |
||
1255 | TSF_FREE(f->outputSamples); |
||
1256 | TSF_FREE(f); |
||
1257 | } |
||
1258 | |||
1259 | TSFDEF void tsf_reset(tsf* f) |
||
1260 | { |
||
1261 | struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum; |
||
1262 | for (; v != vEnd; v++) |
||
1263 | if (v->playingPreset != -1 && (v->ampenv.segment < TSF_SEGMENT_RELEASE || v->ampenv.parameters.release)) |
||
1264 | tsf_voice_endquick(v, f->outSampleRate); |
||
1265 | if (f->channels) { TSF_FREE(f->channels->channels); TSF_FREE(f->channels); f->channels = TSF_NULL; } |
||
1266 | } |
||
1267 | |||
1268 | TSFDEF int tsf_get_presetindex(const tsf* f, int bank, int preset_number) |
||
1269 | { |
||
1270 | const struct tsf_preset *presets; |
||
1271 | int i, iMax; |
||
1272 | for (presets = f->presets, i = 0, iMax = f->presetNum; i < iMax; i++) |
||
1273 | if (presets[i].preset == preset_number && presets[i].bank == bank) |
||
1274 | return i; |
||
1275 | return -1; |
||
1276 | } |
||
1277 | |||
1278 | TSFDEF int tsf_get_presetcount(const tsf* f) |
||
1279 | { |
||
1280 | return f->presetNum; |
||
1281 | } |
||
1282 | |||
1283 | TSFDEF const char* tsf_get_presetname(const tsf* f, int preset) |
||
1284 | { |
||
1285 | return (preset < 0 || preset >= f->presetNum ? TSF_NULL : f->presets[preset].presetName); |
||
1286 | } |
||
1287 | |||
1288 | TSFDEF const char* tsf_bank_get_presetname(const tsf* f, int bank, int preset_number) |
||
1289 | { |
||
1290 | return tsf_get_presetname(f, tsf_get_presetindex(f, bank, preset_number)); |
||
1291 | } |
||
1292 | |||
1293 | TSFDEF void tsf_set_output(tsf* f, enum TSFOutputMode outputmode, int samplerate, float global_gain_db) |
||
1294 | { |
||
1295 | f->outputmode = outputmode; |
||
1296 | f->outSampleRate = (float)(samplerate >= 1 ? samplerate : 44100.0f); |
||
1297 | f->globalGainDB = global_gain_db; |
||
1298 | } |
||
1299 | |||
1300 | TSFDEF void tsf_note_on(tsf* f, int preset_index, int key, float vel) |
||
1301 | { |
||
1302 | short midiVelocity = (short)(vel * 127); |
||
1303 | int voicePlayIndex; |
||
1304 | struct tsf_region *region, *regionEnd; |
||
1305 | |||
1306 | if (preset_index < 0 || preset_index >= f->presetNum) return; |
||
1307 | if (vel <= 0.0f) { tsf_note_off(f, preset_index, key); return; } |
||
1308 | |||
1309 | // Play all matching regions. |
||
1310 | voicePlayIndex = f->voicePlayIndex++; |
||
1311 | for (region = f->presets[preset_index].regions, regionEnd = region + f->presets[preset_index].regionNum; region != regionEnd; region++) |
||
1312 | { |
||
8770 | terminx | 1313 | struct tsf_voice *voice, *v, *vEnd; TSF_BOOL doLoop; float lowpassFilterQDB, lowpassFc; |
8752 | terminx | 1314 | if (key < region->lokey || key > region->hikey || midiVelocity < region->lovel || midiVelocity > region->hivel) continue; |
1315 | |||
1316 | voice = TSF_NULL, v = f->voices, vEnd = v + f->voiceNum; |
||
1317 | if (region->group) |
||
1318 | { |
||
1319 | for (; v != vEnd; v++) |
||
1320 | if (v->playingPreset == preset_index && v->region->group == region->group) tsf_voice_endquick(v, f->outSampleRate); |
||
1321 | else if (v->playingPreset == -1 && !voice) voice = v; |
||
1322 | } |
||
1323 | else for (; v != vEnd; v++) if (v->playingPreset == -1) { voice = v; break; } |
||
1324 | |||
1325 | if (!voice) |
||
1326 | { |
||
1327 | f->voiceNum += 4; |
||
1328 | f->voices = (struct tsf_voice*)TSF_REALLOC(f->voices, f->voiceNum * sizeof(struct tsf_voice)); |
||
1329 | voice = &f->voices[f->voiceNum - 4]; |
||
1330 | voice[1].playingPreset = voice[2].playingPreset = voice[3].playingPreset = -1; |
||
1331 | } |
||
1332 | |||
1333 | voice->region = region; |
||
1334 | voice->playingPreset = preset_index; |
||
1335 | voice->playingKey = key; |
||
1336 | voice->playIndex = voicePlayIndex; |
||
8775 | terminx | 1337 | voice->noteGainDB = f->globalGainDB - region->attenuation - tsf_gainToDecibels(1.0f / vel); |
8752 | terminx | 1338 | |
1339 | if (f->channels) |
||
1340 | { |
||
1341 | f->channels->setupVoice(f, voice); |
||
1342 | } |
||
1343 | else |
||
1344 | { |
||
1345 | tsf_voice_calcpitchratio(voice, 0, f->outSampleRate); |
||
1346 | // The SFZ spec is silent about the pan curve, but a 3dB pan law seems common. This sqrt() curve matches what Dimension LE does; Alchemy Free seems closer to sin(adjustedPan * pi/2). |
||
1347 | voice->panFactorLeft = TSF_SQRTF(0.5f - region->pan); |
||
1348 | voice->panFactorRight = TSF_SQRTF(0.5f + region->pan); |
||
1349 | } |
||
1350 | |||
1351 | // Offset/end. |
||
1352 | voice->sourceSamplePosition = region->offset; |
||
1353 | |||
1354 | // Loop. |
||
1355 | doLoop = (region->loop_mode != TSF_LOOPMODE_NONE && region->loop_start < region->loop_end); |
||
1356 | voice->loopStart = (doLoop ? region->loop_start : 0); |
||
1357 | voice->loopEnd = (doLoop ? region->loop_end : 0); |
||
1358 | |||
1359 | // Setup envelopes. |
||
1360 | tsf_voice_envelope_setup(&voice->ampenv, ®ion->ampenv, key, midiVelocity, TSF_TRUE, f->outSampleRate); |
||
1361 | tsf_voice_envelope_setup(&voice->modenv, ®ion->modenv, key, midiVelocity, TSF_FALSE, f->outSampleRate); |
||
1362 | |||
1363 | // Setup lowpass filter. |
||
8770 | terminx | 1364 | lowpassFc = (region->initialFilterFc <= 13500 ? tsf_cents2Hertz((float)region->initialFilterFc) / f->outSampleRate : 1.0f); |
1365 | lowpassFilterQDB = region->initialFilterQ / 10.0f; |
||
1366 | voice->lowpass.QInv = 1.0 / TSF_POW(10.0, (lowpassFilterQDB / 20.0)); |
||
8752 | terminx | 1367 | voice->lowpass.z1 = voice->lowpass.z2 = 0; |
8770 | terminx | 1368 | voice->lowpass.active = (lowpassFc < 0.499f); |
1369 | if (voice->lowpass.active) tsf_voice_lowpass_setup(&voice->lowpass, lowpassFc); |
||
8752 | terminx | 1370 | |
1371 | // Setup LFO filters. |
||
1372 | tsf_voice_lfo_setup(&voice->modlfo, region->delayModLFO, region->freqModLFO, f->outSampleRate); |
||
1373 | tsf_voice_lfo_setup(&voice->viblfo, region->delayVibLFO, region->freqVibLFO, f->outSampleRate); |
||
1374 | } |
||
1375 | } |
||
1376 | |||
1377 | TSFDEF int tsf_bank_note_on(tsf* f, int bank, int preset_number, int key, float vel) |
||
1378 | { |
||
1379 | int preset_index = tsf_get_presetindex(f, bank, preset_number); |
||
1380 | if (preset_index == -1) return 0; |
||
1381 | tsf_note_on(f, preset_index, key, vel); |
||
1382 | return 1; |
||
1383 | } |
||
1384 | |||
1385 | TSFDEF void tsf_note_off(tsf* f, int preset_index, int key) |
||
1386 | { |
||
1387 | struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum, *vMatchFirst = TSF_NULL, *vMatchLast = TSF_NULL; |
||
1388 | for (; v != vEnd; v++) |
||
1389 | { |
||
1390 | //Find the first and last entry in the voices list with matching preset, key and look up the smallest play index |
||
1391 | if (v->playingPreset != preset_index || v->playingKey != key || v->ampenv.segment >= TSF_SEGMENT_RELEASE) continue; |
||
1392 | else if (!vMatchFirst || v->playIndex < vMatchFirst->playIndex) vMatchFirst = vMatchLast = v; |
||
1393 | else if (v->playIndex == vMatchFirst->playIndex) vMatchLast = v; |
||
1394 | } |
||
1395 | if (!vMatchFirst) return; |
||
1396 | for (v = vMatchFirst; v <= vMatchLast; v++) |
||
1397 | { |
||
1398 | //Stop all voices with matching preset, key and the smallest play index which was enumerated above |
||
1399 | if (v != vMatchFirst && v != vMatchLast && |
||
1400 | (v->playIndex != vMatchFirst->playIndex || v->playingPreset != preset_index || v->playingKey != key || v->ampenv.segment >= TSF_SEGMENT_RELEASE)) continue; |
||
1401 | tsf_voice_end(v, f->outSampleRate); |
||
1402 | } |
||
1403 | } |
||
1404 | |||
1405 | TSFDEF int tsf_bank_note_off(tsf* f, int bank, int preset_number, int key) |
||
1406 | { |
||
1407 | int preset_index = tsf_get_presetindex(f, bank, preset_number); |
||
1408 | if (preset_index == -1) return 0; |
||
1409 | tsf_note_off(f, preset_index, key); |
||
1410 | return 1; |
||
1411 | } |
||
1412 | |||
1413 | TSFDEF void tsf_note_off_all(tsf* f) |
||
1414 | { |
||
1415 | struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum; |
||
1416 | for (; v != vEnd; v++) if (v->playingPreset != -1 && v->ampenv.segment < TSF_SEGMENT_RELEASE) |
||
1417 | tsf_voice_end(v, f->outSampleRate); |
||
1418 | } |
||
1419 | |||
1420 | TSFDEF int tsf_active_voice_count(tsf* f) |
||
1421 | { |
||
1422 | int count = 0; |
||
1423 | struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum; |
||
1424 | for (; v != vEnd; v++) if (v->playingPreset != -1) count++; |
||
1425 | return count; |
||
1426 | } |
||
1427 | |||
1428 | TSFDEF void tsf_render_short(tsf* f, short* buffer, int samples, int flag_mixing) |
||
1429 | { |
||
1430 | float *floatSamples; |
||
1431 | int channelSamples = (f->outputmode == TSF_MONO ? 1 : 2) * samples, floatBufferSize = channelSamples * sizeof(float); |
||
1432 | short* bufferEnd = buffer + channelSamples; |
||
1433 | if (floatBufferSize > f->outputSampleSize) |
||
1434 | { |
||
1435 | TSF_FREE(f->outputSamples); |
||
1436 | f->outputSamples = (float*)TSF_MALLOC(floatBufferSize); |
||
1437 | f->outputSampleSize = floatBufferSize; |
||
1438 | } |
||
1439 | |||
1440 | tsf_render_float(f, f->outputSamples, samples, TSF_FALSE); |
||
1441 | |||
1442 | floatSamples = f->outputSamples; |
||
1443 | if (flag_mixing) |
||
1444 | while (buffer != bufferEnd) |
||
1445 | { |
||
1446 | float v = *floatSamples++; |
||
1447 | int vi = *buffer + (v < -1.00004566f ? (int)-32768 : (v > 1.00001514f ? (int)32767 : (int)(v * 32767.5f))); |
||
1448 | *buffer++ = (vi < -32768 ? (short)-32768 : (vi > 32767 ? (short)32767 : (short)vi)); |
||
1449 | } |
||
1450 | else |
||
1451 | while (buffer != bufferEnd) |
||
1452 | { |
||
1453 | float v = *floatSamples++; |
||
1454 | *buffer++ = (v < -1.00004566f ? (short)-32768 : (v > 1.00001514f ? (short)32767 : (short)(v * 32767.5f))); |
||
1455 | } |
||
1456 | } |
||
1457 | |||
1458 | TSFDEF void tsf_render_float(tsf* f, float* buffer, int samples, int flag_mixing) |
||
1459 | { |
||
1460 | struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum; |
||
1461 | if (!flag_mixing) TSF_MEMSET(buffer, 0, (f->outputmode == TSF_MONO ? 1 : 2) * sizeof(float) * samples); |
||
1462 | for (; v != vEnd; v++) |
||
1463 | if (v->playingPreset != -1) |
||
1464 | tsf_voice_render(f, v, buffer, samples); |
||
1465 | } |
||
1466 | |||
1467 | static void tsf_channel_setup_voice(tsf* f, struct tsf_voice* v) |
||
1468 | { |
||
1469 | struct tsf_channel* c = &f->channels->channels[f->channels->activeChannel]; |
||
1470 | float newpan = v->region->pan + c->panOffset; |
||
1471 | v->playingChannel = f->channels->activeChannel; |
||
1472 | v->noteGainDB += c->gainDB; |
||
1473 | tsf_voice_calcpitchratio(v, (c->pitchWheel == 8192 ? c->tuning : ((c->pitchWheel / 16383.0f * c->pitchRange * 2.0f) - c->pitchRange + c->tuning)), f->outSampleRate); |
||
1474 | if (newpan <= -0.5f) { v->panFactorLeft = 1.0f; v->panFactorRight = 0.0f; } |
||
1475 | else if (newpan >= 0.5f) { v->panFactorLeft = 0.0f; v->panFactorRight = 1.0f; } |
||
1476 | else { v->panFactorLeft = TSF_SQRTF(0.5f - newpan); v->panFactorRight = TSF_SQRTF(0.5f + newpan); } |
||
1477 | } |
||
1478 | |||
1479 | static struct tsf_channel* tsf_channel_init(tsf* f, int channel) |
||
1480 | { |
||
1481 | int i; |
||
1482 | if (f->channels && channel < f->channels->channelNum) return &f->channels->channels[channel]; |
||
1483 | if (!f->channels) |
||
1484 | { |
||
1485 | f->channels = (struct tsf_channels*)TSF_MALLOC(sizeof(struct tsf_channels)); |
||
1486 | f->channels->setupVoice = &tsf_channel_setup_voice; |
||
1487 | f->channels->channels = NULL; |
||
1488 | f->channels->channelNum = 0; |
||
1489 | f->channels->activeChannel = 0; |
||
1490 | } |
||
1491 | i = f->channels->channelNum; |
||
1492 | f->channels->channelNum = channel + 1; |
||
1493 | f->channels->channels = (struct tsf_channel*)TSF_REALLOC(f->channels->channels, f->channels->channelNum * sizeof(struct tsf_channel)); |
||
1494 | for (; i <= channel; i++) |
||
1495 | { |
||
1496 | struct tsf_channel* c = &f->channels->channels[i]; |
||
1497 | c->presetIndex = c->bank = 0; |
||
1498 | c->pitchWheel = c->midiPan = 8192; |
||
1499 | c->midiVolume = c->midiExpression = 16383; |
||
1500 | c->midiRPN = 0xFFFF; |
||
1501 | c->midiData = 0; |
||
1502 | c->panOffset = 0.0f; |
||
1503 | c->gainDB = 0.0f; |
||
1504 | c->pitchRange = 2.0f; |
||
1505 | c->tuning = 0.0f; |
||
1506 | } |
||
1507 | return &f->channels->channels[channel]; |
||
1508 | } |
||
1509 | |||
1510 | static void tsf_channel_applypitch(tsf* f, int channel, struct tsf_channel* c) |
||
1511 | { |
||
1512 | struct tsf_voice *v, *vEnd; |
||
1513 | float pitchShift = (c->pitchWheel == 8192 ? c->tuning : ((c->pitchWheel / 16383.0f * c->pitchRange * 2.0f) - c->pitchRange + c->tuning)); |
||
1514 | for (v = f->voices, vEnd = v + f->voiceNum; v != vEnd; v++) |
||
1515 | if (v->playingChannel == channel && v->playingPreset != -1) |
||
1516 | tsf_voice_calcpitchratio(v, pitchShift, f->outSampleRate); |
||
1517 | } |
||
1518 | |||
1519 | TSFDEF void tsf_channel_set_presetindex(tsf* f, int channel, int preset_index) |
||
1520 | { |
||
1521 | tsf_channel_init(f, channel)->presetIndex = (unsigned short)preset_index; |
||
1522 | } |
||
1523 | |||
1524 | TSFDEF int tsf_channel_set_presetnumber(tsf* f, int channel, int preset_number, int flag_mididrums) |
||
1525 | { |
||
1526 | struct tsf_channel *c = tsf_channel_init(f, channel); |
||
1527 | int preset_index; |
||
1528 | if (flag_mididrums) |
||
1529 | { |
||
1530 | preset_index = tsf_get_presetindex(f, 128 | (c->bank & 0x7FFF), preset_number); |
||
1531 | if (preset_index == -1) preset_index = tsf_get_presetindex(f, 128, preset_number); |
||
1532 | if (preset_index == -1) preset_index = tsf_get_presetindex(f, 128, 0); |
||
1533 | if (preset_index == -1) preset_index = tsf_get_presetindex(f, (c->bank & 0x7FFF), preset_number); |
||
1534 | } |
||
1535 | else preset_index = tsf_get_presetindex(f, (c->bank & 0x7FFF), preset_number); |
||
1536 | if (preset_index == -1) preset_index = tsf_get_presetindex(f, 0, preset_number); |
||
1537 | if (preset_index != -1) |
||
1538 | { |
||
1539 | c->presetIndex = (unsigned short)preset_index; |
||
1540 | return 1; |
||
1541 | } |
||
1542 | return 0; |
||
1543 | } |
||
1544 | |||
1545 | TSFDEF void tsf_channel_set_bank(tsf* f, int channel, int bank) |
||
1546 | { |
||
1547 | tsf_channel_init(f, channel)->bank = (unsigned short)bank; |
||
1548 | } |
||
1549 | |||
1550 | TSFDEF int tsf_channel_set_bank_preset(tsf* f, int channel, int bank, int preset_number) |
||
1551 | { |
||
1552 | struct tsf_channel *c = tsf_channel_init(f, channel); |
||
1553 | int preset_index = tsf_get_presetindex(f, bank, preset_number); |
||
1554 | if (preset_index == -1) return 0; |
||
1555 | c->presetIndex = (unsigned short)preset_index; |
||
1556 | c->bank = (unsigned short)bank; |
||
1557 | return 1; |
||
1558 | } |
||
1559 | |||
1560 | TSFDEF void tsf_channel_set_pan(tsf* f, int channel, float pan) |
||
1561 | { |
||
1562 | struct tsf_voice *v, *vEnd; |
||
1563 | for (v = f->voices, vEnd = v + f->voiceNum; v != vEnd; v++) |
||
1564 | if (v->playingChannel == channel && v->playingPreset != -1) |
||
1565 | { |
||
1566 | float newpan = v->region->pan + pan - 0.5f; |
||
1567 | if (newpan <= -0.5f) { v->panFactorLeft = 1.0f; v->panFactorRight = 0.0f; } |
||
1568 | else if (newpan >= 0.5f) { v->panFactorLeft = 0.0f; v->panFactorRight = 1.0f; } |
||
1569 | else { v->panFactorLeft = TSF_SQRTF(0.5f - newpan); v->panFactorRight = TSF_SQRTF(0.5f + newpan); } |
||
1570 | } |
||
1571 | tsf_channel_init(f, channel)->panOffset = pan - 0.5f; |
||
1572 | } |
||
1573 | |||
1574 | TSFDEF void tsf_channel_set_volume(tsf* f, int channel, float volume) |
||
1575 | { |
||
1576 | struct tsf_channel *c = tsf_channel_init(f, channel); |
||
1577 | float gainDB = tsf_gainToDecibels(volume), gainDBChange = gainDB - c->gainDB; |
||
1578 | struct tsf_voice *v, *vEnd; |
||
1579 | if (gainDBChange == 0) return; |
||
1580 | for (v = f->voices, vEnd = v + f->voiceNum; v != vEnd; v++) |
||
1581 | if (v->playingChannel == channel && v->playingPreset != -1) |
||
1582 | v->noteGainDB += gainDBChange; |
||
1583 | c->gainDB = gainDB; |
||
1584 | } |
||
1585 | |||
1586 | TSFDEF void tsf_channel_set_pitchwheel(tsf* f, int channel, int pitch_wheel) |
||
1587 | { |
||
1588 | struct tsf_channel *c = tsf_channel_init(f, channel); |
||
1589 | if (c->pitchWheel == pitch_wheel) return; |
||
1590 | c->pitchWheel = (unsigned short)pitch_wheel; |
||
1591 | tsf_channel_applypitch(f, channel, c); |
||
1592 | } |
||
1593 | |||
1594 | TSFDEF void tsf_channel_set_pitchrange(tsf* f, int channel, float pitch_range) |
||
1595 | { |
||
1596 | struct tsf_channel *c = tsf_channel_init(f, channel); |
||
1597 | if (c->pitchRange == pitch_range) return; |
||
1598 | c->pitchRange = pitch_range; |
||
1599 | if (c->pitchWheel != 8192) tsf_channel_applypitch(f, channel, c); |
||
1600 | } |
||
1601 | |||
1602 | TSFDEF void tsf_channel_set_tuning(tsf* f, int channel, float tuning) |
||
1603 | { |
||
1604 | struct tsf_channel *c = tsf_channel_init(f, channel); |
||
1605 | if (c->tuning == tuning) return; |
||
1606 | c->tuning = tuning; |
||
1607 | tsf_channel_applypitch(f, channel, c); |
||
1608 | } |
||
1609 | |||
1610 | TSFDEF void tsf_channel_note_on(tsf* f, int channel, int key, float vel) |
||
1611 | { |
||
1612 | if (!f->channels || channel >= f->channels->channelNum) return; |
||
1613 | f->channels->activeChannel = channel; |
||
1614 | tsf_note_on(f, f->channels->channels[channel].presetIndex, key, vel); |
||
1615 | } |
||
1616 | |||
1617 | TSFDEF void tsf_channel_note_off(tsf* f, int channel, int key) |
||
1618 | { |
||
1619 | struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum, *vMatchFirst = TSF_NULL, *vMatchLast = TSF_NULL; |
||
1620 | for (; v != vEnd; v++) |
||
1621 | { |
||
1622 | //Find the first and last entry in the voices list with matching channel, key and look up the smallest play index |
||
1623 | if (v->playingPreset == -1 || v->playingChannel != channel || v->playingKey != key || v->ampenv.segment >= TSF_SEGMENT_RELEASE) continue; |
||
1624 | else if (!vMatchFirst || v->playIndex < vMatchFirst->playIndex) vMatchFirst = vMatchLast = v; |
||
1625 | else if (v->playIndex == vMatchFirst->playIndex) vMatchLast = v; |
||
1626 | } |
||
1627 | if (!vMatchFirst) return; |
||
1628 | for (v = vMatchFirst; v <= vMatchLast; v++) |
||
1629 | { |
||
1630 | //Stop all voices with matching channel, key and the smallest play index which was enumerated above |
||
1631 | if (v != vMatchFirst && v != vMatchLast && |
||
1632 | (v->playIndex != vMatchFirst->playIndex || v->playingPreset == -1 || v->playingChannel != channel || v->playingKey != key || v->ampenv.segment >= TSF_SEGMENT_RELEASE)) continue; |
||
1633 | tsf_voice_end(v, f->outSampleRate); |
||
1634 | } |
||
1635 | } |
||
1636 | |||
1637 | TSFDEF void tsf_channel_note_off_all(tsf* f, int channel) |
||
1638 | { |
||
1639 | struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum; |
||
1640 | for (; v != vEnd; v++) |
||
1641 | if (v->playingPreset != -1 && v->playingChannel == channel && v->ampenv.segment < TSF_SEGMENT_RELEASE) |
||
1642 | tsf_voice_end(v, f->outSampleRate); |
||
1643 | } |
||
1644 | |||
1645 | TSFDEF void tsf_channel_sounds_off_all(tsf* f, int channel) |
||
1646 | { |
||
1647 | struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum; |
||
1648 | for (; v != vEnd; v++) |
||
1649 | if (v->playingPreset != -1 && v->playingChannel == channel && (v->ampenv.segment < TSF_SEGMENT_RELEASE || v->ampenv.parameters.release)) |
||
1650 | tsf_voice_endquick(v, f->outSampleRate); |
||
1651 | } |
||
1652 | |||
1653 | TSFDEF void tsf_channel_midi_control(tsf* f, int channel, int controller, int control_value) |
||
1654 | { |
||
1655 | struct tsf_channel* c = tsf_channel_init(f, channel); |
||
1656 | switch (controller) |
||
1657 | { |
||
1658 | case 7 /*VOLUME_MSB*/ : c->midiVolume = (unsigned short)((c->midiVolume & 0x7F ) | (control_value << 7)); goto TCMC_SET_VOLUME; |
||
1659 | case 39 /*VOLUME_LSB*/ : c->midiVolume = (unsigned short)((c->midiVolume & 0x3F80) | control_value); goto TCMC_SET_VOLUME; |
||
1660 | case 11 /*EXPRESSION_MSB*/ : c->midiExpression = (unsigned short)((c->midiExpression & 0x7F ) | (control_value << 7)); goto TCMC_SET_VOLUME; |
||
1661 | case 43 /*EXPRESSION_LSB*/ : c->midiExpression = (unsigned short)((c->midiExpression & 0x3F80) | control_value); goto TCMC_SET_VOLUME; |
||
1662 | case 10 /*PAN_MSB*/ : c->midiPan = (unsigned short)((c->midiPan & 0x7F ) | (control_value << 7)); goto TCMC_SET_PAN; |
||
1663 | case 42 /*PAN_LSB*/ : c->midiPan = (unsigned short)((c->midiPan & 0x3F80) | control_value); goto TCMC_SET_PAN; |
||
1664 | case 6 /*DATA_ENTRY_MSB*/ : c->midiData = (unsigned short)((c->midiData & 0x7F) | (control_value << 7)); goto TCMC_SET_DATA; |
||
1665 | case 38 /*DATA_ENTRY_LSB*/ : c->midiData = (unsigned short)((c->midiData & 0x3F80) | control_value); goto TCMC_SET_DATA; |
||
1666 | case 0 /*BANK_SELECT_MSB*/ : c->bank = (unsigned short)(0x8000 | control_value); return; //bank select MSB alone acts like LSB |
||
1667 | case 32 /*BANK_SELECT_LSB*/ : c->bank = (unsigned short)((c->bank & 0x8000 ? ((c->bank & 0x7F) << 7) : 0) | control_value); return; |
||
1668 | case 101 /*RPN_MSB*/ : c->midiRPN = (unsigned short)(((c->midiRPN == 0xFFFF ? 0 : c->midiRPN) & 0x7F ) | (control_value << 7)); return; |
||
1669 | case 100 /*RPN_LSB*/ : c->midiRPN = (unsigned short)(((c->midiRPN == 0xFFFF ? 0 : c->midiRPN) & 0x3F80) | control_value); return; |
||
1670 | case 98 /*NRPN_LSB*/ : c->midiRPN = 0xFFFF; return; |
||
1671 | case 99 /*NRPN_MSB*/ : c->midiRPN = 0xFFFF; return; |
||
1672 | case 120 /*ALL_SOUND_OFF*/ : tsf_channel_sounds_off_all(f, channel); return; |
||
1673 | case 123 /*ALL_NOTES_OFF*/ : tsf_channel_note_off_all(f, channel); return; |
||
1674 | case 121 /*ALL_CTRL_OFF*/ : |
||
1675 | c->midiVolume = c->midiExpression = 16383; |
||
1676 | c->midiPan = 8192; |
||
1677 | c->bank = 0; |
||
1678 | tsf_channel_set_volume(f, channel, 1.0f); |
||
1679 | tsf_channel_set_pan(f, channel, 0.5f); |
||
1680 | tsf_channel_set_pitchrange(f, channel, 2.0f); |
||
1681 | return; |
||
1682 | } |
||
1683 | return; |
||
1684 | TCMC_SET_VOLUME: |
||
1685 | //Raising to the power of 3 seems to result in a decent sounding volume curve for MIDI |
||
1686 | tsf_channel_set_volume(f, channel, TSF_POWF((c->midiVolume / 16383.0f) * (c->midiExpression / 16383.0f), 3.0f)); |
||
1687 | return; |
||
1688 | TCMC_SET_PAN: |
||
1689 | tsf_channel_set_pan(f, channel, c->midiPan / 16383.0f); |
||
1690 | return; |
||
1691 | TCMC_SET_DATA: |
||
1692 | if (c->midiRPN == 0) tsf_channel_set_pitchrange(f, channel, (c->midiData >> 7) + 0.01f * (c->midiData & 0x7F)); |
||
1693 | else if (c->midiRPN == 1) tsf_channel_set_tuning(f, channel, (int)c->tuning + ((float)c->midiData - 8192.0f) / 8192.0f); //fine tune |
||
1694 | else if (c->midiRPN == 2 && controller == 6) tsf_channel_set_tuning(f, channel, ((float)control_value - 64.0f) + (c->tuning - (int)c->tuning)); //coarse tune |
||
1695 | return; |
||
1696 | } |
||
1697 | |||
1698 | TSFDEF int tsf_channel_get_preset_index(tsf* f, int channel) |
||
1699 | { |
||
1700 | return (f->channels && channel < f->channels->channelNum ? f->channels->channels[channel].presetIndex : 0); |
||
1701 | } |
||
1702 | |||
1703 | TSFDEF int tsf_channel_get_preset_bank(tsf* f, int channel) |
||
1704 | { |
||
1705 | return (f->channels && channel < f->channels->channelNum ? (f->channels->channels[channel].bank & 0x7FFF) : 0); |
||
1706 | } |
||
1707 | |||
1708 | TSFDEF int tsf_channel_get_preset_number(tsf* f, int channel) |
||
1709 | { |
||
1710 | return (f->channels && channel < f->channels->channelNum ? f->presets[f->channels->channels[channel].presetIndex].preset : 0); |
||
1711 | } |
||
1712 | |||
1713 | TSFDEF float tsf_channel_get_pan(tsf* f, int channel) |
||
1714 | { |
||
1715 | return (f->channels && channel < f->channels->channelNum ? f->channels->channels[channel].panOffset - 0.5f : 0.5f); |
||
1716 | } |
||
1717 | |||
1718 | TSFDEF float tsf_channel_get_volume(tsf* f, int channel) |
||
1719 | { |
||
1720 | return (f->channels && channel < f->channels->channelNum ? tsf_decibelsToGain(f->channels->channels[channel].gainDB) : 1.0f); |
||
1721 | } |
||
1722 | |||
1723 | TSFDEF int tsf_channel_get_pitchwheel(tsf* f, int channel) |
||
1724 | { |
||
1725 | return (f->channels && channel < f->channels->channelNum ? f->channels->channels[channel].pitchWheel : 8192); |
||
1726 | } |
||
1727 | |||
1728 | TSFDEF float tsf_channel_get_pitchrange(tsf* f, int channel) |
||
1729 | { |
||
1730 | return (f->channels && channel < f->channels->channelNum ? f->channels->channels[channel].pitchRange : 2.0f); |
||
1731 | } |
||
1732 | |||
1733 | TSFDEF float tsf_channel_get_tuning(tsf* f, int channel) |
||
1734 | { |
||
1735 | return (f->channels && channel < f->channels->channelNum ? f->channels->channels[channel].tuning : 0.0f); |
||
1736 | } |
||
1737 | |||
1738 | #ifdef __cplusplus |
||
1739 | } |
||
1740 | #endif |
||
1741 | |||
1742 | #endif //TSF_IMPLEMENTATION |