summaryrefslogtreecommitdiff
path: root/libs/fluidsynth/fluidsynth/sfont.h
blob: 30aebfd1261c16d6e3c3131371093f47b4f18954 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/* FluidSynth - A Software Synthesizer
 *
 * Copyright (C) 2003  Peter Hanappe and others.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public License
 * as published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *  
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 */

#ifndef _FLUIDSYNTH_SFONT_H
#define _FLUIDSYNTH_SFONT_H

#ifdef __cplusplus
extern "C" {
#endif


/**
 * @file sfont.h
 * @brief SoundFont plugins
 *
 * It is possible to add new SoundFont loaders to the
 * synthesizer. The API uses a couple of "interfaces" (structures
 * with callback functions): #fluid_sfloader_t, #fluid_sfont_t, and
 * #fluid_preset_t.  This API allows for virtual SoundFont files to be loaded
 * and synthesized, which may not actually be SoundFont files, as long as they
 * can be represented by the SoundFont synthesis model.
 *
 * To add a new SoundFont loader to the synthesizer, call
 * fluid_synth_add_sfloader() and pass a pointer to an
 * fluid_sfloader_t structure. The important callback function in
 * this structure is "load", which should try to load a file and
 * returns a #fluid_sfont_t structure, or NULL if it fails.
 *
 * The #fluid_sfont_t structure contains a callback to obtain the
 * name of the SoundFont. It contains two functions to iterate
 * though the contained presets, and one function to obtain a
 * preset corresponding to a bank and preset number. This
 * function should return a #fluid_preset_t structure.
 *
 * The #fluid_preset_t structure contains some functions to obtain
 * information from the preset (name, bank, number). The most
 * important callback is the noteon function. The noteon function
 * should call fluid_synth_alloc_voice() for every sample that has
 * to be played. fluid_synth_alloc_voice() expects a pointer to a
 * #fluid_sample_t structure and returns a pointer to the opaque
 * #fluid_voice_t structure. To set or increment the values of a
 * generator, use fluid_voice_gen_set() or fluid_voice_gen_incr(). When you are
 * finished initializing the voice call fluid_voice_start() to
 * start playing the synthesis voice.
 */

/**
 * Some notification enums for presets and samples.
 */
enum {
  FLUID_PRESET_SELECTED,                /**< Preset selected notify */
  FLUID_PRESET_UNSELECTED,              /**< Preset unselected notify */
  FLUID_SAMPLE_DONE                     /**< Sample no longer needed notify */
};


/**
 * SoundFont loader structure.
 */
struct _fluid_sfloader_t {
  void* data;           /**< User defined data pointer */

  /**
   * The free method should free the memory allocated for the loader in
   * addition to any private data.
   * @param loader SoundFont loader
   * @return Should return 0 if no error occured, non-zero otherwise
   */
  int (*free)(fluid_sfloader_t* loader);

  /**
   * Method to load an instrument file (does not actually need to be a real file name,
   * could be another type of string identifier that the \a loader understands).
   * @param loader SoundFont loader
   * @param filename File name or other string identifier
   * @return The loaded instrument file (SoundFont) or NULL if an error occured.
   */
  fluid_sfont_t* (*load)(fluid_sfloader_t* loader, const char* filename);
};

/**
 * Virtual SoundFont instance structure.
 */
struct _fluid_sfont_t {
  void* data;           /**< User defined data */
  unsigned int id;      /**< SoundFont ID */

  /**
   * Method to free a virtual SoundFont bank.
   * @param sfont Virtual SoundFont to free.
   * @return Should return 0 when it was able to free all resources or non-zero
   *   if some of the samples could not be freed because they are still in use,
   *   in which case the free will be tried again later, until success.
   */
  int (*free)(fluid_sfont_t* sfont);

  /**
   * Method to return the name of a virtual SoundFont.
   * @param sfont Virtual SoundFont
   * @return The name of the virtual SoundFont.
   */
  char* (*get_name)(fluid_sfont_t* sfont);

  /**
   * Get a virtual SoundFont preset by bank and program numbers.
   * @param sfont Virtual SoundFont
   * @param bank MIDI bank number (0-16384)
   * @param prenum MIDI preset number (0-127)
   * @return Should return an allocated virtual preset or NULL if it could not
   *   be found.
   */
  fluid_preset_t* (*get_preset)(fluid_sfont_t* sfont, unsigned int bank, unsigned int prenum);

  /**
   * Start virtual SoundFont preset iteration method.
   * @param sfont Virtual SoundFont
   *
   * Starts/re-starts virtual preset iteration in a SoundFont.
   */
  void (*iteration_start)(fluid_sfont_t* sfont);

  /**
   * Virtual SoundFont preset iteration function.
   * @param sfont Virtual SoundFont
   * @param preset Caller supplied preset to fill in with current preset information
   * @return 0 when no more presets are available, 1 otherwise
   *
   * Should store preset information to the caller supplied \a preset structure
   * and advance the internal iteration state to the next preset for subsequent
   * calls.
   */
  int (*iteration_next)(fluid_sfont_t* sfont, fluid_preset_t* preset);
};

#define fluid_sfont_get_id(_sf) ((_sf)->id)

/**
 * Virtual SoundFont preset.
 */
struct _fluid_preset_t {
  void* data;                                   /**< User supplied data */
  fluid_sfont_t* sfont;                         /**< Parent virtual SoundFont */

  /**
   * Method to free a virtual SoundFont preset.
   * @param preset Virtual SoundFont preset
   * @return Should return 0
   */
  int (*free)(fluid_preset_t* preset);

  /**
   * Method to get a virtual SoundFont preset name.
   * @param preset Virtual SoundFont preset
   * @return Should return the name of the preset.  The returned string must be
   *   valid for the duration of the virtual preset (or the duration of the
   *   SoundFont, in the case of preset iteration).
   */
  char* (*get_name)(fluid_preset_t* preset);

  /**
   * Method to get a virtual SoundFont preset MIDI bank number.
   * @param preset Virtual SoundFont preset
   * @param return The bank number of the preset
   */
  int (*get_banknum)(fluid_preset_t* preset);

  /**
   * Method to get a virtual SoundFont preset MIDI program number.
   * @param preset Virtual SoundFont preset
   * @param return The program number of the preset
   */
  int (*get_num)(fluid_preset_t* preset);

  /**
   * Method to handle a noteon event (synthesize the instrument).
   * @param preset Virtual SoundFont preset
   * @param synth Synthesizer instance
   * @param chan MIDI channel number of the note on event
   * @param key MIDI note number (0-127)
   * @param vel MIDI velocity (0-127)
   * @return #FLUID_OK on success (0) or #FLUID_FAILED (-1) otherwise
   *
   * This method may be called from within synthesis context and therefore
   * should be as efficient as possible and not perform any operations considered
   * bad for realtime audio output (memory allocations and other OS calls).
   *
   * Call fluid_synth_alloc_voice() for every sample that has
   * to be played. fluid_synth_alloc_voice() expects a pointer to a
   * #fluid_sample_t structure and returns a pointer to the opaque
   * #fluid_voice_t structure. To set or increment the values of a
   * generator, use fluid_voice_gen_set() or fluid_voice_gen_incr(). When you are
   * finished initializing the voice call fluid_voice_start() to
   * start playing the synthesis voice.  Starting with FluidSynth 1.1.0 all voices
   * created will be started at the same time.
   */
  int (*noteon)(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel);

  /**
   * Virtual SoundFont preset notify method.
   * @param preset Virtual SoundFont preset
   * @param reason #FLUID_PRESET_SELECTED or #FLUID_PRESET_UNSELECTED
   * @param chan MIDI channel number
   * @return Should return #FLUID_OK
   *
   * Implement this optional method if the preset needs to be notified about
   * preset select and unselect events.
   *
   * This method may be called from within synthesis context and therefore
   * should be as efficient as possible and not perform any operations considered
   * bad for realtime audio output (memory allocations and other OS calls).
   */
  int (*notify)(fluid_preset_t* preset, int reason, int chan);
};

/**
 * Virtual SoundFont sample.
 */
struct _fluid_sample_t
{
  char name[21];                /**< Sample name */
  unsigned int start;           /**< Start index */
  unsigned int end;	        /**< End index, index of last valid sample point (contrary to SF spec) */
  unsigned int loopstart;       /**< Loop start index */
  unsigned int loopend;         /**< Loop end index, first point following the loop (superimposed on loopstart) */
  unsigned int samplerate;      /**< Sample rate */
  int origpitch;                /**< Original pitch (MIDI note number, 0-127) */
  int pitchadj;                 /**< Fine pitch adjustment (+/- 99 cents) */
  int sampletype;               /**< Values: #FLUID_SAMPLETYPE_MONO, FLUID_SAMPLETYPE_RIGHT, FLUID_SAMPLETYPE_LEFT, FLUID_SAMPLETYPE_ROM */
  int valid;                    /**< Should be TRUE if sample data is valid, FALSE otherwise (in which case it will not be synthesized) */
  short* data;                  /**< Pointer to the sample's data */

  int amplitude_that_reaches_noise_floor_is_valid;      /**< Indicates if \a amplitude_that_reaches_noise_floor is valid (TRUE), set to FALSE initially to calculate. */
  double amplitude_that_reaches_noise_floor;            /**< The amplitude at which the sample's loop will be below the noise floor.  For voice off optimization, calculated automatically. */

  unsigned int refcount;        /**< Count of voices using this sample (use #fluid_sample_refcount to access this field) */

  /**
   * Implement this function to receive notification when sample is no longer used.
   * @param sample Virtual SoundFont sample
   * @param reason #FLUID_SAMPLE_DONE only currently
   * @return Should return #FLUID_OK
   */
  int (*notify)(fluid_sample_t* sample, int reason);

  void* userdata;       /**< User defined data */
};


#define fluid_sample_refcount(_sample) ((_sample)->refcount)    /**< Get the reference count of a sample.  Should only be called from within synthesis context (noteon method for example) */


#define FLUID_SAMPLETYPE_MONO	1       /**< Flag for #fluid_sample_t \a sampletype field for mono samples */
#define FLUID_SAMPLETYPE_RIGHT	2       /**< Flag for #fluid_sample_t \a sampletype field for right samples of a stereo pair */
#define FLUID_SAMPLETYPE_LEFT	4       /**< Flag for #fluid_sample_t \a sampletype field for left samples of a stereo pair */
#define FLUID_SAMPLETYPE_LINKED	8       /**< Flag for #fluid_sample_t \a sampletype field, not used currently */
#define FLUID_SAMPLETYPE_ROM	0x8000  /**< Flag for #fluid_sample_t \a sampletype field, ROM sample, causes sample to be ignored */



#ifdef __cplusplus
}
#endif

#endif /* _FLUIDSYNTH_SFONT_H */