Subversion Repositories eduke32

Rev

Rev 8754 | Rev 8775 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 8754 Rev 8770
1
/* TinySoundFont - v0.8 - SoundFont2 synthesizer - https://github.com/schellingb/TinySoundFont
1
/* TinySoundFont - v0.8 - SoundFont2 synthesizer - https://github.com/schellingb/TinySoundFont
2
                                     no warranty implied; use at your own risk
2
                                     no warranty implied; use at your own risk
3
   Do this:
3
   Do this:
4
      #define TSF_IMPLEMENTATION
4
      #define TSF_IMPLEMENTATION
5
   before you include this file in *one* C or C++ file to create the 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:
6
   // i.e. it should look like this:
7
   #include ...
7
   #include ...
8
   #include ...
8
   #include ...
9
   #define TSF_IMPLEMENTATION
9
   #define TSF_IMPLEMENTATION
10
   #include "tsf.h"
10
   #include "tsf.h"
11

11

12
   [OPTIONAL] #define TSF_NO_STDIO to remove stdio dependency
12
   [OPTIONAL] #define TSF_NO_STDIO to remove stdio dependency
13
   [OPTIONAL] #define TSF_MALLOC, TSF_REALLOC, and TSF_FREE to avoid stdlib.h
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
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
15
   [OPTIONAL] #define TSF_POW, TSF_POWF, TSF_EXPF, TSF_LOG, TSF_TAN, TSF_LOG10, TSF_SQRT to avoid math.h
16

16

17
   NOT YET IMPLEMENTED
17
   NOT YET IMPLEMENTED
18
     - Support for ChorusEffectsSend and ReverbEffectsSend generators
18
     - Support for ChorusEffectsSend and ReverbEffectsSend generators
19
     - Better low-pass filter without lowering performance too much
19
     - Better low-pass filter without lowering performance too much
20
     - Support for modulators
20
     - Support for modulators
21

21

22
   LICENSE (MIT)
22
   LICENSE (MIT)
23

23

24
   Copyright (C) 2017, 2018 Bernhard Schelling
24
   Copyright (C) 2017, 2018 Bernhard Schelling
25
   Based on SFZero, Copyright (C) 2012 Steve Folta (https://github.com/stevefolta/SFZero)
25
   Based on SFZero, Copyright (C) 2012 Steve Folta (https://github.com/stevefolta/SFZero)
26

26

27
   Permission is hereby granted, free of charge, to any person obtaining a copy of this
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
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,
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
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:
31
   to whom the Software is furnished to do so, subject to the following conditions:
32

32

33
   The above copyright notice and this permission notice shall be included in all
33
   The above copyright notice and this permission notice shall be included in all
34
   copies or substantial portions of the Software.
34
   copies or substantial portions of the Software.
35

35

36
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
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
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
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,
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
40
   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
41
   USE OR OTHER DEALINGS IN THE SOFTWARE.
41
   USE OR OTHER DEALINGS IN THE SOFTWARE.
42

42

43
*/
43
*/
44
44
45
#ifndef TSF_INCLUDE_TSF_INL
45
#ifndef TSF_INCLUDE_TSF_INL
46
#define TSF_INCLUDE_TSF_INL
46
#define TSF_INCLUDE_TSF_INL
47
47
48
#ifdef __cplusplus
48
#ifdef __cplusplus
49
extern "C" {
49
extern "C" {
50
#  define CPP_DEFAULT0 = 0
50
#  define CPP_DEFAULT0 = 0
51
#else
51
#else
52
#  define CPP_DEFAULT0
52
#  define CPP_DEFAULT0
53
#endif
53
#endif
54
54
55
//define this if you want the API functions to be static
55
//define this if you want the API functions to be static
56
#ifdef TSF_STATIC
56
#ifdef TSF_STATIC
57
#define TSFDEF static
57
#define TSFDEF static
58
#else
58
#else
59
#define TSFDEF extern
59
#define TSFDEF extern
60
#endif
60
#endif
61
61
62
// The load functions will return a pointer to a struct tsf which all functions
62
// The load functions will return a pointer to a struct tsf which all functions
63
// thereafter take as the first parameter.
63
// thereafter take as the first parameter.
64
// On error the tsf_load* functions will return NULL most likely due to invalid
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).
65
// data (or if the file did not exist in tsf_load_filename).
66
typedef struct tsf tsf;
66
typedef struct tsf tsf;
67
67
68
#ifndef TSF_NO_STDIO
68
#ifndef TSF_NO_STDIO
69
// Directly load a SoundFont from a .sf2 file path
69
// Directly load a SoundFont from a .sf2 file path
70
TSFDEF tsf* tsf_load_filename(const char* filename);
70
TSFDEF tsf* tsf_load_filename(const char* filename);
71
#endif
71
#endif
72
72
73
// Load a SoundFont from a block of memory
73
// Load a SoundFont from a block of memory
74
TSFDEF tsf* tsf_load_memory(const void* buffer, int size);
74
TSFDEF tsf* tsf_load_memory(const void* buffer, int size);
75
75
76
// Stream structure for the generic loading
76
// Stream structure for the generic loading
77
struct tsf_stream
77
struct tsf_stream
78
{
78
{
79
        // Custom data given to the functions as the first parameter
79
        // Custom data given to the functions as the first parameter
80
        void* data;
80
        void* data;
81
81
82
        // Function pointer will be called to read 'size' bytes into ptr (returns number of read bytes)
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);
83
        int (*read)(void* data, void* ptr, unsigned int size);
84
84
85
        // Function pointer will be called to skip ahead over 'count' bytes (returns 1 on success, 0 on error)
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);
86
        int (*skip)(void* data, unsigned int count);
87
};
87
};
88
88
89
// Generic SoundFont loading method using the stream structure above
89
// Generic SoundFont loading method using the stream structure above
90
TSFDEF tsf* tsf_load(struct tsf_stream* stream);
90
TSFDEF tsf* tsf_load(struct tsf_stream* stream);
91
91
92
// Free the memory related to this tsf instance
92
// Free the memory related to this tsf instance
93
TSFDEF void tsf_close(tsf* f);
93
TSFDEF void tsf_close(tsf* f);
94
94
95
// Stop all playing notes immediatly and reset all channel parameters
95
// Stop all playing notes immediatly and reset all channel parameters
96
TSFDEF void tsf_reset(tsf* f);
96
TSFDEF void tsf_reset(tsf* f);
97
97
98
// Returns the preset index from a bank and preset number, or -1 if it does not exist in the loaded SoundFont
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);
99
TSFDEF int tsf_get_presetindex(const tsf* f, int bank, int preset_number);
100
100
101
// Returns the number of presets in the loaded SoundFont
101
// Returns the number of presets in the loaded SoundFont
102
TSFDEF int tsf_get_presetcount(const tsf* f);
102
TSFDEF int tsf_get_presetcount(const tsf* f);
103
103
104
// Returns the name of a preset index >= 0 and < tsf_get_presetcount()
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);
105
TSFDEF const char* tsf_get_presetname(const tsf* f, int preset_index);
106
106
107
// Returns the name of a preset by bank and preset number
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);
108
TSFDEF const char* tsf_bank_get_presetname(const tsf* f, int bank, int preset_number);
109
109
110
// Supported output modes by the render methods
110
// Supported output modes by the render methods
111
enum TSFOutputMode
111
enum TSFOutputMode
112
{
112
{
113
        // Two channels with single left/right samples one after another
113
        // Two channels with single left/right samples one after another
114
        TSF_STEREO_INTERLEAVED,
114
        TSF_STEREO_INTERLEAVED,
115
        // Two channels with all samples for the left channel first then right
115
        // Two channels with all samples for the left channel first then right
116
        TSF_STEREO_UNWEAVED,
116
        TSF_STEREO_UNWEAVED,
117
        // A single channel (stereo instruments are mixed into center)
117
        // A single channel (stereo instruments are mixed into center)
118
        TSF_MONO,
118
        TSF_MONO,
119
};
119
};
120
120
121
// Thread safety:
121
// Thread safety:
122
// Your audio output which calls the tsf_render* functions will most likely
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
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
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.
125
// mutex needs to be used so they are not called at the same time.
126
126
127
// Setup the parameters for the voice render methods
127
// Setup the parameters for the voice render methods
128
//   outputmode: if mono or stereo and how stereo channel data is ordered
128
//   outputmode: if mono or stereo and how stereo channel data is ordered
129
//   samplerate: the number of samples per second (output frequency)
129
//   samplerate: the number of samples per second (output frequency)
130
//   global_gain_db: volume gain in decibels (>0 means higher, <0 means lower)
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);
131
TSFDEF void tsf_set_output(tsf* f, enum TSFOutputMode outputmode, int samplerate, float global_gain_db CPP_DEFAULT0);
132
132
133
// Start playing a note
133
// Start playing a note
134
//   preset_index: preset index >= 0 and < tsf_get_presetcount()
134
//   preset_index: preset index >= 0 and < tsf_get_presetcount()
135
//   key: note value between 0 and 127 (60 being middle C)
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)
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)
137
//   bank: instrument bank number (alternative to preset_index)
138
//   preset_number: preset 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)
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);
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);
141
TSFDEF int  tsf_bank_note_on(tsf* f, int bank, int preset_number, int key, float vel);
142
142
143
// Stop playing a note
143
// Stop playing a note
144
//   (bank_note_off returns 0 if preset does not exist, otherwise 1)
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);
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);
146
TSFDEF int  tsf_bank_note_off(tsf* f, int bank, int preset_number, int key);
147
147
148
// Stop playing all notes (end with sustain and release)
148
// Stop playing all notes (end with sustain and release)
149
TSFDEF void tsf_note_off_all(tsf* f);
149
TSFDEF void tsf_note_off_all(tsf* f);
150
150
151
// Returns the number of active voices
151
// Returns the number of active voices
152
TSFDEF int tsf_active_voice_count(tsf* f);
152
TSFDEF int tsf_active_voice_count(tsf* f);
153
153
154
// Render output samples into a buffer
154
// Render output samples into a buffer
155
// You can either render as signed 16-bit values (tsf_render_short) or
155
// You can either render as signed 16-bit values (tsf_render_short) or
156
// as 32-bit float values (tsf_render_float)
156
// as 32-bit float values (tsf_render_float)
157
//   buffer: target buffer of size samples * output_channels * sizeof(type)
157
//   buffer: target buffer of size samples * output_channels * sizeof(type)
158
//   samples: number of samples to render
158
//   samples: number of samples to render
159
//   flag_mixing: if 0 clear the buffer first, otherwise mix into existing data
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);
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);
161
TSFDEF void tsf_render_float(tsf* f, float* buffer, int samples, int flag_mixing CPP_DEFAULT0);
162
162
163
// Higher level channel based functions, set up channel parameters
163
// Higher level channel based functions, set up channel parameters
164
//   channel: channel number
164
//   channel: channel number
165
//   preset_index: preset index >= 0 and < tsf_get_presetcount()
165
//   preset_index: preset index >= 0 and < tsf_get_presetcount()
166
//   preset_number: preset number (alternative to preset_index)
166
//   preset_number: preset number (alternative to preset_index)
167
//   flag_mididrums: 0 for normal channels, otherwise apply MIDI drum channel rules
167
//   flag_mididrums: 0 for normal channels, otherwise apply MIDI drum channel rules
168
//   bank: instrument bank number (alternative to preset_index)
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)
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)
170
//   volume: linear volume scale factor (default 1.0 full)
171
//   pitch_wheel: pitch wheel position 0 to 16383 (default 8192 unpitched)
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)
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)
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)
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);
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);
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);
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);
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);
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);
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);
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);
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);
183
TSFDEF void tsf_channel_set_tuning(tsf* f, int channel, float tuning);
184
184
185
// Start or stop playing notes on a channel (needs channel preset to be set)
185
// Start or stop playing notes on a channel (needs channel preset to be set)
186
//   channel: channel number
186
//   channel: channel number
187
//   key: note value between 0 and 127 (60 being middle C)
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)
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);
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);
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
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
192
TSFDEF void tsf_channel_sounds_off_all(tsf* f, int channel); //end immediatly
193
193
194
// Apply a MIDI control change to the channel (not all controllers are supported!)
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);
195
TSFDEF void tsf_channel_midi_control(tsf* f, int channel, int controller, int control_value);
196
196
197
// Get current values set on the channels
197
// Get current values set on the channels
198
TSFDEF int tsf_channel_get_preset_index(tsf* f, int channel);
198
TSFDEF int tsf_channel_get_preset_index(tsf* f, int channel);
199
TSFDEF int tsf_channel_get_preset_bank(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);
200
TSFDEF int tsf_channel_get_preset_number(tsf* f, int channel);
201
TSFDEF float tsf_channel_get_pan(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);
202
TSFDEF float tsf_channel_get_volume(tsf* f, int channel);
203
TSFDEF int tsf_channel_get_pitchwheel(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);
204
TSFDEF float tsf_channel_get_pitchrange(tsf* f, int channel);
205
TSFDEF float tsf_channel_get_tuning(tsf* f, int channel);
205
TSFDEF float tsf_channel_get_tuning(tsf* f, int channel);
206
206
207
#ifdef __cplusplus
207
#ifdef __cplusplus
208
#  undef CPP_DEFAULT0
208
#  undef CPP_DEFAULT0
209
}
209
}
210
#endif
210
#endif
211
211
212
// end header
212
// end header
213
// ---------------------------------------------------------------------------------------------------------
213
// ---------------------------------------------------------------------------------------------------------
214
#endif //TSF_INCLUDE_TSF_INL
214
#endif //TSF_INCLUDE_TSF_INL
215
215
216
#ifdef TSF_IMPLEMENTATION
216
#ifdef TSF_IMPLEMENTATION
217
217
218
// The lower this block size is the more accurate the effects are.
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.
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.
220
// If LFO affects the low-pass filter it can be hearable even as low as 8.
221
#ifndef TSF_RENDER_EFFECTSAMPLEBLOCK
221
#ifndef TSF_RENDER_EFFECTSAMPLEBLOCK
222
#define TSF_RENDER_EFFECTSAMPLEBLOCK 64
222
#define TSF_RENDER_EFFECTSAMPLEBLOCK 64
223
#endif
223
#endif
224
224
225
// Grace release time for quick voice off (avoid clicking noise)
225
// Grace release time for quick voice off (avoid clicking noise)
226
#define TSF_FASTRELEASETIME 0.01f
226
#define TSF_FASTRELEASETIME 0.01f
227
227
228
#if !defined(TSF_MALLOC) || !defined(TSF_FREE) || !defined(TSF_REALLOC)
228
#if !defined(TSF_MALLOC) || !defined(TSF_FREE) || !defined(TSF_REALLOC)
229
#  include <stdlib.h>
229
#  include <stdlib.h>
230
#  define TSF_MALLOC  malloc
230
#  define TSF_MALLOC  malloc
231
#  define TSF_FREE    free
231
#  define TSF_FREE    free
232
#  define TSF_REALLOC realloc
232
#  define TSF_REALLOC realloc
233
#endif
233
#endif
234
234
235
#if !defined(TSF_MEMCPY) || !defined(TSF_MEMSET)
235
#if !defined(TSF_MEMCPY) || !defined(TSF_MEMSET)
236
#  include <string.h>
236
#  include <string.h>
237
#  define TSF_MEMCPY  memcpy
237
#  define TSF_MEMCPY  memcpy
238
#  define TSF_MEMSET  memset
238
#  define TSF_MEMSET  memset
239
#endif
239
#endif
240
240
241
#if !defined(TSF_POW) || !defined(TSF_POWF) || !defined(TSF_EXPF) || !defined(TSF_LOG) || !defined(TSF_TAN) || !defined(TSF_LOG10) || !defined(TSF_SQRT)
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>
242
#  include <math.h>
243
#  if !defined(__cplusplus) && !defined(NAN) && !defined(powf) && !defined(expf) && !defined(sqrtf)
243
#  if !defined(__cplusplus) && !defined(NAN) && !defined(powf) && !defined(expf) && !defined(sqrtf)
244
#    define powf (float)pow // deal with old math.h
244
#    define powf (float)pow // deal with old math.h
245
#    define expf (float)exp // files that come without
245
#    define expf (float)exp // files that come without
246
#    define sqrtf (float)sqrt // powf, expf and sqrtf
246
#    define sqrtf (float)sqrt // powf, expf and sqrtf
247
#  endif
247
#  endif
248
#  define TSF_POW     pow
248
#  define TSF_POW     pow
249
#  define TSF_POWF    powf
249
#  define TSF_POWF    powf
250
#  define TSF_EXPF    expf
250
#  define TSF_EXPF    expf
251
#  define TSF_LOG     log
251
#  define TSF_LOG     log
252
#  define TSF_TAN     tan
252
#  define TSF_TAN     tan
253
#  define TSF_LOG10   log10
253
#  define TSF_LOG10   log10
254
#  define TSF_SQRTF   sqrtf
254
#  define TSF_SQRTF   sqrtf
255
#endif
255
#endif
256
256
257
#ifndef TSF_NO_STDIO
257
#ifndef TSF_NO_STDIO
258
#  include <stdio.h>
258
#  include <stdio.h>
259
#endif
259
#endif
260
260
261
#define TSF_TRUE 1
261
#define TSF_TRUE 1
262
#define TSF_FALSE 0
262
#define TSF_FALSE 0
263
#define TSF_BOOL char
263
#define TSF_BOOL char
264
#define TSF_PI 3.14159265358979323846264338327950288
264
#define TSF_PI 3.14159265358979323846264338327950288
265
#define TSF_NULL 0
265
#define TSF_NULL 0
266
266
267
#ifdef __cplusplus
267
#ifdef __cplusplus
268
extern "C" {
268
extern "C" {
269
#endif
269
#endif
270
270
271
typedef char tsf_fourcc[4];
271
typedef char tsf_fourcc[4];
272
typedef signed char tsf_s8;
272
typedef signed char tsf_s8;
273
typedef unsigned char tsf_u8;
273
typedef unsigned char tsf_u8;
274
typedef unsigned short tsf_u16;
274
typedef unsigned short tsf_u16;
275
typedef signed short tsf_s16;
275
typedef signed short tsf_s16;
276
typedef unsigned int tsf_u32;
276
typedef unsigned int tsf_u32;
277
typedef char tsf_char20[20];
277
typedef char tsf_char20[20];
278
278
279
#define TSF_FourCCEquals(value1, value2) (value1[0] == value2[0] && value1[1] == value2[1] && value1[2] == value2[2] && value1[3] == value2[3])
279
#define TSF_FourCCEquals(value1, value2) (value1[0] == value2[0] && value1[1] == value2[1] && value1[2] == value2[2] && value1[3] == value2[3])
280
280
281
struct tsf
281
struct tsf
282
{
282
{
283
        struct tsf_preset* presets;
283
        struct tsf_preset* presets;
284
        float* fontSamples;
284
        float* fontSamples;
285
        struct tsf_voice* voices;
285
        struct tsf_voice* voices;
286
        struct tsf_channels* channels;
286
        struct tsf_channels* channels;
287
        float* outputSamples;
287
        float* outputSamples;
288
288
289
        int presetNum;
289
        int presetNum;
290
        int voiceNum;
290
        int voiceNum;
291
        int outputSampleSize;
291
        int outputSampleSize;
292
        unsigned int voicePlayIndex;
292
        unsigned int voicePlayIndex;
293
293
294
        enum TSFOutputMode outputmode;
294
        enum TSFOutputMode outputmode;
295
        float outSampleRate;
295
        float outSampleRate;
296
        float globalGainDB;
296
        float globalGainDB;
297
};
297
};
298
298
299
#ifndef TSF_NO_STDIO
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); }
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); }
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)
302
TSFDEF tsf* tsf_load_filename(const char* filename)
303
{
303
{
304
        tsf* res;
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 };
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__
306
        #if __STDC_WANT_SECURE_LIB__
307
        FILE* f = TSF_NULL; fopen_s(&f, filename, "rb");
307
        FILE* f = TSF_NULL; fopen_s(&f, filename, "rb");
308
        #else
308
        #else
309
        FILE* f = fopen(filename, "rb");
309
        FILE* f = fopen(filename, "rb");
310
        #endif
310
        #endif
311
        if (!f)
311
        if (!f)
312
        {
312
        {
313
                //if (e) *e = TSF_FILENOTFOUND;
313
                //if (e) *e = TSF_FILENOTFOUND;
314
                return TSF_NULL;
314
                return TSF_NULL;
315
        }
315
        }
316
        stream.data = f;
316
        stream.data = f;
317
        res = tsf_load(&stream);
317
        res = tsf_load(&stream);
318
        fclose(f);
318
        fclose(f);
319
        return res;
319
        return res;
320
}
320
}
321
#endif
321
#endif
322
322
323
struct tsf_stream_memory { const char* buffer; unsigned int total, pos; };
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; }
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; }
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)
326
TSFDEF tsf* tsf_load_memory(const void* buffer, int size)
327
{
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 };
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 };
329
        struct tsf_stream_memory f = { 0, 0, 0 };
