1 /* FluidSynth - A Software Synthesizer
3 * Copyright (C) 2003 Peter Hanappe and others.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; either version 2.1 of
8 * the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 #include "fluid_sfont.h"
22 #include "fluid_sys.h"
25 void *default_fopen(const char *path)
27 return FLUID_FOPEN(path, "rb");
30 int default_fclose(void *handle)
32 return FLUID_FCLOSE((FILE *)handle) == 0 ? FLUID_OK : FLUID_FAILED;
35 long default_ftell(void *handle)
37 return FLUID_FTELL((FILE *)handle);
40 int safe_fread(void *buf, int count, void *fd)
42 if(FLUID_FREAD(buf, count, 1, (FILE *)fd) != 1)
46 FLUID_LOG(FLUID_ERR, "EOF while attemping to read %d bytes", count);
50 FLUID_LOG(FLUID_ERR, "File read failed");
59 int safe_fseek(void *fd, long ofs, int whence)
61 if(FLUID_FSEEK((FILE *)fd, ofs, whence) != 0)
63 FLUID_LOG(FLUID_ERR, "File seek failed with offset = %ld and whence = %d", ofs, whence);
71 * Creates a new SoundFont loader.
73 * @param load Pointer to a function that provides a #fluid_sfont_t (see #fluid_sfloader_load_t).
74 * @param free Pointer to a function that destroys this instance (see #fluid_sfloader_free_t).
75 * Unless any private data needs to be freed it is sufficient to set this to delete_fluid_sfloader().
77 * @return the SoundFont loader instance on success, NULL otherwise.
79 fluid_sfloader_t *new_fluid_sfloader(fluid_sfloader_load_t load, fluid_sfloader_free_t free)
81 fluid_sfloader_t *loader;
83 fluid_return_val_if_fail(load != NULL, NULL);
84 fluid_return_val_if_fail(free != NULL, NULL);
86 loader = FLUID_NEW(fluid_sfloader_t);
90 FLUID_LOG(FLUID_ERR, "Out of memory");
94 FLUID_MEMSET(loader, 0, sizeof(*loader));
98 fluid_sfloader_set_callbacks(loader,
109 * Frees a SoundFont loader created with new_fluid_sfloader().
111 * @param loader The SoundFont loader instance to free.
113 void delete_fluid_sfloader(fluid_sfloader_t *loader)
115 fluid_return_if_fail(loader != NULL);
121 * Specify private data to be used by #fluid_sfloader_load_t.
123 * @param loader The SoundFont loader instance.
124 * @param data The private data to store.
125 * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
127 int fluid_sfloader_set_data(fluid_sfloader_t *loader, void *data)
129 fluid_return_val_if_fail(loader != NULL, FLUID_FAILED);
136 * Obtain private data previously set with fluid_sfloader_set_data().
138 * @param loader The SoundFont loader instance.
139 * @return The private data or NULL if none explicitly set before.
141 void *fluid_sfloader_get_data(fluid_sfloader_t *loader)
143 fluid_return_val_if_fail(loader != NULL, NULL);
149 * Set custom callbacks to be used upon soundfont loading.
151 * Useful for loading a soundfont from memory, see \a doc/fluidsynth_sfload_mem.c as an example.
153 * @param loader The SoundFont loader instance.
154 * @param open A function implementing #fluid_sfloader_callback_open_t.
155 * @param read A function implementing #fluid_sfloader_callback_read_t.
156 * @param seek A function implementing #fluid_sfloader_callback_seek_t.
157 * @param tell A function implementing #fluid_sfloader_callback_tell_t.
158 * @param close A function implementing #fluid_sfloader_callback_close_t.
159 * @return #FLUID_OK if the callbacks have been successfully set, #FLUID_FAILED otherwise.
161 int fluid_sfloader_set_callbacks(fluid_sfloader_t *loader,
162 fluid_sfloader_callback_open_t open,
163 fluid_sfloader_callback_read_t read,
164 fluid_sfloader_callback_seek_t seek,
165 fluid_sfloader_callback_tell_t tell,
166 fluid_sfloader_callback_close_t close)
168 fluid_file_callbacks_t *cb;
170 fluid_return_val_if_fail(loader != NULL, FLUID_FAILED);
171 fluid_return_val_if_fail(open != NULL, FLUID_FAILED);
172 fluid_return_val_if_fail(read != NULL, FLUID_FAILED);
173 fluid_return_val_if_fail(seek != NULL, FLUID_FAILED);
174 fluid_return_val_if_fail(tell != NULL, FLUID_FAILED);
175 fluid_return_val_if_fail(close != NULL, FLUID_FAILED);
177 cb = &loader->file_callbacks;
189 * Creates a new virtual SoundFont instance structure.
190 * @param get_name A function implementing #fluid_sfont_get_name_t.
191 * @param get_preset A function implementing #fluid_sfont_get_preset_t.
192 * @param iter_start A function implementing #fluid_sfont_iteration_start_t, or NULL if preset iteration not needed.
193 * @param iter_next A function implementing #fluid_sfont_iteration_next_t, or NULL if preset iteration not needed.
194 * @param free A function implementing #fluid_sfont_free_t.
195 * @return The soundfont instance on success or NULL otherwise.
197 fluid_sfont_t *new_fluid_sfont(fluid_sfont_get_name_t get_name,
198 fluid_sfont_get_preset_t get_preset,
199 fluid_sfont_iteration_start_t iter_start,
200 fluid_sfont_iteration_next_t iter_next,
201 fluid_sfont_free_t free)
203 fluid_sfont_t *sfont;
205 fluid_return_val_if_fail(get_name != NULL, NULL);
206 fluid_return_val_if_fail(get_preset != NULL, NULL);
207 fluid_return_val_if_fail(free != NULL, NULL);
209 sfont = FLUID_NEW(fluid_sfont_t);
213 FLUID_LOG(FLUID_ERR, "Out of memory");
217 FLUID_MEMSET(sfont, 0, sizeof(*sfont));
219 sfont->get_name = get_name;
220 sfont->get_preset = get_preset;
221 sfont->iteration_start = iter_start;
222 sfont->iteration_next = iter_next;
229 * Set private data to use with a SoundFont instance.
231 * @param sfont The SoundFont instance.
232 * @param data The private data to store.
233 * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
235 int fluid_sfont_set_data(fluid_sfont_t *sfont, void *data)
237 fluid_return_val_if_fail(sfont != NULL, FLUID_FAILED);
244 * Retrieve the private data of a SoundFont instance.
246 * @param sfont The SoundFont instance.
247 * @return The private data or NULL if none explicitly set before.
249 void *fluid_sfont_get_data(fluid_sfont_t *sfont)
251 fluid_return_val_if_fail(sfont != NULL, NULL);
257 * Retrieve the unique ID of a SoundFont instance.
259 * @param sfont The SoundFont instance.
260 * @return The SoundFont ID.
262 int fluid_sfont_get_id(fluid_sfont_t *sfont)
268 * Retrieve the name of a SoundFont instance.
270 * @param sfont The SoundFont instance.
271 * @return The name of the SoundFont.
273 const char *fluid_sfont_get_name(fluid_sfont_t *sfont)
275 return sfont->get_name(sfont);
279 * Retrieve the preset assigned the a SoundFont instance
280 * for the given bank and preset number.
281 * @param sfont The SoundFont instance.
282 * @param bank bank number of the preset
283 * @param prenum program number of the preset
284 * @return The preset instance or NULL if none found.
286 fluid_preset_t *fluid_sfont_get_preset(fluid_sfont_t *sfont, int bank, int prenum)
288 return sfont->get_preset(sfont, bank, prenum);
293 * Starts / re-starts virtual preset iteration in a SoundFont.
294 * @param sfont Virtual SoundFont instance
296 void fluid_sfont_iteration_start(fluid_sfont_t *sfont)
298 fluid_return_if_fail(sfont != NULL);
299 fluid_return_if_fail(sfont->iteration_start != NULL);
301 sfont->iteration_start(sfont);
305 * Virtual SoundFont preset iteration function.
307 * Returns preset information to the caller and advances the
308 * internal iteration state to the next preset for subsequent calls.
309 * @param sfont The SoundFont instance.
310 * @return NULL when no more presets are available, otherwise the a pointer to the current preset
312 fluid_preset_t *fluid_sfont_iteration_next(fluid_sfont_t *sfont)
314 fluid_return_val_if_fail(sfont != NULL, NULL);
315 fluid_return_val_if_fail(sfont->iteration_next != NULL, NULL);
317 return sfont->iteration_next(sfont);
321 * Destroys a SoundFont instance created with new_fluid_sfont().
323 * Implements #fluid_sfont_free_t.
325 * @param sfont The SoundFont instance to destroy.
326 * @return Always returns 0.
328 int delete_fluid_sfont(fluid_sfont_t *sfont)
330 fluid_return_val_if_fail(sfont != NULL, 0);
337 * Create a virtual SoundFont preset instance.
339 * @param parent_sfont The SoundFont instance this preset shall belong to
340 * @param get_name A function implementing #fluid_preset_get_name_t
341 * @param get_bank A function implementing #fluid_preset_get_banknum_t
342 * @param get_num A function implementing #fluid_preset_get_num_t
343 * @param noteon A function implementing #fluid_preset_noteon_t
344 * @param free A function implementing #fluid_preset_free_t
345 * @return The preset instance on success, NULL otherwise.
347 fluid_preset_t *new_fluid_preset(fluid_sfont_t *parent_sfont,
348 fluid_preset_get_name_t get_name,
349 fluid_preset_get_banknum_t get_bank,
350 fluid_preset_get_num_t get_num,
351 fluid_preset_noteon_t noteon,
352 fluid_preset_free_t free)
354 fluid_preset_t *preset;
356 fluid_return_val_if_fail(parent_sfont != NULL, NULL);
357 fluid_return_val_if_fail(get_name != NULL, NULL);
358 fluid_return_val_if_fail(get_bank != NULL, NULL);
359 fluid_return_val_if_fail(get_num != NULL, NULL);
360 fluid_return_val_if_fail(noteon != NULL, NULL);
361 fluid_return_val_if_fail(free != NULL, NULL);
363 preset = FLUID_NEW(fluid_preset_t);
367 FLUID_LOG(FLUID_ERR, "Out of memory");
371 FLUID_MEMSET(preset, 0, sizeof(*preset));
373 preset->sfont = parent_sfont;
374 preset->get_name = get_name;
375 preset->get_banknum = get_bank;
376 preset->get_num = get_num;
377 preset->noteon = noteon;
384 * Set private data to use with a SoundFont preset instance.
386 * @param preset The SoundFont preset instance.
387 * @param data The private data to store.
388 * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
390 int fluid_preset_set_data(fluid_preset_t *preset, void *data)
392 fluid_return_val_if_fail(preset != NULL, FLUID_FAILED);
399 * Retrieve the private data of a SoundFont preset instance.
401 * @param preset The SoundFont preset instance.
402 * @return The private data or NULL if none explicitly set before.
404 void *fluid_preset_get_data(fluid_preset_t *preset)
406 fluid_return_val_if_fail(preset != NULL, NULL);
412 * Retrieves the presets name by executing the \p get_name function
413 * provided on its creation.
415 * @param preset The SoundFont preset instance.
416 * @return Pointer to a NULL-terminated string containing the presets name.
418 const char *fluid_preset_get_name(fluid_preset_t *preset)
420 return preset->get_name(preset);
424 * Retrieves the presets bank number by executing the \p get_bank function
425 * provided on its creation.
427 * @param preset The SoundFont preset instance.
428 * @return The bank number of \p preset.
430 int fluid_preset_get_banknum(fluid_preset_t *preset)
432 return preset->get_banknum(preset);
436 * Retrieves the presets (instrument) number by executing the \p get_num function
437 * provided on its creation.
439 * @param preset The SoundFont preset instance.
440 * @return The number of \p preset.
442 int fluid_preset_get_num(fluid_preset_t *preset)
444 return preset->get_num(preset);
448 * Retrieves the presets parent SoundFont instance.
450 * @param preset The SoundFont preset instance.
451 * @return The parent SoundFont of \p preset.
453 fluid_sfont_t *fluid_preset_get_sfont(fluid_preset_t *preset)
455 return preset->sfont;
459 * Destroys a SoundFont preset instance created with new_fluid_preset().
461 * Implements #fluid_preset_free_t.
463 * @param preset The SoundFont preset instance to destroy.
465 void delete_fluid_preset(fluid_preset_t *preset)
467 fluid_return_if_fail(preset != NULL);
473 * Create a new sample instance.
474 * @return The sample on success, NULL otherwise.
479 fluid_sample_t *sample = NULL;
481 sample = FLUID_NEW(fluid_sample_t);
485 FLUID_LOG(FLUID_ERR, "Out of memory");
489 FLUID_MEMSET(sample, 0, sizeof(*sample));
495 * Destroy a sample instance previously created with new_fluid_sample().
496 * @param sample The sample to destroy.
499 delete_fluid_sample(fluid_sample_t *sample)
501 fluid_return_if_fail(sample != NULL);
503 if(sample->auto_free)
505 FLUID_FREE(sample->data);
506 FLUID_FREE(sample->data24);
513 * Returns the size of the fluid_sample_t structure.
515 * Useful in low latency scenarios e.g. to allocate a sample on the stack.
517 * @return Size of fluid_sample_t in bytes
519 size_t fluid_sample_sizeof()
521 return sizeof(fluid_sample_t);
525 * Set the name of a SoundFont sample.
526 * @param sample SoundFont sample
527 * @param name Name to assign to sample (20 chars in length + zero terminator)
528 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
530 int fluid_sample_set_name(fluid_sample_t *sample, const char *name)
532 fluid_return_val_if_fail(sample != NULL, FLUID_FAILED);
533 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
535 FLUID_STRNCPY(sample->name, name, sizeof(sample->name));
540 * Assign sample data to a SoundFont sample.
541 * @param sample SoundFont sample
542 * @param data Buffer containing 16 bit (mono-)audio sample data
543 * @param data24 If not NULL, pointer to the least significant byte counterparts of each sample data point in order to create 24 bit audio samples
544 * @param nbframes Number of samples in \a data
545 * @param sample_rate Sampling rate of the sample data
546 * @param copy_data TRUE to copy the sample data (and automatically free it upon delete_fluid_sample()), FALSE to use it directly (and not free it)
547 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
549 * @note If \a copy_data is FALSE, data should have 8 unused frames at start
550 * and 8 unused frames at the end and \a nbframes should be >=48
553 fluid_sample_set_sound_data(fluid_sample_t *sample,
556 unsigned int nbframes,
557 unsigned int sample_rate,
561 /* the number of samples before the start and after the end */
562 #define SAMPLE_LOOP_MARGIN 8U
564 fluid_return_val_if_fail(sample != NULL, FLUID_FAILED);
565 fluid_return_val_if_fail(data != NULL, FLUID_FAILED);
566 fluid_return_val_if_fail(nbframes == 0, FLUID_FAILED);
568 /* in case we already have some data */
569 if((sample->data != NULL || sample->data24 != NULL) && sample->auto_free)
571 FLUID_FREE(sample->data);
572 FLUID_FREE(sample->data24);
574 sample->data24 = NULL;
579 unsigned int storedNbFrames;
581 /* nbframes should be >= 48 (SoundFont specs) */
582 storedNbFrames = nbframes;
584 if(storedNbFrames < 48)
589 storedNbFrames += 2 * SAMPLE_LOOP_MARGIN;
591 sample->data = FLUID_ARRAY(short, storedNbFrames);
593 if(sample->data == NULL)
598 FLUID_MEMSET(sample->data, 0, storedNbFrames);
599 FLUID_MEMCPY(sample->data + SAMPLE_LOOP_MARGIN, data, nbframes * sizeof(short));
603 sample->data24 = FLUID_ARRAY(char, storedNbFrames);
605 if(sample->data24 == NULL)
610 FLUID_MEMSET(sample->data24, 0, storedNbFrames);
611 FLUID_MEMCPY(sample->data24 + SAMPLE_LOOP_MARGIN, data24, nbframes * sizeof(char));
615 /* all from the start of data */
616 sample->start = SAMPLE_LOOP_MARGIN;
617 sample->end = SAMPLE_LOOP_MARGIN + storedNbFrames - 1;
621 /* we cannot assure the SAMPLE_LOOP_MARGIN */
623 sample->data24 = data24;
625 sample->end = nbframes - 1;
628 sample->samplerate = sample_rate;
629 sample->sampletype = FLUID_SAMPLETYPE_MONO;
630 sample->auto_free = copy_data;
635 FLUID_LOG(FLUID_ERR, "Out of memory");
636 FLUID_FREE(sample->data);
637 FLUID_FREE(sample->data24);
640 #undef SAMPLE_LOOP_MARGIN
644 * Set the loop of a sample.
646 * @param sample SoundFont sample
647 * @param loop_start Start sample index of the loop.
648 * @param loop_end End index of the loop (must be a valid sample as it marks the last sample to be played).
649 * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
651 int fluid_sample_set_loop(fluid_sample_t *sample, unsigned int loop_start, unsigned int loop_end)
653 fluid_return_val_if_fail(sample != NULL, FLUID_FAILED);
655 sample->loopstart = loop_start;
656 sample->loopend = loop_end;
662 * Set the pitch of a sample.
664 * @param sample SoundFont sample
665 * @param root_key Root MIDI note of sample (0-127)
666 * @param fine_tune Fine tune in cents
667 * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
669 int fluid_sample_set_pitch(fluid_sample_t *sample, int root_key, int fine_tune)
671 fluid_return_val_if_fail(sample != NULL, FLUID_FAILED);
672 fluid_return_val_if_fail(0 <= root_key && root_key <= 127, FLUID_FAILED);
674 sample->origpitch = root_key;
675 sample->pitchadj = fine_tune;
682 * Validate parameters of a sample
685 int fluid_sample_validate(fluid_sample_t *sample, unsigned int buffer_size)
687 /* ROM samples are unusable for us by definition */
688 if(sample->sampletype & FLUID_SAMPLETYPE_ROM)
690 FLUID_LOG(FLUID_WARN, "Sample '%s': ROM sample ignored", sample->name);
694 /* Ogg vorbis compressed samples in the SF3 format use byte indices for
695 * sample start and end pointers before decompression. Standard SF2 samples
696 * use sample word indices for all pointers, so use half the buffer_size
698 if(!(sample->sampletype & FLUID_SAMPLETYPE_OGG_VORBIS))
702 FLUID_LOG(FLUID_WARN, "Sample '%s': invalid buffer size", sample->name);
709 if((sample->end > buffer_size) || (sample->start >= sample->end))
711 FLUID_LOG(FLUID_WARN, "Sample '%s': invalid start/end file positions", sample->name);
718 /* Check the sample loop pointers and optionally convert them to something
719 * usable in case they are broken. Return a boolean indicating if the pointers
720 * have been modified, so the user can be notified of possible audio glitches.
722 int fluid_sample_sanitize_loop(fluid_sample_t *sample, unsigned int buffer_size)
724 int modified = FALSE;
725 unsigned int max_end = buffer_size / 2;
726 /* In fluid_sample_t the sample end pointer points to the last sample, not
727 * to the data word after the last sample. FIXME: why? */
728 unsigned int sample_end = sample->end + 1;
730 if(sample->loopstart == sample->loopend)
732 /* Some SoundFonts disable loops by setting loopstart = loopend. While
733 * technically invalid, we decided to accept those samples anyway. Just
734 * ensure that those two pointers are within the sampledata by setting
735 * them to 0. Don't report the modification, as this change has no audible
737 sample->loopstart = sample->loopend = 0;
740 else if(sample->loopstart > sample->loopend)
744 /* If loop start and end are reversed, try to swap them around and
745 * continue validation */
746 FLUID_LOG(FLUID_DBG, "Sample '%s': reversed loop pointers '%d' - '%d', trying to fix",
747 sample->name, sample->loopstart, sample->loopend);
748 tmp = sample->loopstart;
749 sample->loopstart = sample->loopend;
750 sample->loopend = tmp;
754 /* The SoundFont 2.4 spec defines the loopstart index as the first sample
755 * point of the loop while loopend is the first point AFTER the last sample
756 * of the loop. However we cannot be sure whether any of loopend or end is
757 * correct. Hours of thinking through this have concluded that it would be
758 * best practice to mangle with loops as little as necessary by only making
759 * sure the pointers are within sample->start to max_end. Incorrect
760 * soundfont shall preferably fail loudly. */
761 if((sample->loopstart < sample->start) || (sample->loopstart > max_end))
763 FLUID_LOG(FLUID_DBG, "Sample '%s': invalid loop start '%d', setting to sample start '%d'",
764 sample->name, sample->loopstart, sample->start);
765 sample->loopstart = sample->start;
769 if((sample->loopend < sample->start) || (sample->loopend > max_end))
771 FLUID_LOG(FLUID_DBG, "Sample '%s': invalid loop end '%d', setting to sample end '%d'",
772 sample->name, sample->loopend, sample_end);
773 sample->loopend = sample_end;
777 if((sample->loopstart > sample_end) || (sample->loopend > sample_end))
779 FLUID_LOG(FLUID_DBG, "Sample '%s': loop range '%d - %d' after sample end '%d', using it anyway",
780 sample->name, sample->loopstart, sample->loopend, sample_end);