330
        f.buffer = (const char*)buffer;
330
        f.buffer = (const char*)buffer;
331
        f.total = size;
331
        f.total = size;
332
        stream.data = &f;
332
        stream.data = &f;
333
        return tsf_load(&stream);
333
        return tsf_load(&stream);
334
}
334
}
335
335
336
enum { TSF_LOOPMODE_NONE, TSF_LOOPMODE_CONTINUOUS, TSF_LOOPMODE_SUSTAIN };
336
enum { TSF_LOOPMODE_NONE, TSF_LOOPMODE_CONTINUOUS, TSF_LOOPMODE_SUSTAIN };
337
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 };
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
339
340
struct tsf_hydra
340
struct tsf_hydra
341
{
341
{
342
        struct tsf_hydra_phdr *phdrs; struct tsf_hydra_pbag *pbags; struct tsf_hydra_pmod *pmods;
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;
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;
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;
345
        int phdrNum, pbagNum, pmodNum, pgenNum, instNum, ibagNum, imodNum, igenNum, shdrNum;
346
};
346
};
347
347
348
union tsf_hydra_genamount { struct { tsf_u8 lo, hi; } range; tsf_s16 shortAmount; tsf_u16 wordAmount; };
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; };
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; };
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; };
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; };
352
struct tsf_hydra_pgen { tsf_u16 genOper; union tsf_hydra_genamount genAmount; };
353
struct tsf_hydra_inst { tsf_char20 instName; tsf_u16 instBagNdx; };
353
struct tsf_hydra_inst { tsf_char20 instName; tsf_u16 instBagNdx; };
354
struct tsf_hydra_ibag { tsf_u16 instGenNdx, instModNdx; };
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; };
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; };
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; };
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
358
359
#define TSFR(FIELD) stream->read(stream->data, &i->FIELD, sizeof(i->FIELD));
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) }
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) }
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) }
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) }
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) }
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) }
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) }
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) }
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) }
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
369
#undef TSFR
370
370
371
struct tsf_riffchunk { tsf_fourcc id; tsf_u32 size; };
371
struct tsf_riffchunk { tsf_fourcc id; tsf_u32 size; };
372
struct tsf_envelope { float delay, attack, hold, decay, sustain, release, keynumToHold, keynumToDecay; };
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; };
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; };
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; };
375
struct tsf_voice_lfo { int samplesUntil; float level, delta; };
376
376
377
struct tsf_region
377
struct tsf_region
378
{
378
{
379
        int loop_mode;
379
        int loop_mode;
380
        unsigned int sample_rate;
380
        unsigned int sample_rate;
381
        unsigned char lokey, hikey, lovel, hivel;
381
        unsigned char lokey, hikey, lovel, hivel;
382
        unsigned int group, offset, end, loop_start, loop_end;
382
        unsigned int group, offset, end, loop_start, loop_end;
383
        int transpose, tune, pitch_keycenter, pitch_keytrack;
383
        int transpose, tune, pitch_keycenter, pitch_keytrack;
384
        float attenuation, pan;
384
        float attenuation, pan;
385
        struct tsf_envelope ampenv, modenv;
385
        struct tsf_envelope ampenv, modenv;
386
        int initialFilterQ, initialFilterFc;
386
        int initialFilterQ, initialFilterFc;
387
        int modEnvToPitch, modEnvToFilterFc, modLfoToFilterFc, modLfoToVolume;
387
        int modEnvToPitch, modEnvToFilterFc, modLfoToFilterFc, modLfoToVolume;
388
        float delayModLFO;
388
        float delayModLFO;
389
        int freqModLFO, modLfoToPitch;
389
        int freqModLFO, modLfoToPitch;
390
        float delayVibLFO;
390
        float delayVibLFO;
391
        int freqVibLFO, vibLfoToPitch;
391
        int freqVibLFO, vibLfoToPitch;
392
};
392
};
393
393
394
struct tsf_preset
394
struct tsf_preset
395
{
395
{
396
        tsf_char20 presetName;
396
        tsf_char20 presetName;
397
        tsf_u16 preset, bank;
397
        tsf_u16 preset, bank;
398
        struct tsf_region* regions;
398
        struct tsf_region* regions;
399
        int regionNum;
399
        int regionNum;
400
};
400
};
401
401
402
struct tsf_voice
402
struct tsf_voice
403
{
403
{
404
        int playingPreset, playingKey, playingChannel;
404
        int playingPreset, playingKey, playingChannel;
405
        struct tsf_region* region;
405
        struct tsf_region* region;
406
        double pitchInputTimecents, pitchOutputFactor;
406
        double pitchInputTimecents, pitchOutputFactor;
407
        double sourceSamplePosition;
407
        double sourceSamplePosition;
408
        float  noteGainDB, panFactorLeft, panFactorRight;
408
        float  noteGainDB, panFactorLeft, panFactorRight;
409
        unsigned int playIndex, loopStart, loopEnd;
409
        unsigned int playIndex, loopStart, loopEnd;
410
        struct tsf_voice_envelope ampenv, modenv;
410
        struct tsf_voice_envelope ampenv, modenv;
411
        struct tsf_voice_lowpass lowpass;
411
        struct tsf_voice_lowpass lowpass;
412
        struct tsf_voice_lfo modlfo, viblfo;
412
        struct tsf_voice_lfo modlfo, viblfo;
413
};
413
};
414
414
415
struct tsf_channel
415
struct tsf_channel
416
{
416
{
417
        unsigned short presetIndex, bank, pitchWheel, midiPan, midiVolume, midiExpression, midiRPN, midiData;
417
        unsigned short presetIndex, bank, pitchWheel, midiPan, midiVolume, midiExpression, midiRPN, midiData;
418
        float panOffset, gainDB, pitchRange, tuning;
418
        float panOffset, gainDB, pitchRange, tuning;
419
};
419
};
420
420
421
struct tsf_channels
421
struct tsf_channels
422
{
422
{
423
        void (*setupVoice)(tsf* f, struct tsf_voice* voice);
423
        void (*setupVoice)(tsf* f, struct tsf_voice* voice);
424
        struct tsf_channel* channels;
424
        struct tsf_channel* channels;
425
        int channelNum, activeChannel;
425
        int channelNum, activeChannel;
426
};
426
};
427
427
428
static double tsf_timecents2Secsd(double timecents) { return TSF_POW(2.0, timecents / 1200.0); }
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); }
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); }
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); }
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))); }
432
static float tsf_gainToDecibels(float gain) { return (gain <= .00001f ? -100.f : (float)(20.0 * TSF_LOG10(gain))); }
433
433
434
static TSF_BOOL tsf_riffchunk_read(struct tsf_riffchunk* parent, struct tsf_riffchunk* chunk, struct tsf_stream* stream)
434
static TSF_BOOL tsf_riffchunk_read(struct tsf_riffchunk* parent, struct tsf_riffchunk* chunk, struct tsf_stream* stream)
435
{
435
{
436
        TSF_BOOL IsRiff, IsList;
436
        TSF_BOOL IsRiff, IsList;
437
        if (parent && sizeof(tsf_fourcc) + sizeof(tsf_u32) > parent->size) return TSF_FALSE;
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;
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;
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;
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;
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");
442
        IsRiff = TSF_FourCCEquals(chunk->id, "RIFF"), IsList = TSF_FourCCEquals(chunk->id, "LIST");
443
        if (IsRiff && parent) return TSF_FALSE; //not allowed
443
        if (IsRiff && parent) return TSF_FALSE; //not allowed
444
        if (!IsRiff && !IsList) return TSF_TRUE; //custom type without sub type
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;
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);
446
        chunk->size -= sizeof(tsf_fourcc);
447
        return TSF_TRUE;
447
        return TSF_TRUE;
448
}
448
}
449
449
450
static void tsf_region_clear(struct tsf_region* i, TSF_BOOL for_relative)
450
static void tsf_region_clear(struct tsf_region* i, TSF_BOOL for_relative)
451
{
451
{
452
        TSF_MEMSET(i, 0, sizeof(struct tsf_region));
452
        TSF_MEMSET(i, 0, sizeof(struct tsf_region));
453
        i->hikey = i->hivel = 127;
453
        i->hikey = i->hivel = 127;
454
        i->pitch_keycenter = 60; // C4
454
        i->pitch_keycenter = 60; // C4
455
        if (for_relative) return;
455
        if (for_relative) return;
456
456
457
        i->pitch_keytrack = 100;
457
        i->pitch_keytrack = 100;
458
458
459
        i->pitch_keycenter = -1;
459
        i->pitch_keycenter = -1;
460
460
461
        // SF2 defaults in timecents.
461
        // SF2 defaults in timecents.
462
        i->ampenv.delay = i->ampenv.attack = i->ampenv.hold = i->ampenv.decay = i->ampenv.release = -12000.0f;
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;
463
        i->modenv.delay = i->modenv.attack = i->modenv.hold = i->modenv.decay = i->modenv.release = -12000.0f;
464
464
465
        i->initialFilterFc = 13500;
465
        i->initialFilterFc = 13500;
466
466
467
        i->delayModLFO = -12000.0f;
467
        i->delayModLFO = -12000.0f;
468
        i->delayVibLFO = -12000.0f;
468
        i->delayVibLFO = -12000.0f;
469
}
469
}
470
470
471
static void tsf_region_operator(struct tsf_region* region, tsf_u16 genOper, union tsf_hydra_genamount* amount)
471
static void tsf_region_operator(struct tsf_region* region, tsf_u16 genOper, union tsf_hydra_genamount* amount)
472
{
472
{
473
        enum
473
        enum
474
        {
474
        {
475
                StartAddrsOffset, EndAddrsOffset, StartloopAddrsOffset, EndloopAddrsOffset, StartAddrsCoarseOffset, ModLfoToPitch, VibLfoToPitch, ModEnvToPitch,
475
                StartAddrsOffset, EndAddrsOffset, StartloopAddrsOffset, EndloopAddrsOffset, StartAddrsCoarseOffset, ModLfoToPitch, VibLfoToPitch, ModEnvToPitch,
476
                InitialFilterFc, InitialFilterQ, ModLfoToFilterFc, ModEnvToFilterFc, EndAddrsCoarseOffset, ModLfoToVolume, Unused1, ChorusEffectsSend,
476
                InitialFilterFc, InitialFilterQ, ModLfoToFilterFc, ModEnvToFilterFc, EndAddrsCoarseOffset, ModLfoToVolume, Unused1, ChorusEffectsSend,
477
                ReverbEffectsSend, Pan, Unused2, Unused3, Unused4, DelayModLFO, FreqModLFO, DelayVibLFO, FreqVibLFO, DelayModEnv, AttackModEnv, HoldModEnv,
477
                ReverbEffectsSend, Pan, Unused2, Unused3, Unused4, DelayModLFO, FreqModLFO, DelayVibLFO, FreqVibLFO, DelayModEnv, AttackModEnv, HoldModEnv,
478
                DecayModEnv, SustainModEnv, ReleaseModEnv, KeynumToModEnvHold, KeynumToModEnvDecay, DelayVolEnv, AttackVolEnv, HoldVolEnv, DecayVolEnv,
478
                DecayModEnv, SustainModEnv, ReleaseModEnv, KeynumToModEnvHold, KeynumToModEnvDecay, DelayVolEnv, AttackVolEnv, HoldVolEnv, DecayVolEnv,
479
                SustainVolEnv, ReleaseVolEnv, KeynumToVolEnvHold, KeynumToVolEnvDecay, Instrument, Reserved1, KeyRange, VelRange, StartloopAddrsCoarseOffset,
479
                SustainVolEnv, ReleaseVolEnv, KeynumToVolEnvHold, KeynumToVolEnvDecay, Instrument, Reserved1, KeyRange, VelRange, StartloopAddrsCoarseOffset,
480
                Keynum, Velocity, InitialAttenuation, Reserved2, EndloopAddrsCoarseOffset, CoarseTune, FineTune, SampleID, SampleModes, Reserved3, ScaleTuning,
480
                Keynum, Velocity, InitialAttenuation, Reserved2, EndloopAddrsCoarseOffset, CoarseTune, FineTune, SampleID, SampleModes, Reserved3, ScaleTuning,
481
                ExclusiveClass, OverridingRootKey, Unused5, EndOper
481
                ExclusiveClass, OverridingRootKey, Unused5, EndOper
482
        };
482
        };
483
        switch (genOper)
483
        switch (genOper)
484
        {
484
        {
485
                case StartAddrsOffset:           region->offset += amount->shortAmount; break;
485
                case StartAddrsOffset:           region->offset += amount->shortAmount; break;
486
                case EndAddrsOffset:             region->end += amount->shortAmount; break;
486
                case EndAddrsOffset:             region->end += amount->shortAmount; break;
487
                case StartloopAddrsOffset:       region->loop_start += amount->shortAmount; break;
487
                case StartloopAddrsOffset:       region->loop_start += amount->shortAmount; break;
488
                case EndloopAddrsOffset:         region->loop_end += amount->shortAmount; break;
488
                case EndloopAddrsOffset:         region->loop_end += amount->shortAmount; break;
489
                case StartAddrsCoarseOffset:     region->offset += amount->shortAmount * 32768; break;
489
                case StartAddrsCoarseOffset:     region->offset += amount->shortAmount * 32768; break;
490
                case ModLfoToPitch:              region->modLfoToPitch = amount->shortAmount; break;
490
                case ModLfoToPitch:              region->modLfoToPitch = amount->shortAmount; break;
491
                case VibLfoToPitch:              region->vibLfoToPitch = amount->shortAmount; break;
491
                case VibLfoToPitch:              region->vibLfoToPitch = amount->shortAmount; break;
492
                case ModEnvToPitch:              region->modEnvToPitch = amount->shortAmount; break;
492
                case ModEnvToPitch:              region->modEnvToPitch = amount->shortAmount; break;
493
                case InitialFilterFc:            region->initialFilterFc = amount->shortAmount; break;
493
                case InitialFilterFc:            region->initialFilterFc = amount->shortAmount; break;
494
                case InitialFilterQ:             region->initialFilterQ = amount->shortAmount; break;
494
                case InitialFilterQ:             region->initialFilterQ = amount->shortAmount; break;
495
                case ModLfoToFilterFc:           region->modLfoToFilterFc = amount->shortAmount; break;
495
                case ModLfoToFilterFc:           region->modLfoToFilterFc = amount->shortAmount; break;
496
                case ModEnvToFilterFc:           region->modEnvToFilterFc = amount->shortAmount; break;
496
                case ModEnvToFilterFc:           region->modEnvToFilterFc = amount->shortAmount; break;
497
                case EndAddrsCoarseOffset:       region->end += amount->shortAmount * 32768; break;
497
                case EndAddrsCoarseOffset:       region->end += amount->shortAmount * 32768; break;
498
                case ModLfoToVolume:             region->modLfoToVolume = amount->shortAmount; break;
498
                case ModLfoToVolume:             region->modLfoToVolume = amount->shortAmount; break;
499
                case Pan:                        region->pan = amount->shortAmount / 1000.0f; break;
499
                case Pan:                        region->pan = amount->shortAmount / 1000.0f; break;
500
                case DelayModLFO:                region->delayModLFO = amount->shortAmount; break;
500
                case DelayModLFO:                region->delayModLFO = amount->shortAmount; break;
501
                case FreqModLFO:                 region->freqModLFO = amount->shortAmount; break;
501
                case FreqModLFO:                 region->freqModLFO = amount->shortAmount; break;
502
                case DelayVibLFO:                region->delayVibLFO = amount->shortAmount; break;
502
                case DelayVibLFO:                region->delayVibLFO = amount->shortAmount; break;
503
                case FreqVibLFO:                 region->freqVibLFO = amount->shortAmount; break;
503
                case FreqVibLFO:                 region->freqVibLFO = amount->shortAmount; break;
504
                case DelayModEnv:                region->modenv.delay = amount->shortAmount; break;
504
                case DelayModEnv:                region->modenv.delay = amount->shortAmount; break;
505
                case AttackModEnv:               region->modenv.attack = amount->shortAmount; break;
505
                case AttackModEnv:               region->modenv.attack = amount->shortAmount; break;
506
                case HoldModEnv:                 region->modenv.hold = amount->shortAmount; break;
506
                case HoldModEnv:                 region->modenv.hold = amount->shortAmount; break;
507
                case DecayModEnv:                region->modenv.decay = amount->shortAmount; break;
507
                case DecayModEnv:                region->modenv.decay = amount->shortAmount; break;
508
                case SustainModEnv:              region->modenv.sustain = amount->shortAmount; break;
508
                case SustainModEnv:              region->modenv.sustain = amount->shortAmount; break;
509
                case ReleaseModEnv:              region->modenv.release = amount->shortAmount; break;
509
                case ReleaseModEnv:              region->modenv.release = amount->shortAmount; break;
510
                case KeynumToModEnvHold:         region->modenv.keynumToHold = amount->shortAmount; break;
510
                case KeynumToModEnvHold:         region->modenv.keynumToHold = amount->shortAmount; break;
511
                case KeynumToModEnvDecay:        region->modenv.keynumToDecay = amount->shortAmount; break;
511
                case KeynumToModEnvDecay:        region->modenv.keynumToDecay = amount->shortAmount; break;
512
                case DelayVolEnv:                region->ampenv.delay = amount->shortAmount; break;
512
                case DelayVolEnv:                region->ampenv.delay = amount->shortAmount; break;
513
                case AttackVolEnv:               region->ampenv.attack = amount->shortAmount; break;
513
                case AttackVolEnv:               region->ampenv.attack = amount->shortAmount; break;
514
                case HoldVolEnv:                 region->ampenv.hold = amount->shortAmount; break;
514
                case HoldVolEnv:                 region->ampenv.hold = amount->shortAmount; break;
515
                case DecayVolEnv:                region->ampenv.decay = amount->shortAmount; break;
515
                case DecayVolEnv:                region->ampenv.decay = amount->shortAmount; break;
516
                case SustainVolEnv:              region->ampenv.sustain = amount->shortAmount; break;
516
                case SustainVolEnv:              region->ampenv.sustain = amount->shortAmount; break;
517
                case ReleaseVolEnv:              region->ampenv.release = amount->shortAmount; break;
517
                case ReleaseVolEnv:              region->ampenv.release = amount->shortAmount; break;
518
                case KeynumToVolEnvHold:         region->ampenv.keynumToHold = amount->shortAmount; break;
518
                case KeynumToVolEnvHold:         region->ampenv.keynumToHold = amount->shortAmount; break;
519
                case KeynumToVolEnvDecay:        region->ampenv.keynumToDecay = amount->shortAmount; break;
519
                case KeynumToVolEnvDecay:        region->ampenv.keynumToDecay = amount->shortAmount; break;
520
                case KeyRange:                   region->lokey = amount->range.lo; region->hikey = amount->range.hi; break;
520
                case KeyRange:                   region->lokey = amount->range.lo; region->hikey = amount->range.hi; break;
521
                case VelRange:                   region->lovel = amount->range.lo; region->hivel = amount->range.hi; break;
521
                case VelRange:                   region->lovel = amount->range.lo; region->hivel = amount->range.hi; break;
522
                case StartloopAddrsCoarseOffset: region->loop_start += amount->shortAmount * 32768; break;
522
                case StartloopAddrsCoarseOffset: region->loop_start += amount->shortAmount * 32768; break;
523
                case InitialAttenuation:         region->attenuation += amount->shortAmount * 0.1f; break;
523
                case InitialAttenuation:         region->attenuation += amount->shortAmount * 0.1f; break;
524
                case EndloopAddrsCoarseOffset:   region->loop_end += amount->shortAmount * 32768; break;
524
                case EndloopAddrsCoarseOffset:   region->loop_end += amount->shortAmount * 32768; break;
525
                case CoarseTune:                 region->transpose += amount->shortAmount; break;
525
                case CoarseTune:                 region->transpose += amount->shortAmount; break;
526
                case FineTune:                   region->tune += amount->shortAmount; break;
526
                case FineTune:                   region->tune += amount->shortAmount; break;
527
                case SampleModes:                region->loop_mode = ((amount->wordAmount&3) == 3 ? TSF_LOOPMODE_SUSTAIN : ((amount->wordAmount&3) == 1 ? TSF_LOOPMODE_CONTINUOUS : TSF_LOOPMODE_NONE)); break;
527
                case SampleModes:                region->loop_mode = ((amount->wordAmount&3) == 3 ? TSF_LOOPMODE_SUSTAIN : ((amount->wordAmount&3) == 1 ? TSF_LOOPMODE_CONTINUOUS : TSF_LOOPMODE_NONE)); break;
528
                case ScaleTuning:                region->pitch_keytrack = amount->shortAmount; break;
528
                case ScaleTuning:                region->pitch_keytrack = amount->shortAmount; break;
529
                case ExclusiveClass:             region->group = amount->wordAmount; break;
529
                case ExclusiveClass:             region->group = amount->wordAmount; break;
530
                case OverridingRootKey:          region->pitch_keycenter = amount->shortAmount; break;
530
                case OverridingRootKey:          region->pitch_keycenter = amount->shortAmount; break;
531
                //case gen_endOper: break; // Ignore.
531
                //case gen_endOper: break; // Ignore.
532
                //default: addUnsupportedOpcode(generator_name);
532
                //default: addUnsupportedOpcode(generator_name);
533
        }
533
        }
534
}
534
}
535
535
536
static void tsf_region_envtosecs(struct tsf_envelope* p, TSF_BOOL sustainIsGain)
536
static void tsf_region_envtosecs(struct tsf_envelope* p, TSF_BOOL sustainIsGain)
537
{
537
{
538
        // EG times need to be converted from timecents to seconds.
538
        // EG times need to be converted from timecents to seconds.
539
        // Pin very short EG segments.  Timecents don't get to zero, and our EG is
539
        // Pin very short EG segments.  Timecents don't get to zero, and our EG is
540
        // happier with zero values.
540
        // happier with zero values.
541
        p->delay   = (p->delay   < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->delay));
541
        p->delay   = (p->delay   < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->delay));
542
        p->attack  = (p->attack  < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->attack));
542
        p->attack  = (p->attack  < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->attack));
543
        p->release = (p->release < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->release));
543
        p->release = (p->release < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->release));
544
544
545
        // If we have dynamic hold or decay times depending on key number we need
545
        // If we have dynamic hold or decay times depending on key number we need
546
        // to keep the values in timecents so we can calculate it during startNote
546
        // to keep the values in timecents so we can calculate it during startNote
547
        if (!p->keynumToHold)  p->hold  = (p->hold  < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->hold));
547
        if (!p->keynumToHold)  p->hold  = (p->hold  < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->hold));
548
        if (!p->keynumToDecay) p->decay = (p->decay < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->decay));
548
        if (!p->keynumToDecay) p->decay = (p->decay < -11950.0f ? 0.0f : tsf_timecents2Secsf(p->decay));
549
       
549
       
550
        if (p->sustain < 0.0f) p->sustain = 0.0f;
550
        if (p->sustain < 0.0f) p->sustain = 0.0f;
551
        else if (sustainIsGain) p->sustain = tsf_decibelsToGain(-p->sustain / 10.0f);
551
        else if (sustainIsGain) p->sustain = tsf_decibelsToGain(-p->sustain / 10.0f);
552
        else p->sustain = 1.0f - (p->sustain / 1000.0f);
552
        else p->sustain = 1.0f - (p->sustain / 1000.0f);
553
553
554
        p->sustain = clamp(p->sustain, 0, 1.f);
554
        p->sustain = clamp(p->sustain, 0, 1.f);
555
}
555
}
556
556
557
static void tsf_load_presets(tsf* res, struct tsf_hydra *hydra, unsigned int fontSampleCount)
557
static void tsf_load_presets(tsf* res, struct tsf_hydra *hydra, unsigned int fontSampleCount)
558
{
558
{
559
        enum { GenInstrument = 41, GenKeyRange = 43, GenVelRange = 44, GenSampleID = 53 };
559
        enum { GenInstrument = 41, GenKeyRange = 43, GenVelRange = 44, GenSampleID = 53 };
560
        // Read each preset.
560
        // Read each preset.
561
        struct tsf_hydra_phdr *pphdr, *pphdrMax;
561
        struct tsf_hydra_phdr *pphdr, *pphdrMax;
562
        for (pphdr = hydra->phdrs, pphdrMax = pphdr + hydra->phdrNum - 1; pphdr != pphdrMax; pphdr++)
562
        for (pphdr = hydra->phdrs, pphdrMax = pphdr + hydra->phdrNum - 1; pphdr != pphdrMax; pphdr++)
563
        {
563
        {
564
                int sortedIndex = 0, region_index = 0;
564
                int sortedIndex = 0, region_index = 0;
565
                struct tsf_hydra_phdr *otherphdr;
565
                struct tsf_hydra_phdr *otherphdr;
566
                struct tsf_preset* preset;
566
                struct tsf_preset* preset;
567
                struct tsf_hydra_pbag *ppbag, *ppbagEnd;
567
                struct tsf_hydra_pbag *ppbag, *ppbagEnd;
568
                struct tsf_region globalRegion;
568
                struct tsf_region globalRegion;
569
                for (otherphdr = hydra->phdrs; otherphdr != pphdrMax; otherphdr++)
569
                for (otherphdr = hydra->phdrs; otherphdr != pphdrMax; otherphdr++)
570
                {
570
                {
571
                        if (otherphdr == pphdr || otherphdr->bank > pphdr->bank) continue;
571
                        if (otherphdr == pphdr || otherphdr->bank > pphdr->bank) continue;
572
                        else if (otherphdr->bank < pphdr->bank) sortedIndex++;
572
                        else if (otherphdr->bank < pphdr->bank) sortedIndex++;
573
                        else if (otherphdr->preset > pphdr->preset) continue;
573
                        else if (otherphdr->preset > pphdr->preset) continue;
574
                        else if (otherphdr->preset < pphdr->preset) sortedIndex++;
574
                        else if (otherphdr->preset < pphdr->preset) sortedIndex++;
575
                        else if (otherphdr < pphdr) sortedIndex++;
575
                        else if (otherphdr < pphdr) sortedIndex++;
576
                }
576
                }
577
577
578
                preset = &res->presets[sortedIndex];
578
                preset = &res->presets[sortedIndex];
579
                TSF_MEMCPY(preset->presetName, pphdr->presetName, sizeof(preset->presetName));
579
                TSF_MEMCPY(preset->presetName, pphdr->presetName, sizeof(preset->presetName));
580
                preset->presetName[sizeof(preset->presetName)-1] = '\0'; //should be zero terminated in source file but make sure
580
                preset->presetName[sizeof(preset->presetName)-1] = '\0'; //should be zero terminated in source file but make sure
581
                preset->bank = pphdr->bank;
581
                preset->bank = pphdr->bank;
582
                preset->preset = pphdr->preset;
582
                preset->preset = pphdr->preset;
583
                preset->regionNum = 0;
583
                preset->regionNum = 0;
584
584
585
                //count regions covered by this preset
585
                //count regions covered by this preset
586
                for (ppbag = hydra->pbags + pphdr->presetBagNdx, ppbagEnd = hydra->pbags + pphdr[1].presetBagNdx; ppbag != ppbagEnd; ppbag++)
586
                for (ppbag = hydra->pbags + pphdr->presetBagNdx, ppbagEnd = hydra->pbags + pphdr[1].presetBagNdx; ppbag != ppbagEnd; ppbag++)
587
                {
587
                {
588
                        unsigned char plokey = 0, phikey = 127, plovel = 0, phivel = 127;
588
                        unsigned char plokey = 0, phikey = 127, plovel = 0, phivel = 127;
589
                        struct tsf_hydra_pgen *ppgen, *ppgenEnd; struct tsf_hydra_inst *pinst; struct tsf_hydra_ibag *pibag, *pibagEnd; struct tsf_hydra_igen *pigen, *pigenEnd;
589
                        struct tsf_hydra_pgen *ppgen, *ppgenEnd; struct tsf_hydra_inst *pinst; struct tsf_hydra_ibag *pibag, *pibagEnd; struct tsf_hydra_igen *pigen, *pigenEnd;
590
                        for (ppgen = hydra->pgens + ppbag->genNdx, ppgenEnd = hydra->pgens + ppbag[1].genNdx; ppgen != ppgenEnd; ppgen++)
590
                        for (ppgen = hydra->pgens + ppbag->genNdx, ppgenEnd = hydra->pgens + ppbag[1].genNdx; ppgen != ppgenEnd; ppgen++)
591
                        {
591
                        {
592
                                if (ppgen->genOper == GenKeyRange) { plokey = ppgen->genAmount.range.lo; phikey = ppgen->genAmount.range.hi; continue; }
592
                                if (ppgen->genOper == GenKeyRange) { plokey = ppgen->genAmount.range.lo; phikey = ppgen->genAmount.range.hi; continue; }
593
                                if (ppgen->genOper == GenVelRange) { plovel = ppgen->genAmount.range.lo; phivel = ppgen->genAmount.range.hi; continue; }
593
                                if (ppgen->genOper == GenVelRange) { plovel = ppgen->genAmount.range.lo; phivel = ppgen->genAmount.range.hi; continue; }
594
                                if (ppgen->genOper != GenInstrument) continue;
594
                                if (ppgen->genOper != GenInstrument) continue;
595
                                if (ppgen->genAmount.wordAmount >= hydra->instNum) continue;
595
                                if (ppgen->genAmount.wordAmount >= hydra->instNum) continue;
596
                                pinst = hydra->insts + ppgen->genAmount.wordAmount;
596
                                pinst = hydra->insts + ppgen->genAmount.wordAmount;
597
                                for (pibag = hydra->ibags + pinst->instBagNdx, pibagEnd = hydra->ibags + pinst[1].instBagNdx; pibag != pibagEnd; pibag++)
597
                                for (pibag = hydra->ibags + pinst->instBagNdx, pibagEnd = hydra->ibags + pinst[1].instBagNdx; pibag != pibagEnd; pibag++)
598
                                {
598
                                {
599
                                        unsigned char ilokey = 0, ihikey = 127, ilovel = 0, ihivel = 127;
599
                                        unsigned char ilokey = 0, ihikey = 127, ilovel = 0, ihivel = 127;
600
                                        for (pigen = hydra->igens + pibag->instGenNdx, pigenEnd = hydra->igens + pibag[1].instGenNdx; pigen != pigenEnd; pigen++)
600
                                        for (pigen = hydra->igens + pibag->instGenNdx, pigenEnd = hydra->igens + pibag[1].instGenNdx; pigen != pigenEnd; pigen++)
601
                                        {
601
                                        {
602
                                                if (pigen->genOper == GenKeyRange) { ilokey = pigen->genAmount.range.lo; ihikey = pigen->genAmount.range.hi; continue; }
602
                                                if (pigen->genOper == GenKeyRange) { ilokey = pigen->genAmount.range.lo; ihikey = pigen->genAmount.range.hi; continue; }
603
                                                if (pigen->genOper == GenVelRange) { ilovel = pigen->genAmount.range.lo; ihivel = pigen->genAmount.range.hi; continue; }
603
                                                if (pigen->genOper == GenVelRange) { ilovel = pigen->genAmount.range.lo; ihivel = pigen->genAmount.range.hi; continue; }
604
                                                if (pigen->genOper == GenSampleID && ihikey >= plokey && ilokey <= phikey && ihivel >= plovel && ilovel <= phivel) preset->regionNum++;
604
                                                if (pigen->genOper == GenSampleID && ihikey >= plokey && ilokey <= phikey && ihivel >= plovel && ilovel <= phivel) preset->regionNum++;
605
                                        }
605
                                        }
606
                                }
606
                                }
607
                        }
607
                        }
608
                }
608
                }
609
609
610
                preset->regions = (struct tsf_region*)TSF_MALLOC(preset->regionNum * sizeof(struct tsf_region));
610
                preset->regions = (struct tsf_region*)TSF_MALLOC(preset->regionNum * sizeof(struct tsf_region));
611
                tsf_region_clear(&globalRegion, TSF_TRUE);
611
                tsf_region_clear(&globalRegion, TSF_TRUE);
612
612
613
                // Zones.
613
                // Zones.
614
                for (ppbag = hydra->pbags + pphdr->presetBagNdx, ppbagEnd = hydra->pbags + pphdr[1].presetBagNdx; ppbag != ppbagEnd; ppbag++)
614
                for (ppbag = hydra->pbags + pphdr->presetBagNdx, ppbagEnd = hydra->pbags + pphdr[1].presetBagNdx; ppbag != ppbagEnd; ppbag++)
615
                {
615
                {
616
                        struct tsf_hydra_pgen *ppgen, *ppgenEnd; struct tsf_hydra_inst *pinst; struct tsf_hydra_ibag *pibag, *pibagEnd; struct tsf_hydra_igen *pigen, *pigenEnd;
616
                        struct tsf_hydra_pgen *ppgen, *ppgenEnd; struct tsf_hydra_inst *pinst; struct tsf_hydra_ibag *pibag, *pibagEnd; struct tsf_hydra_igen *pigen, *pigenEnd;
617
                        struct tsf_region presetRegion = globalRegion;
617
                        struct tsf_region presetRegion = globalRegion;
618
                        int hadGenInstrument = 0;
618
                        int hadGenInstrument = 0;
619
619
620
                        // Generators.
620
                        // Generators.
621
                        for (ppgen = hydra->pgens + ppbag->genNdx, ppgenEnd = hydra->pgens + ppbag[1].genNdx; ppgen != ppgenEnd; ppgen++)
621
                        for (ppgen = hydra->pgens + ppbag->genNdx, ppgenEnd = hydra->pgens + ppbag[1].genNdx; ppgen != ppgenEnd; ppgen++)
622
                        {
622
                        {
623
                                // Instrument.
623
                                // Instrument.
624
                                if (ppgen->genOper == GenInstrument)
624
                                if (ppgen->genOper == GenInstrument)
625
                                {
625
                                {
626
                                        struct tsf_region instRegion;
626
                                        struct tsf_region instRegion;
627
                                        tsf_u16 whichInst = ppgen->genAmount.wordAmount;
627
                                        tsf_u16 whichInst = ppgen->genAmount.wordAmount;
628
                                        if (whichInst >= hydra->instNum) continue;
628
                                        if (whichInst >= hydra->instNum) continue;
629
629
630
                                        tsf_region_clear(&instRegion, TSF_FALSE);
630
                                        tsf_region_clear(&instRegion, TSF_FALSE);
631
                                        pinst = &hydra->insts[whichInst];
631
                                        pinst = &hydra->insts[whichInst];
632
                                        for (pibag = hydra->ibags + pinst->instBagNdx, pibagEnd = hydra->ibags + pinst[1].instBagNdx; pibag != pibagEnd; pibag++)
632
                                        for (pibag = hydra->ibags + pinst->instBagNdx, pibagEnd = hydra->ibags + pinst[1].instBagNdx; pibag != pibagEnd; pibag++)
633
                                        {
633
                                        {
634
                                                // Generators.
634
                                                // Generators.
635
                                                struct tsf_region zoneRegion = instRegion;
635
                                                struct tsf_region zoneRegion = instRegion;
636
                                                int hadSampleID = 0;
636
                                                int hadSampleID = 0;
637
                                                for (pigen = hydra->igens + pibag->instGenNdx, pigenEnd = hydra->igens + pibag[1].instGenNdx; pigen != pigenEnd; pigen++)
637
                                                for (pigen = hydra->igens + pibag->instGenNdx, pigenEnd = hydra->igens + pibag[1].instGenNdx; pigen != pigenEnd; pigen++)
638
                                                {
638
                                                {
639
                                                        if (pigen->genOper == GenSampleID)
639
                                                        if (pigen->genOper == GenSampleID)
640
                                                        {
640
                                                        {
641
                                                                struct tsf_hydra_shdr* pshdr;
641
                                                                struct tsf_hydra_shdr* pshdr;
642
642
643
                                                                //preset region key and vel ranges are a filter for the zone regions
643
                                                                //preset region key and vel ranges are a filter for the zone regions
644
                                                                if (zoneRegion.hikey < presetRegion.lokey || zoneRegion.lokey > presetRegion.hikey) continue;
644
                                                                if (zoneRegion.hikey < presetRegion.lokey || zoneRegion.lokey > presetRegion.hikey) continue;
645
                                                                if (zoneRegion.hivel < presetRegion.lovel || zoneRegion.lovel > presetRegion.hivel) continue;
645
                                                                if (zoneRegion.hivel < presetRegion.lovel || zoneRegion.lovel > presetRegion.hivel) continue;
646
                                                                if (presetRegion.lokey > zoneRegion.lokey) zoneRegion.lokey = presetRegion.lokey;
646
                                                                if (presetRegion.lokey > zoneRegion.lokey) zoneRegion.lokey = presetRegion.lokey;
647
                                                                if (presetRegion.hikey < zoneRegion.hikey) zoneRegion.hikey = presetRegion.hikey;
647
                                                                if (presetRegion.hikey < zoneRegion.hikey) zoneRegion.hikey = presetRegion.hikey;
648
                                                                if (presetRegion.lovel > zoneRegion.lovel) zoneRegion.lovel = presetRegion.lovel;
648
                                                                if (presetRegion.lovel > zoneRegion.lovel) zoneRegion.lovel = presetRegion.lovel;
649
                                                                if (presetRegion.hivel < zoneRegion.hivel) zoneRegion.hivel = presetRegion.hivel;
649
                                                                if (presetRegion.hivel < zoneRegion.hivel) zoneRegion.hivel = presetRegion.hivel;
650
650
651
                                                                //sum regions
651
                                                                //sum regions
652
                                                                zoneRegion.offset += presetRegion.offset;
652
                                                                zoneRegion.offset += presetRegion.offset;
653
                                                                zoneRegion.end += presetRegion.end;
653
                                                                zoneRegion.end += presetRegion.end;
654
                                                                zoneRegion.loop_start += presetRegion.loop_start;
654
                                                                zoneRegion.loop_start += presetRegion.loop_start;
655
                                                                zoneRegion.loop_end += presetRegion.loop_end;
655
                                                                zoneRegion.loop_end += presetRegion.loop_end;
656
                                                                zoneRegion.transpose += presetRegion.transpose;
656
                                                                zoneRegion.transpose += presetRegion.transpose;
657
                                                                zoneRegion.tune += presetRegion.tune;
657
                                                                zoneRegion.tune += presetRegion.tune;
658
                                                                zoneRegion.pitch_keytrack += presetRegion.pitch_keytrack;
658
                                                                zoneRegion.pitch_keytrack += presetRegion.pitch_keytrack;
659
                                                                zoneRegion.attenuation += presetRegion.attenuation;
659
                                                                zoneRegion.attenuation += presetRegion.attenuation;
660
                                                                zoneRegion.pan += presetRegion.pan;
660
                                                                zoneRegion.pan += presetRegion.pan;
661
                                                                zoneRegion.ampenv.delay += presetRegion.ampenv.delay;
661
                                                                zoneRegion.ampenv.delay += presetRegion.ampenv.delay;
662
                                                                zoneRegion.ampenv.attack += presetRegion.ampenv.attack;
662
                                                                zoneRegion.ampenv.attack += presetRegion.ampenv.attack;
663
                                                                zoneRegion.ampenv.hold += presetRegion.ampenv.hold;
663
                                                                zoneRegion.ampenv.hold += presetRegion.ampenv.hold;
664
                                                                zoneRegion.ampenv.decay += presetRegion.ampenv.decay;
664
                                                                zoneRegion.ampenv.decay += presetRegion.ampenv.decay;
665
                                                                zoneRegion.ampenv.sustain += presetRegion.ampenv.sustain;
665
                                                                zoneRegion.ampenv.sustain += presetRegion.ampenv.sustain;
666
                                                                zoneRegion.ampenv.release += presetRegion.ampenv.release;
666
                                                                zoneRegion.ampenv.release += presetRegion.ampenv.release;
667
                                                                zoneRegion.modenv.delay += presetRegion.modenv.delay;
667
                                                                zoneRegion.modenv.delay += presetRegion.modenv.delay;
668
                                                                zoneRegion.modenv.attack += presetRegion.modenv.attack;
668
                                                                zoneRegion.modenv.attack += presetRegion.modenv.attack;
669
                                                                zoneRegion.modenv.hold += presetRegion.modenv.hold;
669
                                                                zoneRegion.modenv.hold += presetRegion.modenv.hold;
670
                                                                zoneRegion.modenv.decay += presetRegion.modenv.decay;
670
                                                                zoneRegion.modenv.decay += presetRegion.modenv.decay;
671
                                                                zoneRegion.modenv.sustain += presetRegion.modenv.sustain;
671
                                                                zoneRegion.modenv.sustain += presetRegion.modenv.sustain;
672
                                                                zoneRegion.modenv.release += presetRegion.modenv.release;
672
                                                                zoneRegion.modenv.release += presetRegion.modenv.release;
673
                                                                zoneRegion.initialFilterQ += presetRegion.initialFilterQ;
673
                                                                zoneRegion.initialFilterQ += presetRegion.initialFilterQ;
674
                                                                zoneRegion.initialFilterFc += presetRegion.initialFilterFc;
674
                                                                zoneRegion.initialFilterFc += presetRegion.initialFilterFc;
675
                                                                zoneRegion.modEnvToPitch += presetRegion.modEnvToPitch;
675
                                                                zoneRegion.modEnvToPitch += presetRegion.modEnvToPitch;
676
                                                                zoneRegion.modEnvToFilterFc += presetRegion.modEnvToFilterFc;
676
                                                                zoneRegion.modEnvToFilterFc += presetRegion.modEnvToFilterFc;
677
                                                                zoneRegion.delayModLFO += presetRegion.delayModLFO;
677
                                                                zoneRegion.delayModLFO += presetRegion.delayModLFO;
678
                                                                zoneRegion.freqModLFO += presetRegion.freqModLFO;
678
                                                                zoneRegion.freqModLFO += presetRegion.freqModLFO;
679
                                                                zoneRegion.modLfoToPitch += presetRegion.modLfoToPitch;
679
                                                                zoneRegion.modLfoToPitch += presetRegion.modLfoToPitch;
680
                                                                zoneRegion.modLfoToFilterFc += presetRegion.modLfoToFilterFc;
680
                                                                zoneRegion.modLfoToFilterFc += presetRegion.modLfoToFilterFc;
681
                                                                zoneRegion.modLfoToVolume += presetRegion.modLfoToVolume;
681
                                                                zoneRegion.modLfoToVolume += presetRegion.modLfoToVolume;
682
                                                                zoneRegion.delayVibLFO += presetRegion.delayVibLFO;
682
                                                                zoneRegion.delayVibLFO += presetRegion.delayVibLFO;
683
                                                                zoneRegion.freqVibLFO += presetRegion.freqVibLFO;
683
                                                                zoneRegion.freqVibLFO += presetRegion.freqVibLFO;
684
                                                                zoneRegion.vibLfoToPitch += presetRegion.vibLfoToPitch;
684
                                                                zoneRegion.vibLfoToPitch += presetRegion.vibLfoToPitch;
685
685
686
                                                                // EG times need to be converted from timecents to seconds.
686
                                                                // EG times need to be converted from timecents to seconds.
687
                                                                tsf_region_envtosecs(&zoneRegion.ampenv, TSF_TRUE);
687
                                                                tsf_region_envtosecs(&zoneRegion.ampenv, TSF_TRUE);
688
                                                                tsf_region_envtosecs(&zoneRegion.modenv, TSF_FALSE);
688
                                                                tsf_region_envtosecs(&zoneRegion.modenv, TSF_FALSE);
689
689
690
                                                                // LFO times need to be converted from timecents to seconds.
690
                                                                // LFO times need to be converted from timecents to seconds.
691
                                                                zoneRegion.delayModLFO = (zoneRegion.delayModLFO < -11950.0f ? 0.0f : tsf_timecents2Secsf(zoneRegion.delayModLFO));
691
                                                                zoneRegion.delayModLFO = (zoneRegion.delayModLFO < -11950.0f ? 0.0f : tsf_timecents2Secsf(zoneRegion.delayModLFO));
692
                                                                zoneRegion.delayVibLFO = (zoneRegion.delayVibLFO < -11950.0f ? 0.0f : tsf_timecents2Secsf(zoneRegion.delayVibLFO));
692
                                                                zoneRegion.delayVibLFO = (zoneRegion.delayVibLFO < -11950.0f ? 0.0f : tsf_timecents2Secsf(zoneRegion.delayVibLFO));
693
693
694
                                                                // Pin values to their ranges.
694
                                                                // Pin values to their ranges.
695
                                                                if (zoneRegion.pan < -0.5f) zoneRegion.pan = -0.5f;
695
                                                                if (zoneRegion.pan < -0.5f) zoneRegion.pan = -0.5f;
696
                                                                else if (zoneRegion.pan > 0.5f) zoneRegion.pan = 0.5f;
696
                                                                else if (zoneRegion.pan > 0.5f) zoneRegion.pan = 0.5f;
697
                                                                if (zoneRegion.initialFilterQ < 1500 || zoneRegion.initialFilterQ > 13500) zoneRegion.initialFilterQ = 0;
697
                                                                if (zoneRegion.initialFilterQ < 1500 || zoneRegion.initialFilterQ > 13500) zoneRegion.initialFilterQ = 0;
698
698
699
                                                                pshdr = &hydra->shdrs[pigen->genAmount.wordAmount];
699
                                                                pshdr = &hydra->shdrs[pigen->genAmount.wordAmount];
700
                                                                zoneRegion.offset += pshdr->start;
700
                                                                zoneRegion.offset += pshdr->start;
701
                                                                zoneRegion.end += pshdr->end;
701
                                                                zoneRegion.end += pshdr->end;
702
                                                                zoneRegion.loop_start += pshdr->startLoop;
702
                                                                zoneRegion.loop_start += pshdr->startLoop;
703
                                                                zoneRegion.loop_end += pshdr->endLoop;
703
                                                                zoneRegion.loop_end += pshdr->endLoop;
704
                                                                if (pshdr->endLoop > 0) zoneRegion.loop_end -= 1;
704
                                                                if (pshdr->endLoop > 0) zoneRegion.loop_end -= 1;
705
                                                                if (zoneRegion.pitch_keycenter == -1) zoneRegion.pitch_keycenter = pshdr->originalPitch;
705
                                                                if (zoneRegion.pitch_keycenter == -1) zoneRegion.pitch_keycenter = pshdr->originalPitch;
706
                                                                zoneRegion.tune += pshdr->pitchCorrection;
706
                                                                zoneRegion.tune += pshdr->pitchCorrection;
707
                                                                zoneRegion.sample_rate = pshdr->sampleRate;
707
                                                                zoneRegion.sample_rate = pshdr->sampleRate;
708
                                                                if (zoneRegion.end && zoneRegion.end < fontSampleCount) zoneRegion.end++;
708
                                                                if (zoneRegion.end && zoneRegion.end < fontSampleCount) zoneRegion.end++;
709
                                                                else zoneRegion.end = fontSampleCount;
709
                                                                else zoneRegion.end = fontSampleCount;
710
710
711
                                                                preset->regions[region_index] = zoneRegion;
711
                                                                preset->regions[region_index] = zoneRegion;
712
                                                                region_index++;
712
                                                                region_index++;
713
                                                                hadSampleID = 1;
713
                                                                hadSampleID = 1;
714
                                                        }
714
                                                        }
715
                                                        else tsf_region_operator(&zoneRegion, pigen->genOper, &pigen->genAmount);
715
                                                        else tsf_region_operator(&zoneRegion, pigen->genOper, &pigen->genAmount);
716
                                                }
716
                                                }
717
717
718
                                                // Handle instrument's global zone.
718
                                                // Handle instrument's global zone.
719
                                                if (pibag == hydra->ibags + pinst->instBagNdx && !hadSampleID)
719
                                                if (pibag == hydra->ibags + pinst->instBagNdx && !hadSampleID)
720
                                                        instRegion = zoneRegion;
720
                                                        instRegion = zoneRegion;
721
721
722
                                                // Modulators (TODO)
722
                                                // Modulators (TODO)
723
                                                //if (ibag->instModNdx < ibag[1].instModNdx) addUnsupportedOpcode("any modulator");
723
                                                //if (ibag->instModNdx < ibag[1].instModNdx) addUnsupportedOpcode("any modulator");
724
                                        }
724
                                        }
725
                                        hadGenInstrument = 1;
725
                                        hadGenInstrument = 1;
726
                                }
726
                                }
727
                                else tsf_region_operator(&presetRegion, ppgen->genOper, &ppgen->genAmount);
727
                                else tsf_region_operator(&presetRegion, ppgen->genOper, &ppgen->genAmount);
728
                        }
728
                        }
729
729
730
                        // Modulators (TODO)
730
                        // Modulators (TODO)
731
                        //if (pbag->modNdx < pbag[1].modNdx) addUnsupportedOpcode("any modulator");
731
                        //if (pbag->modNdx < pbag[1].modNdx) addUnsupportedOpcode("any modulator");
732
732
733
                        // Handle preset's global zone.
733
                        // Handle preset's global zone.
734
                        if (ppbag == hydra->pbags + pphdr->presetBagNdx && !hadGenInstrument)
734
                        if (ppbag == hydra->pbags + pphdr->presetBagNdx && !hadGenInstrument)
735
                                globalRegion = presetRegion;
735
                                globalRegion = presetRegion;
736
                }
736
                }
737
        }
737
        }
738
}
738
}
739
739
740
static void tsf_load_samples(float** fontSamples, unsigned int* fontSampleCount, struct tsf_riffchunk *chunkSmpl, struct tsf_stream* stream)
740
static void tsf_load_samples(float** fontSamples, unsigned int* fontSampleCount, struct tsf_riffchunk *chunkSmpl, struct tsf_stream* stream)
741
{
741
{
742
        // Read sample data into float format buffer.
742
        // Read sample data into float format buffer.
743
        float* out; unsigned int samplesLeft, samplesToRead, samplesToConvert;
743
        float* out; unsigned int samplesLeft, samplesToRead, samplesToConvert;
744
        samplesLeft = *fontSampleCount = chunkSmpl->size / sizeof(short);
744
        samplesLeft = *fontSampleCount = chunkSmpl->size / sizeof(short);
745
        out = *fontSamples = (float*)TSF_MALLOC(samplesLeft * sizeof(float));
745
        out = *fontSamples = (float*)TSF_MALLOC(samplesLeft * sizeof(float));
746
        for (; samplesLeft; samplesLeft -= samplesToRead)
746
        for (; samplesLeft; samplesLeft -= samplesToRead)
747
        {
747
        {
748
                short sampleBuffer[1024], *in = sampleBuffer;;
748
                short sampleBuffer[1024], *in = sampleBuffer;;
749
                samplesToRead = (samplesLeft > 1024 ? 1024 : samplesLeft);
749
                samplesToRead = (samplesLeft > 1024 ? 1024 : samplesLeft);
750
                stream->read(stream->data, sampleBuffer, samplesToRead * sizeof(short));
750
                stream->read(stream->data, sampleBuffer, samplesToRead * sizeof(short));
751
751
752
                // Convert from signed 16-bit to float.
752
                // Convert from signed 16-bit to float.
753
                for (samplesToConvert = samplesToRead; samplesToConvert > 0; --samplesToConvert)
753
                for (samplesToConvert = samplesToRead; samplesToConvert > 0; --samplesToConvert)
754
                        // If we ever need to compile for big-endian platforms, we'll need to byte-swap here.
754
                        // If we ever need to compile for big-endian platforms, we'll need to byte-swap here.
755
                        *out++ = (float)(*in++ / 32767.0);
755
                        *out++ = (float)(*in++ / 32767.0);
756
        }
756
        }
757
}
757
}
758
758
759
static void tsf_voice_envelope_nextsegment(struct tsf_voice_envelope* e, short active_segment, float outSampleRate)
759
static void tsf_voice_envelope_nextsegment(struct tsf_voice_envelope* e, short active_segment, float outSampleRate)
760
{
760
{
761
        switch (active_segment)
761
        switch (active_segment)
762
        {
762
        {
763
                case TSF_SEGMENT_NONE:
763
                case TSF_SEGMENT_NONE:
764
                        e->samplesUntilNextSegment = (int)(e->parameters.delay * outSampleRate);
764
                        e->samplesUntilNextSegment = (int)(e->parameters.delay * outSampleRate);
765
                        if (e->samplesUntilNextSegment > 0)
765
                        if (e->samplesUntilNextSegment > 0)
766
                        {
766
                        {
767
                                e->segment = TSF_SEGMENT_DELAY;
767
                                e->segment = TSF_SEGMENT_DELAY;
768
                                e->segmentIsExponential = TSF_FALSE;
768
                                e->segmentIsExponential = TSF_FALSE;
769
                                e->level = 0.0;
769
                                e->level = 0.0;
770
                                e->slope = 0.0;
770
                                e->slope = 0.0;
771
                                return;
771
                                return;
772
                        }
772
                        }
773
                        /* fall through */
773
                        /* fall through */
774
                case TSF_SEGMENT_DELAY:
774
                case TSF_SEGMENT_DELAY:
775
                        e->samplesUntilNextSegment = (int)(e->parameters.attack * outSampleRate);
775
                        e->samplesUntilNextSegment = (int)(e->parameters.attack * outSampleRate);
776
                        if (e->samplesUntilNextSegment > 0)
776
                        if (e->samplesUntilNextSegment > 0)
777
                        {
777
                        {
778
                                if (!e->isAmpEnv)
778
                                if (!e->isAmpEnv)
779
                                {
779
                                {
780
                                        //mod env attack duration scales with velocity (velocity of 1 is full duration, max velocity is 0.125 times duration)
780
                                        //mod env attack duration scales with velocity (velocity of 1 is full duration, max velocity is 0.125 times duration)
781
                                        e->samplesUntilNextSegment = (int)(e->parameters.attack * ((145 - e->midiVelocity) / 144.0f) * outSampleRate);
781
                                        e->samplesUntilNextSegment = (int)(e->parameters.attack * ((145 - e->midiVelocity) / 144.0f) * outSampleRate);
782
                                }
782
                                }
783
                                e->segment = TSF_SEGMENT_ATTACK;
783
                                e->segment = TSF_SEGMENT_ATTACK;
784
                                e->segmentIsExponential = TSF_FALSE;
784
                                e->segmentIsExponential = TSF_FALSE;
785
                                e->level = 0.0f;
785
                                e->level = 0.0f;
786
                                e->slope = 1.0f / e->samplesUntilNextSegment;
786
                                e->slope = 1.0f / e->samplesUntilNextSegment;
787
                                return;
787
                                return;
788
                        }
788
                        }
789
                        /* fall through */
789
                        /* fall through */
790
                case TSF_SEGMENT_ATTACK:
790
                case TSF_SEGMENT_ATTACK:
791
                        e->samplesUntilNextSegment = (int)(e->parameters.hold * outSampleRate);
791
                        e->samplesUntilNextSegment = (int)(e->parameters.hold * outSampleRate);
792
                        if (e->samplesUntilNextSegment > 0)
792
                        if (e->samplesUntilNextSegment > 0)
793
                        {
793
                        {
794
                                e->segment = TSF_SEGMENT_HOLD;
794
                                e->segment = TSF_SEGMENT_HOLD;
795
                                e->segmentIsExponential = TSF_FALSE;
795
                                e->segmentIsExponential = TSF_FALSE;
796
                                e->level = 1.0f;
796
                                e->level = 1.0f;
797
                                e->slope = 0.0f;
797
                                e->slope = 0.0f;
798
                                return;
798
                                return;
799
                        }
799
                        }
800
                        /* fall through */
800
                        /* fall through */
801
                case TSF_SEGMENT_HOLD:
801
                case TSF_SEGMENT_HOLD:
802
                        e->samplesUntilNextSegment = (int)(e->parameters.decay * outSampleRate);
802
                        e->samplesUntilNextSegment = (int)(e->parameters.decay * outSampleRate);
803
                        if (e->samplesUntilNextSegment > 0)
803
                        if (e->samplesUntilNextSegment > 0)
804
                        {
804
                        {
805
                                e->segment = TSF_SEGMENT_DECAY;
805
                                e->segment = TSF_SEGMENT_DECAY;
806
                                e->level = 1.0f;
806
                                e->level = 1.0f;
807
                                if (e->isAmpEnv)
807
                                if (e->isAmpEnv)
808
                                {
808
                                {
809
                                        // I don't truly understand this; just following what LinuxSampler does.
809
                                        // I don't truly understand this; just following what LinuxSampler does.
810
                                        float mysterySlope = -9.226f / e->samplesUntilNextSegment;
810
                                        float mysterySlope = -9.226f / e->samplesUntilNextSegment;
811
                                        e->slope = TSF_EXPF(mysterySlope);
811
                                        e->slope = TSF_EXPF(mysterySlope);
812
                                        e->segmentIsExponential = TSF_TRUE;
812
                                        e->segmentIsExponential = TSF_TRUE;
813
                                        if (e->parameters.sustain > 0.0f)
813
                                        if (e->parameters.sustain > 0.0f)
814
                                        {
814
                                        {
815
                                                // Again, this is following LinuxSampler's example, which is similar to
815
                                                // Again, this is following LinuxSampler's example, which is similar to
816
                                                // SF2-style decay, where "decay" specifies the time it would take to
816
                                                // SF2-style decay, where "decay" specifies the time it would take to
817
                                                // get to zero, not to the sustain level.  The SFZ spec is not that
817
                                                // get to zero, not to the sustain level.  The SFZ spec is not that
818
                                                // specific about what "decay" means, so perhaps it's really supposed
818
                                                // specific about what "decay" means, so perhaps it's really supposed
819
                                                // to specify the time to reach the sustain level.
819
                                                // to specify the time to reach the sustain level.
820
                                                e->samplesUntilNextSegment = (int)(TSF_LOG(e->parameters.sustain) / mysterySlope);
820
                                                e->samplesUntilNextSegment = (int)(TSF_LOG(e->parameters.sustain) / mysterySlope);
821
                                        }
821
                                        }
822
                                }
822
                                }
823
                                else
823
                                else
824
                                {
824
                                {
825
                                        e->slope = -1.0f / e->samplesUntilNextSegment;
825
                                        e->slope = -1.0f / e->samplesUntilNextSegment;
826
                                        e->samplesUntilNextSegment = (int)(e->parameters.decay * (1.0f - e->parameters.sustain) * outSampleRate);
826
                                        e->samplesUntilNextSegment = (int)(e->parameters.decay * (1.0f - e->parameters.sustain) * outSampleRate);
827
                                        e->segmentIsExponential = TSF_FALSE;
827
                                        e->segmentIsExponential = TSF_FALSE;
828
                                }
828
                                }
829
                                return;
829
                                return;
830
                        }
830
                        }
831
                        /* fall through */
831
                        /* fall through */
832
                case TSF_SEGMENT_DECAY:
832
                case TSF_SEGMENT_DECAY:
833
                        e->segment = TSF_SEGMENT_SUSTAIN;
833
                        e->segment = TSF_SEGMENT_SUSTAIN;
834
                        e->level = e->parameters.sustain;
834
                        e->level = e->parameters.sustain;
835
                        e->slope = 0.0f;
835
                        e->slope = 0.0f;
836
                        e->samplesUntilNextSegment = 0x7FFFFFFF;
836
                        e->samplesUntilNextSegment = 0x7FFFFFFF;
837
                        e->segmentIsExponential = TSF_FALSE;
837
                        e->segmentIsExponential = TSF_FALSE;
838
                        return;
838
                        return;
839
                case TSF_SEGMENT_SUSTAIN:
839
                case TSF_SEGMENT_SUSTAIN:
840
                        e->segment = TSF_SEGMENT_RELEASE;
840
                        e->segment = TSF_SEGMENT_RELEASE;
841
                        e->samplesUntilNextSegment = (int)((e->parameters.release <= 0 ? TSF_FASTRELEASETIME : e->parameters.release) * outSampleRate);
841
                        e->samplesUntilNextSegment = (int)((e->parameters.release <= 0 ? TSF_FASTRELEASETIME : e->parameters.release) * outSampleRate);
842
                        if (e->isAmpEnv)
842
                        if (e->isAmpEnv)
843
                        {
843
                        {
844
                                // I don't truly understand this; just following what LinuxSampler does.
844
                                // I don't truly understand this; just following what LinuxSampler does.
845
                                float mysterySlope = -9.226f / e->samplesUntilNextSegment;
845
                                float mysterySlope = -9.226f / e->samplesUntilNextSegment;
846
                                e->slope = TSF_EXPF(mysterySlope);
846
                                e->slope = TSF_EXPF(mysterySlope);
847
                                e->segmentIsExponential = TSF_TRUE;
847
                                e->segmentIsExponential = TSF_TRUE;
848
                        }
848
                        }
849
                        else
849
                        else
850
                        {
850
                        {
851
                                e->slope = -e->level / e->samplesUntilNextSegment;
851
                                e->slope = -e->level / e->samplesUntilNextSegment;
852
                                e->segmentIsExponential = TSF_FALSE;
852
                                e->segmentIsExponential = TSF_FALSE;
853
                        }
853
                        }
854
                        return;
854
                        return;
855
                case TSF_SEGMENT_RELEASE:
855
                case TSF_SEGMENT_RELEASE:
856
                default:
856
                default:
857
                        e->segment = TSF_SEGMENT_DONE;
857
                        e->segment = TSF_SEGMENT_DONE;
858
                        e->segmentIsExponential = TSF_FALSE;
858
                        e->segmentIsExponential = TSF_FALSE;
859
                        e->level = e->slope = 0.0f;
859
                        e->level = e->slope = 0.0f;
860
                        e->samplesUntilNextSegment = 0x7FFFFFF;
860
                        e->samplesUntilNextSegment = 0x7FFFFFF;
861
        }
861
        }
862
}
862
}
863
863
864
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)
864
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)
865
{
865
{
866
        e->parameters = *new_parameters;
866
        e->parameters = *new_parameters;
867
        if (e->parameters.keynumToHold)
867
        if (e->parameters.keynumToHold)
868
        {
868
        {
869
                e->parameters.hold += e->parameters.keynumToHold * (60.0f - midiNoteNumber);
869
                e->parameters.hold += e->parameters.keynumToHold * (60.0f - midiNoteNumber);
870
                e->parameters.hold = (e->parameters.hold < -10000.0f ? 0.0f : tsf_timecents2Secsf(e->parameters.hold));
870
                e->parameters.hold = (e->parameters.hold < -10000.0f ? 0.0f : tsf_timecents2Secsf(e->parameters.hold));
871
        }
871
        }
872
        if (e->parameters.keynumToDecay)
872
        if (e->parameters.keynumToDecay)
873
        {
873
        {
874
                e->parameters.decay += e->parameters.keynumToDecay * (60.0f - midiNoteNumber);
874
                e->parameters.decay += e->parameters.keynumToDecay * (60.0f - midiNoteNumber);
875
                e->parameters.decay = (e->parameters.decay < -10000.0f ? 0.0f : tsf_timecents2Secsf(e->parameters.decay));
875
                e->parameters.decay = (e->parameters.decay < -10000.0f ? 0.0f : tsf_timecents2Secsf(e->parameters.decay));
876
        }
876
        }
877
        e->midiVelocity = midiVelocity;
877
        e->midiVelocity = midiVelocity;
878
        e->isAmpEnv = isAmpEnv;
878
        e->isAmpEnv = isAmpEnv;
879
        tsf_voice_envelope_nextsegment(e, TSF_SEGMENT_NONE, outSampleRate);
879
        tsf_voice_envelope_nextsegment(e, TSF_SEGMENT_NONE, outSampleRate);
880
}
880
}
881
881
882
static void tsf_voice_envelope_process(struct tsf_voice_envelope* e, int numSamples, float outSampleRate)
882
static void tsf_voice_envelope_process(struct tsf_voice_envelope* e, int numSamples, float outSampleRate)
883
{
883
{
884
        if (e->slope)
884
        if (e->slope)
885
        {
885
        {
886
                if (e->segmentIsExponential) e->level *= TSF_POWF(e->slope, (float)numSamples);
886
                if (e->segmentIsExponential) e->level *= TSF_POWF(e->slope, (float)numSamples);
887
                else e->level += (e->slope * numSamples);
887
                else e->level += (e->slope * numSamples);
888
        }
888
        }
889
        if ((e->samplesUntilNextSegment -= numSamples) <= 0)
889
        if ((e->samplesUntilNextSegment -= numSamples) <= 0)
890
                tsf_voice_envelope_nextsegment(e, e->segment, outSampleRate);
890
                tsf_voice_envelope_nextsegment(e, e->segment, outSampleRate);
891
}
891
}
892
892
893
static void tsf_voice_lowpass_setup(struct tsf_voice_lowpass* e, float Fc)
893
static void tsf_voice_lowpass_setup(struct tsf_voice_lowpass* e, float Fc)
894
{
894
{
895
        // Lowpass filter from http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/
895
        // Lowpass filter from http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/
896
        double K = TSF_TAN(TSF_PI * Fc), KK = K * K;
896
        double K = TSF_TAN(TSF_PI * Fc), KK = K * K;
897
        double norm = 1 / (1 + K * e->QInv + KK);
897
        double norm = 1 / (1 + K * e->QInv + KK);
898
        e->a0 = KK * norm;
898
        e->a0 = KK * norm;
899
        e->a1 = 2 * e->a0;
899
        e->a1 = 2 * e->a0;
900
        e->b1 = 2 * (KK - 1) * norm;
900
        e->b1 = 2 * (KK - 1) * norm;
901
        e->b2 = (1 - K * e->QInv + KK) * norm;
901
        e->b2 = (1 - K * e->QInv + KK) * norm;
902
}
902
}
903
903
904
static float tsf_voice_lowpass_process(struct tsf_voice_lowpass* e, double In)
904
static float tsf_voice_lowpass_process(struct tsf_voice_lowpass* e, double In)
905
{
905
{
906
        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;
906
        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;
907
}
907
}
908
908
909
static void tsf_voice_lfo_setup(struct tsf_voice_lfo* e, float delay, int freqCents, float outSampleRate)
909
static void tsf_voice_lfo_setup(struct tsf_voice_lfo* e, float delay, int freqCents, float outSampleRate)
910
{
910
{
911
        e->samplesUntil = (int)(delay * outSampleRate);
911
        e->samplesUntil = (int)(delay * outSampleRate);
912
        e->delta = (4.0f * tsf_cents2Hertz((float)freqCents) / outSampleRate);
912
        e->delta = (4.0f * tsf_cents2Hertz((float)freqCents) / outSampleRate);
913
        e->level = 0;
913
        e->level = 0;
914
}
914
}
915
915
916
static void tsf_voice_lfo_process(struct tsf_voice_lfo* e, int blockSamples)
916
static void tsf_voice_lfo_process(struct tsf_voice_lfo* e, int blockSamples)
917
{
917
{
918
        if (e->samplesUntil > blockSamples) { e->samplesUntil -= blockSamples; return; }
918
        if (e->samplesUntil > blockSamples) { e->samplesUntil -= blockSamples; return; }
919
        e->level += e->delta * blockSamples;
919
        e->level += e->delta * blockSamples;
920
        if      (e->level >  1.0f) { e->delta = -e->delta; e->level =  2.0f - e->level; }
920
        if      (e->level >  1.0f) { e->delta = -e->delta; e->level =  2.0f - e->level; }
921
        else if (e->level < -1.0f) { e->delta = -e->delta; e->level = -2.0f - e->level; }
921
        else if (e->level < -1.0f) { e->delta = -e->delta; e->level = -2.0f - e->level; }
922
}
922
}
923
923
924
static void tsf_voice_kill(struct tsf_voice* v)
924
static void tsf_voice_kill(struct tsf_voice* v)
925
{
925
{
926
        v->playingPreset = -1;
926
        v->playingPreset = -1;
927
}
927
}
928
928
929
static void tsf_voice_end(struct tsf_voice* v, float outSampleRate)
929
static void tsf_voice_end(struct tsf_voice* v, float outSampleRate)
930
{
930
{
931
        tsf_voice_envelope_nextsegment(&v->ampenv, TSF_SEGMENT_SUSTAIN, outSampleRate);
931
        tsf_voice_envelope_nextsegment(&v->ampenv, TSF_SEGMENT_SUSTAIN, outSampleRate);
932
        tsf_voice_envelope_nextsegment(&v->modenv, TSF_SEGMENT_SUSTAIN, outSampleRate);
932
        tsf_voice_envelope_nextsegment(&v->modenv, TSF_SEGMENT_SUSTAIN, outSampleRate);
933
        if (v->region->loop_mode == TSF_LOOPMODE_SUSTAIN)
933
        if (v->region->loop_mode == TSF_LOOPMODE_SUSTAIN)
934
        {
934
        {
935
                // Continue playing, but stop looping.
935
                // Continue playing, but stop looping.
936
                v->loopEnd = v->loopStart;
936
                v->loopEnd = v->loopStart;
937
        }
937
        }
938
}
938
}
939
939
940
static void tsf_voice_endquick(struct tsf_voice* v, float outSampleRate)
940
static void tsf_voice_endquick(struct tsf_voice* v, float outSampleRate)
941
{
941
{
942
        v->ampenv.parameters.release = 0.0f; tsf_voice_envelope_nextsegment(&v->ampenv, TSF_SEGMENT_SUSTAIN, outSampleRate);
942
        v->ampenv.parameters.release = 0.0f; tsf_voice_envelope_nextsegment(&v->ampenv, TSF_SEGMENT_SUSTAIN, outSampleRate);
943
        v->modenv.parameters.release = 0.0f; tsf_voice_envelope_nextsegment(&v->modenv, TSF_SEGMENT_SUSTAIN, outSampleRate);
943
        v->modenv.parameters.release = 0.0f; tsf_voice_envelope_nextsegment(&v->modenv, TSF_SEGMENT_SUSTAIN, outSampleRate);
944
}
944
}
945
945
946
static void tsf_voice_calcpitchratio(struct tsf_voice* v, float pitchShift, float outSampleRate)
946
static void tsf_voice_calcpitchratio(struct tsf_voice* v, float pitchShift, float outSampleRate)
947
{
947
{
948
        double note = v->playingKey + v->region->transpose + v->region->tune / 100.0;
948
        double note = v->playingKey + v->region->transpose + v->region->tune / 100.0;
949
        double adjustedPitch = v->region->pitch_keycenter + (note - v->region->pitch_keycenter) * (v->region->pitch_keytrack / 100.0);
949
        double adjustedPitch = v->region->pitch_keycenter + (note - v->region->pitch_keycenter) * (v->region->pitch_keytrack / 100.0);
950
        if (pitchShift) adjustedPitch += pitchShift;
950
        if (pitchShift) adjustedPitch += pitchShift;
951
        v->pitchInputTimecents = adjustedPitch * 100.0;
951
        v->pitchInputTimecents = adjustedPitch * 100.0;
952
        v->pitchOutputFactor = v->region->sample_rate / (tsf_timecents2Secsd(v->region->pitch_keycenter * 100.0) * outSampleRate);
952
        v->pitchOutputFactor = v->region->sample_rate / (tsf_timecents2Secsd(v->region->pitch_keycenter * 100.0) * outSampleRate);
953
}
953
}
954
954
955
static void tsf_voice_render(tsf* f, struct tsf_voice* v, float* outputBuffer, int numSamples)
955
static void tsf_voice_render(tsf* f, struct tsf_voice* v, float* outputBuffer, int numSamples)
956
{
956
{
957
        struct tsf_region* region = v->region;
957
        struct tsf_region* region = v->region;
958
        float* input = f->fontSamples;
958
        float* input = f->fontSamples;
959
        float* outL = outputBuffer;
959
        float* outL = outputBuffer;
960
        float* outR = (f->outputmode == TSF_STEREO_UNWEAVED ? outL + numSamples : TSF_NULL);
960
        float* outR = (f->outputmode == TSF_STEREO_UNWEAVED ? outL + numSamples : TSF_NULL);
961
961
962
        // Cache some values, to give them at least some chance of ending up in registers.
962
        // Cache some values, to give them at least some chance of ending up in registers.
963
        TSF_BOOL updateModEnv = (region->modEnvToPitch || region->modEnvToFilterFc);
963
        TSF_BOOL updateModEnv = (region->modEnvToPitch || region->modEnvToFilterFc);
964
        TSF_BOOL updateModLFO = (v->modlfo.delta && (region->modLfoToPitch || region->modLfoToFilterFc || region->modLfoToVolume));
964
        TSF_BOOL updateModLFO = (v->modlfo.delta && (region->modLfoToPitch || region->modLfoToFilterFc || region->modLfoToVolume));
965
        TSF_BOOL updateVibLFO = (v->viblfo.delta && (region->vibLfoToPitch));
965
        TSF_BOOL updateVibLFO = (v->viblfo.delta && (region->vibLfoToPitch));
966
        TSF_BOOL isLooping    = (v->loopStart < v->loopEnd);
966
        TSF_BOOL isLooping    = (v->loopStart < v->loopEnd);
967
        unsigned int tmpLoopStart = v->loopStart, tmpLoopEnd = v->loopEnd;
967
        unsigned int tmpLoopStart = v->loopStart, tmpLoopEnd = v->loopEnd;
968
        double tmpSampleEndDbl = (double)region->end, tmpLoopEndDbl = (double)tmpLoopEnd + 1.0;
968
        double tmpSampleEndDbl = (double)region->end, tmpLoopEndDbl = (double)tmpLoopEnd + 1.0;
969
        double tmpSourceSamplePosition = v->sourceSamplePosition;
969
        double tmpSourceSamplePosition = v->sourceSamplePosition;
970
        struct tsf_voice_lowpass tmpLowpass = v->lowpass;
970
        struct tsf_voice_lowpass tmpLowpass = v->lowpass;
971
971
972
        TSF_BOOL dynamicLowpass = (region->modLfoToFilterFc || region->modEnvToFilterFc);
972
        TSF_BOOL dynamicLowpass = (region->modLfoToFilterFc || region->modEnvToFilterFc);
973
        float tmpSampleRate, tmpInitialFilterFc, tmpModLfoToFilterFc, tmpModEnvToFilterFc;
973
        float tmpSampleRate, tmpInitialFilterFc, tmpModLfoToFilterFc, tmpModEnvToFilterFc;
974
974
975
        TSF_BOOL dynamicPitchRatio = (region->modLfoToPitch || region->modEnvToPitch || region->vibLfoToPitch);
975
        TSF_BOOL dynamicPitchRatio = (region->modLfoToPitch || region->modEnvToPitch || region->vibLfoToPitch);
976
        double pitchRatio;
976
        double pitchRatio;
977
        float tmpModLfoToPitch, tmpVibLfoToPitch, tmpModEnvToPitch;
977
        float tmpModLfoToPitch, tmpVibLfoToPitch, tmpModEnvToPitch;
978
978
979
        TSF_BOOL dynamicGain = (region->modLfoToVolume != 0);
979
        TSF_BOOL dynamicGain = (region->modLfoToVolume != 0);
980
        float noteGain = 0, tmpModLfoToVolume;
980
        float noteGain = 0, tmpModLfoToVolume;
981
981
982
        if (dynamicLowpass) tmpSampleRate = f->outSampleRate, tmpInitialFilterFc = (float)region->initialFilterFc, tmpModLfoToFilterFc = (float)region->modLfoToFilterFc, tmpModEnvToFilterFc = (float)region->modEnvToFilterFc;
982
        if (dynamicLowpass) tmpSampleRate = f->outSampleRate, tmpInitialFilterFc = (float)region->initialFilterFc, tmpModLfoToFilterFc = (float)region->modLfoToFilterFc, tmpModEnvToFilterFc = (float)region->modEnvToFilterFc;
983
        else tmpSampleRate = 0, tmpInitialFilterFc = 0, tmpModLfoToFilterFc = 0, tmpModEnvToFilterFc = 0;
983
        else tmpSampleRate = 0, tmpInitialFilterFc = 0, tmpModLfoToFilterFc = 0, tmpModEnvToFilterFc = 0;
984
984
985
        if (dynamicPitchRatio) pitchRatio = 0, tmpModLfoToPitch = (float)region->modLfoToPitch, tmpVibLfoToPitch = (float)region->vibLfoToPitch, tmpModEnvToPitch = (float)region->modEnvToPitch;
985
        if (dynamicPitchRatio) pitchRatio = 0, tmpModLfoToPitch = (float)region->modLfoToPitch, tmpVibLfoToPitch = (float)region->vibLfoToPitch, tmpModEnvToPitch = (float)region->modEnvToPitch;
986
        else pitchRatio = tsf_timecents2Secsd(v->pitchInputTimecents) * v->pitchOutputFactor, tmpModLfoToPitch = 0, tmpVibLfoToPitch = 0, tmpModEnvToPitch = 0;
986
        else pitchRatio = tsf_timecents2Secsd(v->pitchInputTimecents) * v->pitchOutputFactor, tmpModLfoToPitch = 0, tmpVibLfoToPitch = 0, tmpModEnvToPitch = 0;
987
987
988
        if (dynamicGain) tmpModLfoToVolume = (float)region->modLfoToVolume * 0.1f;
988
        if (dynamicGain) tmpModLfoToVolume = (float)region->modLfoToVolume * 0.1f;
989
        else noteGain = tsf_decibelsToGain(v->noteGainDB), tmpModLfoToVolume = 0;
989
        else noteGain = tsf_decibelsToGain(v->noteGainDB), tmpModLfoToVolume = 0;
990
990
991
        while (numSamples)
991
        while (numSamples)
992
        {
992
        {
993
                float gainMono, gainLeft, gainRight;
993
                float gainMono, gainLeft, gainRight;
994
                int blockSamples = (numSamples > TSF_RENDER_EFFECTSAMPLEBLOCK ? TSF_RENDER_EFFECTSAMPLEBLOCK : numSamples);
994
                int blockSamples = (numSamples > TSF_RENDER_EFFECTSAMPLEBLOCK ? TSF_RENDER_EFFECTSAMPLEBLOCK : numSamples);
995
                numSamples -= blockSamples;
995
                numSamples -= blockSamples;
996
996
997
                if (dynamicLowpass)
997
                if (dynamicLowpass)
998
                {
998
                {
999
                        float fres = tmpInitialFilterFc + v->modlfo.level * tmpModLfoToFilterFc + v->modenv.level * tmpModEnvToFilterFc;
999
                        float fres = tmpInitialFilterFc + v->modlfo.level * tmpModLfoToFilterFc + v->modenv.level * tmpModEnvToFilterFc;
-
 
1000
                        float lowpassFc = (fres <= 13500 ? tsf_cents2Hertz(fres) / f->outSampleRate : 1.0f);
1000
                        tmpLowpass.active = (fres <= 13500.0f);
1001
                        tmpLowpass.active = (lowpassFc < 0.499f);
1001
                        if (tmpLowpass.active) tsf_voice_lowpass_setup(&tmpLowpass, tsf_cents2Hertz(fres) / tmpSampleRate);
1002
                        if (tmpLowpass.active) tsf_voice_lowpass_setup(&tmpLowpass, lowpassFc);
1002
                }
1003
                }
1003
1004
1004
                if (dynamicPitchRatio)
1005
                if (dynamicPitchRatio)
1005
                        pitchRatio = tsf_timecents2Secsd(v->pitchInputTimecents + (v->modlfo.level * tmpModLfoToPitch + v->viblfo.level * tmpVibLfoToPitch + v->modenv.level * tmpModEnvToPitch)) * v->pitchOutputFactor;
1006
                        pitchRatio = tsf_timecents2Secsd(v->pitchInputTimecents + (v->modlfo.level * tmpModLfoToPitch + v->viblfo.level * tmpVibLfoToPitch + v->modenv.level * tmpModEnvToPitch)) * v->pitchOutputFactor;
1006
1007
1007
                if (dynamicGain)
1008
                if (dynamicGain)
1008
                        noteGain = tsf_decibelsToGain(v->noteGainDB + (v->modlfo.level * tmpModLfoToVolume));
1009
                        noteGain = tsf_decibelsToGain(v->noteGainDB + (v->modlfo.level * tmpModLfoToVolume));
1009
1010
1010
                gainMono = noteGain * v->ampenv.level;
1011
                gainMono = noteGain * v->ampenv.level;
1011
1012
1012
                // Update EG.
1013
                // Update EG.
1013
                tsf_voice_envelope_process(&v->ampenv, blockSamples, f->outSampleRate);
1014
                tsf_voice_envelope_process(&v->ampenv, blockSamples, f->outSampleRate);
1014
                if (updateModEnv) tsf_voice_envelope_process(&v->modenv, blockSamples, f->outSampleRate);
1015
                if (updateModEnv) tsf_voice_envelope_process(&v->modenv, blockSamples, f->outSampleRate);
1015
1016
1016
                // Update LFOs.
1017
                // Update LFOs.
1017
                if (updateModLFO) tsf_voice_lfo_process(&v->modlfo, blockSamples);
1018
                if (updateModLFO) tsf_voice_lfo_process(&v->modlfo, blockSamples);
1018
                if (updateVibLFO) tsf_voice_lfo_process(&v->viblfo, blockSamples);
1019
                if (updateVibLFO) tsf_voice_lfo_process(&v->viblfo, blockSamples);
1019
1020
1020
                switch (f->outputmode)
1021
                switch (f->outputmode)
1021
                {
1022
                {
1022
                        case TSF_STEREO_INTERLEAVED:
1023
                        case TSF_STEREO_INTERLEAVED:
1023
                                gainLeft = gainMono * v->panFactorLeft, gainRight = gainMono * v->panFactorRight;
1024
                                gainLeft = gainMono * v->panFactorLeft, gainRight = gainMono * v->panFactorRight;
1024
                                while (blockSamples-- && tmpSourceSamplePosition < tmpSampleEndDbl)
1025
                                while (blockSamples-- && tmpSourceSamplePosition < tmpSampleEndDbl)
1025
                                {
1026
                                {
1026
                                        unsigned int pos = (unsigned int)tmpSourceSamplePosition, nextPos = (pos >= tmpLoopEnd && isLooping ? tmpLoopStart : pos + 1);
1027
                                        unsigned int pos = (unsigned int)tmpSourceSamplePosition, nextPos = (pos >= tmpLoopEnd && isLooping ? tmpLoopStart : pos + 1);
1027
1028
1028
                                        // Simple linear interpolation.
1029
                                        // Simple linear interpolation.
1029
                                        float alpha = (float)(tmpSourceSamplePosition - pos), val = (input[pos] * (1.0f - alpha) + input[nextPos] * alpha);
1030
                                        float alpha = (float)(tmpSourceSamplePosition - pos), val = (input[pos] * (1.0f - alpha) + input[nextPos] * alpha);
1030
1031
1031
                                        // Low-pass filter.
1032
                                        // Low-pass filter.
1032
                                        if (tmpLowpass.active) val = tsf_voice_lowpass_process(&tmpLowpass, val);
1033
                                        if (tmpLowpass.active) val = tsf_voice_lowpass_process(&tmpLowpass, val);
1033
1034
1034
                                        *outL++ += val * gainLeft;
1035
                                        *outL++ += val * gainLeft;
1035
                                        *outL++ += val * gainRight;
1036
                                        *outL++ += val * gainRight;
1036
1037
1037
                                        // Next sample.
1038
                                        // Next sample.
1038
                                        tmpSourceSamplePosition += pitchRatio;
1039
                                        tmpSourceSamplePosition += pitchRatio;
1039
                                        if (tmpSourceSamplePosition >= tmpLoopEndDbl && isLooping) tmpSourceSamplePosition -= (tmpLoopEnd - tmpLoopStart + 1.0);
1040
                                        if (tmpSourceSamplePosition >= tmpLoopEndDbl && isLooping) tmpSourceSamplePosition -= (tmpLoopEnd - tmpLoopStart + 1.0);
1040
                                }
1041
                                }
1041
                                break;
1042
                                break;
1042
1043
1043
                        case TSF_STEREO_UNWEAVED:
1044
                        case TSF_STEREO_UNWEAVED:
1044
                                gainLeft = gainMono * v->panFactorLeft, gainRight = gainMono * v->panFactorRight;
1045
                                gainLeft = gainMono * v->panFactorLeft, gainRight = gainMono * v->panFactorRight;
1045
                                while (blockSamples-- && tmpSourceSamplePosition < tmpSampleEndDbl)
1046
                                while (blockSamples-- && tmpSourceSamplePosition < tmpSampleEndDbl)
1046
                                {
1047
                                {
1047
                                        unsigned int pos = (unsigned int)tmpSourceSamplePosition, nextPos = (pos >= tmpLoopEnd && isLooping ? tmpLoopStart : pos + 1);
1048
                                        unsigned int pos = (unsigned int)tmpSourceSamplePosition, nextPos = (pos >= tmpLoopEnd && isLooping ? tmpLoopStart : pos + 1);
1048
1049
1049
                                        // Simple linear interpolation.
1050
                                        // Simple linear interpolation.
1050
                                        float alpha = (float)(tmpSourceSamplePosition - pos), val = (input[pos] * (1.0f - alpha) + input[nextPos] * alpha);
1051
                                        float alpha = (float)(tmpSourceSamplePosition - pos), val = (input[pos] * (1.0f - alpha) + input[nextPos] * alpha);
1051
1052
1052
                                        // Low-pass filter.
1053
                                        // Low-pass filter.
1053
                                        if (tmpLowpass.active) val = tsf_voice_lowpass_process(&tmpLowpass, val);
1054
                                        if (tmpLowpass.active) val = tsf_voice_lowpass_process(&tmpLowpass, val);
1054
1055
1055
                                        *outL++ += val * gainLeft;
1056
                                        *outL++ += val * gainLeft;
1056
                                        *outR++ += val * gainRight;
1057
                                        *outR++ += val * gainRight;
1057
1058
1058
                                        // Next sample.
1059
                                        // Next sample.
1059
                                        tmpSourceSamplePosition += pitchRatio;
1060
                                        tmpSourceSamplePosition += pitchRatio;
1060
                                        if (tmpSourceSamplePosition >= tmpLoopEndDbl && isLooping) tmpSourceSamplePosition -= (tmpLoopEnd - tmpLoopStart + 1.0);
1061
                                        if (tmpSourceSamplePosition >= tmpLoopEndDbl && isLooping) tmpSourceSamplePosition -= (tmpLoopEnd - tmpLoopStart + 1.0);
1061
                                }
1062
                                }
1062
                                break;
1063
                                break;
1063
1064
1064
                        case TSF_MONO:
1065
                        case TSF_MONO:
1065
                                while (blockSamples-- && tmpSourceSamplePosition < tmpSampleEndDbl)
1066
                                while (blockSamples-- && tmpSourceSamplePosition < tmpSampleEndDbl)
1066
                                {
1067
                                {
1067
                                        unsigned int pos = (unsigned int)tmpSourceSamplePosition, nextPos = (pos >= tmpLoopEnd && isLooping ? tmpLoopStart : pos + 1);
1068
                                        unsigned int pos = (unsigned int)tmpSourceSamplePosition, nextPos = (pos >= tmpLoopEnd && isLooping ? tmpLoopStart : pos + 1);
1068
1069
1069
                                        // Simple linear interpolation.
1070
                                        // Simple linear interpolation.
1070
                                        float alpha = (float)(tmpSourceSamplePosition - pos), val = (input[pos] * (1.0f - alpha) + input[nextPos] * alpha);
1071
                                        float alpha = (float)(tmpSourceSamplePosition - pos), val = (input[pos] * (1.0f - alpha) + input[nextPos] * alpha);
1071
1072
1072
                                        // Low-pass filter.
1073
                                        // Low-pass filter.
1073
                                        if (tmpLowpass.active) val = tsf_voice_lowpass_process(&tmpLowpass, val);
1074
                                        if (tmpLowpass.active) val = tsf_voice_lowpass_process(&tmpLowpass, val);
1074
1075
1075
                                        *outL++ += val * gainMono;
1076
                                        *outL++ += val * gainMono;
1076
1077
1077
                                        // Next sample.
1078
                                        // Next sample.
1078
                                        tmpSourceSamplePosition += pitchRatio;
1079
                                        tmpSourceSamplePosition += pitchRatio;
1079
                                        if (tmpSourceSamplePosition >= tmpLoopEndDbl && isLooping) tmpSourceSamplePosition -= (tmpLoopEnd - tmpLoopStart + 1.0);
1080
                                        if (tmpSourceSamplePosition >= tmpLoopEndDbl && isLooping) tmpSourceSamplePosition -= (tmpLoopEnd - tmpLoopStart + 1.0);
1080
                                }
1081
                                }
1081
                                break;
1082
                                break;
1082
                }
1083
                }
1083
1084
1084
                if (tmpSourceSamplePosition >= tmpSampleEndDbl || v->ampenv.segment == TSF_SEGMENT_DONE)
1085
                if (tmpSourceSamplePosition >= tmpSampleEndDbl || v->ampenv.segment == TSF_SEGMENT_DONE)
1085
                {
1086
                {
1086
                        tsf_voice_kill(v);
1087
                        tsf_voice_kill(v);
1087
                        return;
1088
                        return;
1088
                }
1089
                }
1089
        }
1090
        }
1090
1091
1091
        v->sourceSamplePosition = tmpSourceSamplePosition;
1092
        v->sourceSamplePosition = tmpSourceSamplePosition;
1092
        if (tmpLowpass.active || dynamicLowpass) v->lowpass = tmpLowpass;
1093
        if (tmpLowpass.active || dynamicLowpass) v->lowpass = tmpLowpass;
1093
}
1094
}
1094
1095
1095
TSFDEF tsf* tsf_load(struct tsf_stream* stream)
1096
TSFDEF tsf* tsf_load(struct tsf_stream* stream)
1096
{
1097
{
1097
        tsf* res = TSF_NULL;
1098
        tsf* res = TSF_NULL;
1098
        struct tsf_riffchunk chunkHead;
1099
        struct tsf_riffchunk chunkHead;
1099
        struct tsf_riffchunk chunkList;
1100
        struct tsf_riffchunk chunkList;
1100
        struct tsf_hydra hydra;
1101
        struct tsf_hydra hydra;
1101
        float* fontSamples = TSF_NULL;
1102
        float* fontSamples = TSF_NULL;
1102
        unsigned int fontSampleCount = 0;
1103
        unsigned int fontSampleCount = 0;
1103
1104
1104
        if (!tsf_riffchunk_read(TSF_NULL, &chunkHead, stream) || !TSF_FourCCEquals(chunkHead.id, "sfbk"))
1105
        if (!tsf_riffchunk_read(TSF_NULL, &chunkHead, stream) || !TSF_FourCCEquals(chunkHead.id, "sfbk"))
1105
        {
1106
        {
1106
                //if (e) *e = TSF_INVALID_NOSF2HEADER;
1107
                //if (e) *e = TSF_INVALID_NOSF2HEADER;
1107
                return res;
1108
                return res;
1108
        }
1109
        }
1109
1110
1110
        // Read hydra and locate sample data.
1111
        // Read hydra and locate sample data.
1111
        TSF_MEMSET(&hydra, 0, sizeof(hydra));
1112
        TSF_MEMSET(&hydra, 0, sizeof(hydra));
1112
        while (tsf_riffchunk_read(&chunkHead, &chunkList, stream))
1113
        while (tsf_riffchunk_read(&chunkHead, &chunkList, stream))
1113
        {
1114
        {
1114
                struct tsf_riffchunk chunk;
1115
                struct tsf_riffchunk chunk;
1115
                if (TSF_FourCCEquals(chunkList.id, "pdta"))
1116
                if (TSF_FourCCEquals(chunkList.id, "pdta"))
1116
                {
1117
                {
1117
                        while (tsf_riffchunk_read(&chunkList, &chunk, stream))
1118
                        while (tsf_riffchunk_read(&chunkList, &chunk, stream))
1118
                        {
1119
                        {
1119
                                #define HandleChunk(chunkName) (TSF_FourCCEquals(chunk.id, #chunkName) && !(chunk.size % chunkName##SizeInFile)) \
1120
                                #define HandleChunk(chunkName) (TSF_FourCCEquals(chunk.id, #chunkName) && !(chunk.size % chunkName##SizeInFile)) \
1120
                                        { \
1121
                                        { \
1121
                                                int num = chunk.size / chunkName##SizeInFile, i; \
1122
                                                int num = chunk.size / chunkName##SizeInFile, i; \
1122
                                                hydra.chunkName##Num = num; \
1123
                                                hydra.chunkName##Num = num; \
1123
                                                hydra.chunkName##s = (struct tsf_hydra_##chunkName*)TSF_MALLOC(num * sizeof(struct tsf_hydra_##chunkName)); \
1124
                                                hydra.chunkName##s = (struct tsf_hydra_##chunkName*)TSF_MALLOC(num * sizeof(struct tsf_hydra_##chunkName)); \
1124
                                                for (i = 0; i < num; ++i) tsf_hydra_read_##chunkName(&hydra.chunkName##s[i], stream); \
1125
                                                for (i = 0; i < num; ++i) tsf_hydra_read_##chunkName(&hydra.chunkName##s[i], stream); \
1125
                                        }
1126
                                        }
1126
                                enum
1127
                                enum
1127
                                {
1128
                                {
1128
                                        phdrSizeInFile = 38, pbagSizeInFile =  4, pmodSizeInFile = 10,
1129
                                        phdrSizeInFile = 38, pbagSizeInFile =  4, pmodSizeInFile = 10,
1129
                                        pgenSizeInFile =  4, instSizeInFile = 22, ibagSizeInFile =  4,
1130
                                        pgenSizeInFile =  4, instSizeInFile = 22, ibagSizeInFile =  4,
1130
                                        imodSizeInFile = 10, igenSizeInFile =  4, shdrSizeInFile = 46
1131
                                        imodSizeInFile = 10, igenSizeInFile =  4, shdrSizeInFile = 46
1131
                                };
1132
                                };
1132
                                if      HandleChunk(phdr) else if HandleChunk(pbag) else if HandleChunk(pmod)
1133
                                if      HandleChunk(phdr) else if HandleChunk(pbag) else if HandleChunk(pmod)
1133
                                else if HandleChunk(pgen) else if HandleChunk(inst) else if HandleChunk(ibag)
1134
                                else if HandleChunk(pgen) else if HandleChunk(inst) else if HandleChunk(ibag)
1134
                                else if HandleChunk(imod) else if HandleChunk(igen) else if HandleChunk(shdr)
1135
                                else if HandleChunk(imod) else if HandleChunk(igen) else if HandleChunk(shdr)
1135
                                else stream->skip(stream->data, chunk.size);
1136
                                else stream->skip(stream->data, chunk.size);
1136
                                #undef HandleChunk
1137
                                #undef HandleChunk
1137
                        }
1138
                        }
1138
                }
1139
                }
1139
                else if (TSF_FourCCEquals(chunkList.id, "sdta"))
1140
                else if (TSF_FourCCEquals(chunkList.id, "sdta"))
1140
                {
1141
                {
1141
                        while (tsf_riffchunk_read(&chunkList, &chunk, stream))
1142
                        while (tsf_riffchunk_read(&chunkList, &chunk, stream))
1142
                        {
1143
                        {
1143
                                if (TSF_FourCCEquals(chunk.id, "smpl"))
1144
                                if (TSF_FourCCEquals(chunk.id, "smpl"))
1144
                                {
1145
                                {
1145
                                        tsf_load_samples(&fontSamples, &fontSampleCount, &chunk, stream);
1146
                                        tsf_load_samples(&fontSamples, &fontSampleCount, &chunk, stream);
1146
                                }
1147
                                }
1147
                                else stream->skip(stream->data, chunk.size);
1148
                                else stream->skip(stream->data, chunk.size);
1148
                        }
1149
                        }
1149
                }
1150
                }
1150
                else stream->skip(stream->data, chunkList.size);
1151
                else stream->skip(stream->data, chunkList.size);
1151
        }
1152
        }
1152
        if (!hydra.phdrs || !hydra.pbags || !hydra.pmods || !hydra.pgens || !hydra.insts || !hydra.ibags || !hydra.imods || !hydra.igens || !hydra.shdrs)
1153
        if (!hydra.phdrs || !hydra.pbags || !hydra.pmods || !hydra.pgens || !hydra.insts || !hydra.ibags || !hydra.imods || !hydra.igens || !hydra.shdrs)
1153
        {
1154
        {
1154
                //if (e) *e = TSF_INVALID_INCOMPLETE;
1155
                //if (e) *e = TSF_INVALID_INCOMPLETE;
1155
        }
1156
        }
1156
        else if (fontSamples == TSF_NULL)
1157
        else if (fontSamples == TSF_NULL)
1157
        {
1158
        {
1158
                //if (e) *e = TSF_INVALID_NOSAMPLEDATA;
1159
                //if (e) *e = TSF_INVALID_NOSAMPLEDATA;
1159
        }
1160
        }
1160
        else
1161
        else
1161
        {
1162
        {
1162
                res = (tsf*)TSF_MALLOC(sizeof(tsf));
1163
                res = (tsf*)TSF_MALLOC(sizeof(tsf));
1163
                TSF_MEMSET(res, 0, sizeof(tsf));
1164
                TSF_MEMSET(res, 0, sizeof(tsf));
1164
                res->presetNum = hydra.phdrNum - 1;
1165
                res->presetNum = hydra.phdrNum - 1;
1165
                res->presets = (struct tsf_preset*)TSF_MALLOC(res->presetNum * sizeof(struct tsf_preset));
1166
                res->presets = (struct tsf_preset*)TSF_MALLOC(res->presetNum * sizeof(struct tsf_preset));
1166
                res->fontSamples = fontSamples;
1167
                res->fontSamples = fontSamples;
1167
                res->outSampleRate = 44100.0f;
1168
                res->outSampleRate = 44100.0f;
1168
                fontSamples = TSF_NULL; //don't free below
1169
                fontSamples = TSF_NULL; //don't free below
1169
                tsf_load_presets(res, &hydra, fontSampleCount);
1170
                tsf_load_presets(res, &hydra, fontSampleCount);
1170
        }
1171
        }
1171
        TSF_FREE(hydra.phdrs); TSF_FREE(hydra.pbags); TSF_FREE(hydra.pmods);
1172
        TSF_FREE(hydra.phdrs); TSF_FREE(hydra.pbags); TSF_FREE(hydra.pmods);
1172
        TSF_FREE(hydra.pgens); TSF_FREE(hydra.insts); TSF_FREE(hydra.ibags);
1173
        TSF_FREE(hydra.pgens); TSF_FREE(hydra.insts); TSF_FREE(hydra.ibags);
1173
        TSF_FREE(hydra.imods); TSF_FREE(hydra.igens); TSF_FREE(hydra.shdrs);
1174
        TSF_FREE(hydra.imods); TSF_FREE(hydra.igens); TSF_FREE(hydra.shdrs);
1174
        TSF_FREE(fontSamples);
1175
        TSF_FREE(fontSamples);
1175
        return res;
1176
        return res;
1176
}
1177
}
1177
1178
1178
TSFDEF void tsf_close(tsf* f)
1179
TSFDEF void tsf_close(tsf* f)
1179
{
1180
{
1180
        struct tsf_preset *preset, *presetEnd;
1181
        struct tsf_preset *preset, *presetEnd;
1181
        if (!f) return;
1182
        if (!f) return;
1182
        for (preset = f->presets, presetEnd = preset + f->presetNum; preset != presetEnd; preset++)
1183
        for (preset = f->presets, presetEnd = preset + f->presetNum; preset != presetEnd; preset++)
1183
                TSF_FREE(preset->regions);
1184
                TSF_FREE(preset->regions);
1184
        TSF_FREE(f->presets);
1185
        TSF_FREE(f->presets);
1185
        TSF_FREE(f->fontSamples);
1186
        TSF_FREE(f->fontSamples);
1186
        TSF_FREE(f->voices);
1187
        TSF_FREE(f->voices);
1187
        if (f->channels) { TSF_FREE(f->channels->channels); TSF_FREE(f->channels); }
1188
        if (f->channels) { TSF_FREE(f->channels->channels); TSF_FREE(f->channels); }
1188
        TSF_FREE(f->outputSamples);
1189
        TSF_FREE(f->outputSamples);
1189
        TSF_FREE(f);
1190
        TSF_FREE(f);
1190
}
1191
}
1191
1192
1192
TSFDEF void tsf_reset(tsf* f)
1193
TSFDEF void tsf_reset(tsf* f)
1193
{
1194
{
1194
        struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum;
1195
        struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum;
1195
        for (; v != vEnd; v++)
1196
        for (; v != vEnd; v++)
1196
                if (v->playingPreset != -1 && (v->ampenv.segment < TSF_SEGMENT_RELEASE || v->ampenv.parameters.release))
1197
                if (v->playingPreset != -1 && (v->ampenv.segment < TSF_SEGMENT_RELEASE || v->ampenv.parameters.release))
1197
                        tsf_voice_endquick(v, f->outSampleRate);
1198
                        tsf_voice_endquick(v, f->outSampleRate);
1198
        if (f->channels) { TSF_FREE(f->channels->channels); TSF_FREE(f->channels); f->channels = TSF_NULL; }
1199
        if (f->channels) { TSF_FREE(f->channels->channels); TSF_FREE(f->channels); f->channels = TSF_NULL; }
1199
}
1200
}
1200
1201
1201
TSFDEF int tsf_get_presetindex(const tsf* f, int bank, int preset_number)
1202
TSFDEF int tsf_get_presetindex(const tsf* f, int bank, int preset_number)
1202
{
1203
{
1203
        const struct tsf_preset *presets;
1204
        const struct tsf_preset *presets;
1204
        int i, iMax;
1205
        int i, iMax;
1205
        for (presets = f->presets, i = 0, iMax = f->presetNum; i < iMax; i++)
1206
        for (presets = f->presets, i = 0, iMax = f->presetNum; i < iMax; i++)
1206
                if (presets[i].preset == preset_number && presets[i].bank == bank)
1207
                if (presets[i].preset == preset_number && presets[i].bank == bank)
1207
                        return i;
1208
                        return i;
1208
        return -1;
1209
        return -1;
1209
}
1210
}
1210
1211
1211
TSFDEF int tsf_get_presetcount(const tsf* f)
1212
TSFDEF int tsf_get_presetcount(const tsf* f)
1212
{
1213
{
1213
        return f->presetNum;
1214
        return f->presetNum;
1214
}
1215
}
1215
1216
1216
TSFDEF const char* tsf_get_presetname(const tsf* f, int preset)
1217
TSFDEF const char* tsf_get_presetname(const tsf* f, int preset)
1217
{
1218
{
1218
        return (preset < 0 || preset >= f->presetNum ? TSF_NULL : f->presets[preset].presetName);
1219
        return (preset < 0 || preset >= f->presetNum ? TSF_NULL : f->presets[preset].presetName);
1219
}
1220
}
1220
1221
1221
TSFDEF const char* tsf_bank_get_presetname(const tsf* f, int bank, int preset_number)
1222
TSFDEF const char* tsf_bank_get_presetname(const tsf* f, int bank, int preset_number)
1222
{
1223
{
1223
        return tsf_get_presetname(f, tsf_get_presetindex(f, bank, preset_number));
1224
        return tsf_get_presetname(f, tsf_get_presetindex(f, bank, preset_number));
1224
}
1225
}
1225
1226
1226
TSFDEF void tsf_set_output(tsf* f, enum TSFOutputMode outputmode, int samplerate, float global_gain_db)
1227
TSFDEF void tsf_set_output(tsf* f, enum TSFOutputMode outputmode, int samplerate, float global_gain_db)
1227
{
1228
{
1228
        f->outputmode = outputmode;
1229
        f->outputmode = outputmode;
1229
        f->outSampleRate = (float)(samplerate >= 1 ? samplerate : 44100.0f);
1230
        f->outSampleRate = (float)(samplerate >= 1 ? samplerate : 44100.0f);
1230
        f->globalGainDB = global_gain_db;
1231
        f->globalGainDB = global_gain_db;
1231
}
1232
}
1232
1233
1233
TSFDEF void tsf_note_on(tsf* f, int preset_index, int key, float vel)
1234
TSFDEF void tsf_note_on(tsf* f, int preset_index, int key, float vel)
1234
{
1235
{
1235
        short midiVelocity = (short)(vel * 127);
1236
        short midiVelocity = (short)(vel * 127);
1236
        int voicePlayIndex;
1237
        int voicePlayIndex;
1237
        struct tsf_region *region, *regionEnd;
1238
        struct tsf_region *region, *regionEnd;
1238
1239
1239
        if (preset_index < 0 || preset_index >= f->presetNum) return;
1240
        if (preset_index < 0 || preset_index >= f->presetNum) return;
1240
        if (vel <= 0.0f) { tsf_note_off(f, preset_index, key); return; }
1241
        if (vel <= 0.0f) { tsf_note_off(f, preset_index, key); return; }
1241
1242
1242
        // Play all matching regions.
1243
        // Play all matching regions.
1243
        voicePlayIndex = f->voicePlayIndex++;
1244
        voicePlayIndex = f->voicePlayIndex++;
1244
        for (region = f->presets[preset_index].regions, regionEnd = region + f->presets[preset_index].regionNum; region != regionEnd; region++)
1245
        for (region = f->presets[preset_index].regions, regionEnd = region + f->presets[preset_index].regionNum; region != regionEnd; region++)
1245
        {
1246
        {
1246
                struct tsf_voice *voice, *v, *vEnd; TSF_BOOL doLoop; float filterQDB;
1247
                struct tsf_voice *voice, *v, *vEnd; TSF_BOOL doLoop; float lowpassFilterQDB, lowpassFc;
1247
                if (key < region->lokey || key > region->hikey || midiVelocity < region->lovel || midiVelocity > region->hivel) continue;
1248
                if (key < region->lokey || key > region->hikey || midiVelocity < region->lovel || midiVelocity > region->hivel) continue;
1248
1249
1249
                voice = TSF_NULL, v = f->voices, vEnd = v + f->voiceNum;
1250
                voice = TSF_NULL, v = f->voices, vEnd = v + f->voiceNum;
1250
                if (region->group)
1251
                if (region->group)
1251
                {
1252
                {
1252
                        for (; v != vEnd; v++)
1253
                        for (; v != vEnd; v++)
1253
                                if (v->playingPreset == preset_index && v->region->group == region->group) tsf_voice_endquick(v, f->outSampleRate);
1254
                                if (v->playingPreset == preset_index && v->region->group == region->group) tsf_voice_endquick(v, f->outSampleRate);
1254
                                else if (v->playingPreset == -1 && !voice) voice = v;
1255
                                else if (v->playingPreset == -1 && !voice) voice = v;
1255
                }
1256
                }
1256
                else for (; v != vEnd; v++) if (v->playingPreset == -1) { voice = v; break; }
1257
                else for (; v != vEnd; v++) if (v->playingPreset == -1) { voice = v; break; }
1257
1258
1258
                if (!voice)
1259
                if (!voice)
1259
                {
1260
                {
1260
                        f->voiceNum += 4;
1261
                        f->voiceNum += 4;
1261
                        f->voices = (struct tsf_voice*)TSF_REALLOC(f->voices, f->voiceNum * sizeof(struct tsf_voice));
1262
                        f->voices = (struct tsf_voice*)TSF_REALLOC(f->voices, f->voiceNum * sizeof(struct tsf_voice));
1262
                        voice = &f->voices[f->voiceNum - 4];
1263
                        voice = &f->voices[f->voiceNum - 4];
1263
                        voice[1].playingPreset = voice[2].playingPreset = voice[3].playingPreset = -1;
1264
                        voice[1].playingPreset = voice[2].playingPreset = voice[3].playingPreset = -1;
1264
                }
1265
                }
1265
1266
1266
                voice->region = region;
1267
                voice->region = region;
1267
                voice->playingPreset = preset_index;
1268
                voice->playingPreset = preset_index;
1268
                voice->playingKey = key;
1269
                voice->playingKey = key;
1269
                voice->playIndex = voicePlayIndex;
1270
                voice->playIndex = voicePlayIndex;
1270
                voice->noteGainDB = f->globalGainDB - clamp(region->attenuation, 0.f, 144.f) - tsf_gainToDecibels(1.0f / vel);
1271
                voice->noteGainDB = f->globalGainDB - clamp(region->attenuation, 0.f, 144.f) - tsf_gainToDecibels(1.0f / vel);
1271
1272
1272
                if (f->channels)
1273
                if (f->channels)
1273
                {
1274
                {
1274
                        f->channels->setupVoice(f, voice);
1275
                        f->channels->setupVoice(f, voice);
1275
                }
1276
                }
1276
                else
1277
                else
1277
                {
1278
                {
1278
                        tsf_voice_calcpitchratio(voice, 0, f->outSampleRate);
1279
                        tsf_voice_calcpitchratio(voice, 0, f->outSampleRate);
1279
                        // 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).
1280
                        // 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).
1280
                        voice->panFactorLeft  = TSF_SQRTF(0.5f - region->pan);
1281
                        voice->panFactorLeft  = TSF_SQRTF(0.5f - region->pan);
1281
                        voice->panFactorRight = TSF_SQRTF(0.5f + region->pan);
1282
                        voice->panFactorRight = TSF_SQRTF(0.5f + region->pan);
1282
                }
1283
                }
1283
1284
1284
                // Offset/end.
1285
                // Offset/end.
1285
                voice->sourceSamplePosition = region->offset;
1286
                voice->sourceSamplePosition = region->offset;
1286
1287
1287
                // Loop.
1288
                // Loop.
1288
                doLoop = (region->loop_mode != TSF_LOOPMODE_NONE && region->loop_start < region->loop_end);
1289
                doLoop = (region->loop_mode != TSF_LOOPMODE_NONE && region->loop_start < region->loop_end);
1289
                voice->loopStart = (doLoop ? region->loop_start : 0);
1290
                voice->loopStart = (doLoop ? region->loop_start : 0);
1290
                voice->loopEnd = (doLoop ? region->loop_end : 0);
1291
                voice->loopEnd = (doLoop ? region->loop_end : 0);
1291
1292
1292
                // Setup envelopes.
1293
                // Setup envelopes.
1293
                tsf_voice_envelope_setup(&voice->ampenv, &region->ampenv, key, midiVelocity, TSF_TRUE, f->outSampleRate);
1294
                tsf_voice_envelope_setup(&voice->ampenv, &region->ampenv, key, midiVelocity, TSF_TRUE, f->outSampleRate);
1294
                tsf_voice_envelope_setup(&voice->modenv, &region->modenv, key, midiVelocity, TSF_FALSE, f->outSampleRate);
1295
                tsf_voice_envelope_setup(&voice->modenv, &region->modenv, key, midiVelocity, TSF_FALSE, f->outSampleRate);
1295
1296
1296
                // Setup lowpass filter.
1297
                // Setup lowpass filter.
-
 
1298
                lowpassFc = (region->initialFilterFc <= 13500 ? tsf_cents2Hertz((float)region->initialFilterFc) / f->outSampleRate : 1.0f);
1297
                filterQDB = region->initialFilterQ / 10.0f;
1299
                lowpassFilterQDB = region->initialFilterQ / 10.0f;
1298
                voice->lowpass.QInv = 1.0 / TSF_POW(10.0, (filterQDB / 20.0));
1300
                voice->lowpass.QInv = 1.0 / TSF_POW(10.0, (lowpassFilterQDB / 20.0));
1299
                voice->lowpass.z1 = voice->lowpass.z2 = 0;
1301
                voice->lowpass.z1 = voice->lowpass.z2 = 0;
1300
                voice->lowpass.active = (region->initialFilterFc <= 13500);
1302
                voice->lowpass.active = (lowpassFc < 0.499f);
1301
                if (voice->lowpass.active) tsf_voice_lowpass_setup(&voice->lowpass, tsf_cents2Hertz((float)region->initialFilterFc) / f->outSampleRate);
1303
                if (voice->lowpass.active) tsf_voice_lowpass_setup(&voice->lowpass, lowpassFc);
1302
1304
1303
                // Setup LFO filters.
1305
                // Setup LFO filters.
1304
                tsf_voice_lfo_setup(&voice->modlfo, region->delayModLFO, region->freqModLFO, f->outSampleRate);
1306
                tsf_voice_lfo_setup(&voice->modlfo, region->delayModLFO, region->freqModLFO, f->outSampleRate);
1305
                tsf_voice_lfo_setup(&voice->viblfo, region->delayVibLFO, region->freqVibLFO, f->outSampleRate);
1307
                tsf_voice_lfo_setup(&voice->viblfo, region->delayVibLFO, region->freqVibLFO, f->outSampleRate);
1306
        }
1308
        }
1307
}
1309
}
1308
1310
1309
TSFDEF int tsf_bank_note_on(tsf* f, int bank, int preset_number, int key, float vel)
1311
TSFDEF int tsf_bank_note_on(tsf* f, int bank, int preset_number, int key, float vel)
1310
{
1312
{
1311
        int preset_index = tsf_get_presetindex(f, bank, preset_number);
1313
        int preset_index = tsf_get_presetindex(f, bank, preset_number);
1312
        if (preset_index == -1) return 0;
1314
        if (preset_index == -1) return 0;
1313
        tsf_note_on(f, preset_index, key, vel);
1315
        tsf_note_on(f, preset_index, key, vel);
1314
        return 1;
1316
        return 1;
1315
}
1317
}
1316
1318
1317
TSFDEF void tsf_note_off(tsf* f, int preset_index, int key)
1319
TSFDEF void tsf_note_off(tsf* f, int preset_index, int key)
1318
{
1320
{
1319
        struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum, *vMatchFirst = TSF_NULL, *vMatchLast = TSF_NULL;
1321
        struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum, *vMatchFirst = TSF_NULL, *vMatchLast = TSF_NULL;
1320
        for (; v != vEnd; v++)
1322
        for (; v != vEnd; v++)
1321
        {
1323
        {
1322
                //Find the first and last entry in the voices list with matching preset, key and look up the smallest play index
1324
                //Find the first and last entry in the voices list with matching preset, key and look up the smallest play index
1323
                if (v->playingPreset != preset_index || v->playingKey != key || v->ampenv.segment >= TSF_SEGMENT_RELEASE) continue;
1325
                if (v->playingPreset != preset_index || v->playingKey != key || v->ampenv.segment >= TSF_SEGMENT_RELEASE) continue;
1324
                else if (!vMatchFirst || v->playIndex < vMatchFirst->playIndex) vMatchFirst = vMatchLast = v;
1326
                else if (!vMatchFirst || v->playIndex < vMatchFirst->playIndex) vMatchFirst = vMatchLast = v;
1325
                else if (v->playIndex == vMatchFirst->playIndex) vMatchLast = v;
1327
                else if (v->playIndex == vMatchFirst->playIndex) vMatchLast = v;
1326
        }
1328
        }
1327
        if (!vMatchFirst) return;
1329
        if (!vMatchFirst) return;
1328
        for (v = vMatchFirst; v <= vMatchLast; v++)
1330
        for (v = vMatchFirst; v <= vMatchLast; v++)
1329
        {
1331
        {
1330
                //Stop all voices with matching preset, key and the smallest play index which was enumerated above
1332
                //Stop all voices with matching preset, key and the smallest play index which was enumerated above
1331
                if (v != vMatchFirst && v != vMatchLast &&
1333
                if (v != vMatchFirst && v != vMatchLast &&
1332
                        (v->playIndex != vMatchFirst->playIndex || v->playingPreset != preset_index || v->playingKey != key || v->ampenv.segment >= TSF_SEGMENT_RELEASE)) continue;
1334
                        (v->playIndex != vMatchFirst->playIndex || v->playingPreset != preset_index || v->playingKey != key || v->ampenv.segment >= TSF_SEGMENT_RELEASE)) continue;
1333
                tsf_voice_end(v, f->outSampleRate);
1335
                tsf_voice_end(v, f->outSampleRate);
1334
        }
1336
        }
1335
}
1337
}
1336
1338
1337
TSFDEF int tsf_bank_note_off(tsf* f, int bank, int preset_number, int key)
1339
TSFDEF int tsf_bank_note_off(tsf* f, int bank, int preset_number, int key)
1338
{
1340
{
1339
        int preset_index = tsf_get_presetindex(f, bank, preset_number);
1341
        int preset_index = tsf_get_presetindex(f, bank, preset_number);
1340
        if (preset_index == -1) return 0;
1342
        if (preset_index == -1) return 0;
1341
        tsf_note_off(f, preset_index, key);
1343
        tsf_note_off(f, preset_index, key);
1342
        return 1;
1344
        return 1;
1343
}
1345
}
1344
1346
1345
TSFDEF void tsf_note_off_all(tsf* f)
1347
TSFDEF void tsf_note_off_all(tsf* f)
1346
{
1348
{
1347
        struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum;
1349
        struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum;
1348
        for (; v != vEnd; v++) if (v->playingPreset != -1 && v->ampenv.segment < TSF_SEGMENT_RELEASE)
1350
        for (; v != vEnd; v++) if (v->playingPreset != -1 && v->ampenv.segment < TSF_SEGMENT_RELEASE)
1349
                tsf_voice_end(v, f->outSampleRate);
1351
                tsf_voice_end(v, f->outSampleRate);
1350
}
1352
}
1351
1353
1352
TSFDEF int tsf_active_voice_count(tsf* f)
1354
TSFDEF int tsf_active_voice_count(tsf* f)
1353
{
1355