Fixes a use-after-free when the MIDI player is deleted before the audio
driver, because the synthesis thread is still actively making callbacks
on the sample timer, which is deleted by the player though.
Enabling the option supresses the default welcome message and
some other text output that normally gets printed to stdout.
It also slightly changes the way the welcome message and argument
errors are handled: in case of an argument error, the welcome message
is never printed.
Previously, sample timers were deleted in fluid_player_stop() which caused a use-after-free when at the same time the sample timers were advanced by the synthesizer thread. This was incorrectly addressed in 5d3f727547 . Deleting sample timers is now done in delete_fluid_player(). A broken application could still crash if it does not respect the order of object creation though. At least now, this issue is properly documented.
In an out of memory situation, fluid_synth_t::voice and fluid_synth_t::channel may not be fully initialized, causing a NULL dereference and heap corruption in delete_fluid_synth().
By default, libinstpatch silently adds all SF2 default modulators to the
converted DLS voices. Since fluidsynth respects the modulators provided
by libinstpatch, those modulators would conflict with the default
modulator list managed by fluidsynth. This is only noticeable, if the
user used fluidsynth's API to manipulate default modulators.
When compiled with compatibility for WinXP (toolset v141_xp), read() may return 0 (EOF) rather than '\n' which led to an early exit of the shell after a single user input.
Vorbis compressed SF3 samples are always loaded individually and stored
in the sample cache in uncompressed form. When dynamic-sample-loading is
not active (the default), then the uncompressed samples did not get
unloaded when unloading the SF3 font.
This fix makes sure that those samples are also freed. For bulk loaded
samples, the sample->data pointer is always the same as the
font->sampledata pointer. For individually loaded samples, the sample->data
pointer always points to a different memory region. So we can use that
information to determine if and when to unload the samples one by one.
Fixes#530Fixes#528
The old buffering code assumes that synth->cur is between 0 and FLUID_BUFSIZE.
However since fluid_synth_process() can render more than one buffer at a time
this isn't always true, and the new code handles other values properly.
Closes#527
This set of changes implements audio drivers for Android, OpenSLES and Oboe. The changes in the original sources are kept minimal so that it should be easily maintained.
When fluidsynth is run as a service using systemd, make sure
the service is considered started only when it is ready to process events.
In order to do so:
- Add an optional runtime dependency to libsystemd to the fluidsynth executable
- Change the systemd service type to "notify"
- Have fluidsynth notify systemd that the service is started after the server is started
- Have fluidsynth notify systemd that the service is stopping after joining the server thread
possibly due to glibc-2.29 commit 424c4f60ed6190e2ea0e72e0873bf3ebcbbf5448
pow is using fused-multiply-add (fma) if available.
That caused the fluidsynth binaries to differ depending on
the build machine's CPU.
This was visible among others in
grep '7.58577575029183[56]e-04' fluidsynth-2.0.3/build/fluid_conv_tables.c
See https://reproducible-builds.org/ for why this is matters.
Closes#512.
-Name of an instrument zone shouldn't prefixed by the preset zone
name.
This is due to the fact that instrument zone are common to all
preset zone. Consequently, an instrument zone cannot identfied
via a preset zone.
-This new change, simply prefixe a zone as this:
instrument zone name prefixed by iz:
preset zone name prefixed by pz:
Normalized value of MIDI sources (before unipolar or bipolar mapping) is always in the range [0..+1], regardless of MIDI event (even for FLUID_MOD_PITCHWHEEL).
Actually some basic modulators check are done at noteon time (in fluid_voice_add_mod()). That means that we know if a modulator (modx) is invalid only when a MIDI noteon is received and only for a preset modx belongs to. This is not appropriate.
This moves the modulator checking at soundfont loading time. Enhancements are:
1) A better verbose modulator integrity check, for any soundfont loaded at appropriate time.
1.1) All modulators are checked (preset zone (local/global), instrument zone (local/global).
1.2.1) Modulators check are enforced to source src1 and src2 (for non-CC and CC sources) (following SF specs (except for CC LSB) ( see comment in fluid_synth_cc_LOCAL()).
Modulators CC sources checking is coherent with the actual behaviour in fluid_synth_cc_LOCAL() in regard of modulation triggering.
1.2.2) Also, identical modulator in the same zone are detected.
1.2.3) Any invalid modulator(sources invalid, or modulator identical) is removed at loading time with a warning message displaying the cause and name of the modulators.
2) This fix a bug in noteon, in the case of identical modulators in global preset zone.
Assuming 2 identical modulator (m1 and m2) in a preset global zone, the actual noteon doesn't check this case (the actual code detect identical modulator in all others zones (instrument (local or global), preset(local)) but not preset global).
3) NoteOn is faster.
3.1)There is no more modulators checks at noteon making this more efficient.
3.2) As there are no identical modulator in the same zone, there is no more identity modulator check (i.e local zone against local zone), (i.e global zone against global zone). This result in a faster code and the bug described in (2) is gone.
4) Modulators sources checking as been added in API functions fluid_synth_add_default_mod() and fluid_voice_add_mod(). Please
- When primary source input (src1) is set to General Controller
'No Controller', output will be forced to 0.0 at synthesis time
(see fluid_mod_get_value()).
That means that the minimum value of the modulator will be always 0.0.
We need to force amount value to 0 to ensure a correct evaluation of the
minimum value later (see fluid_voice_get_lower_boundary_for_attenuation()).
- When secondary source input (src2) is set to General
Controller 'No Controller', output will be forced to +1.0 at synthesis time
(see fluid_mod_get_value()).
That means that this source will behave unipolar only. We need to force the
unipolar flags to ensure the modulator will behave correctly later in
fluid_voice_get_lower_boundary_for_attenuation().
This change removes the warning message if retrieving the soundfont file
modification time fails in the sample cache loader. The warning made sense
while we didn't have mtime support on all platforms, but after switching
to GLibs g_stat, it's no longer needed.
To reduce the number of calls to fluid_get_file_modification_time and also
get rid of a possible race condition, getting the mtime has been moved to
fluid_samplecache_load.
This change also fixes#483 because it removes the bogus warning messages
if a soundfont was loaded from memory by abusing the filename to store a
pointer.
- v variable is renamed min_val for clarity.
- This fix a bug when calculating the possible minimun
value (min_val) of a modulator. min_val should only
be dependant of:
- signs of mapped sources (ie bipolar [-1..+1] or unipolar [0..+1])
- sign of amount.
- absolute value of amount.
If we move UNKN_ID to the bottom of the enum, in the for() cycle inside chunkid() if the value is not found then the "i" variable will be already UNKN_ID.
I tried to check the generated ASM code when WITH_FLOAT macro is defined and when it is undefined. In both cases I noticed that there are some points where the math number are converted from float to double and viceversa. Actually this happens whether the FPU is present or not, perhaps for granting the right precision in digits. I also noticed few points that could be simplified a bit by using integer math, so I also included them.
* Since fluid_voice_get_actual_key() returns an integer value, the value 60 could be subtracted directly as integer, the code generated looks a bit better.
* FLUID_NOISE_FLOOR needs to be cast to fluid_real_t to generate a bit more efficient code.
* DC_OFFSET needs a cast to fluid_real_t to generate a bit more efficient code.
* "last_fres" and "output_rate" are already fluid_real_t, so they do not need type cast.
* "chan_add", "par1_add" and "par2_add" are integer types, so they can be added without FPU. "chan_mul", "par1_mul" and "par2_mul" are already fluid_real_t, so they do not need type cast. Instead, the constant 0.5 needs cast to fluid_real_t to be more efficient.
Libreadline is already used into fluid_istream_readline().
In my opinion, there is no need to have this duplicated code, so I would suggest to move the call to add_history() into fluid_sys.h
Closes#460.
Since 'data' is an integer value clipped between +/-8192 and 'nrpn_scale' is a char value, this calculation could be done with integers and then return the fluid_real_t value.
Addresses #455.
Instead of saving the name of the driver, it would be worth to save to pointer to the selected definition instead.
In this way, the function for deleting the driver does not need to search its name by parsing all the list, but it just needs to call the pointer into the saved definition (less code). This fix can be applied to MIDI drivers too.
I also moved the FLUID_FREE(allnames) inside the "if(allnames != NULL)" block, nothing bad should happen even by keeping that instruction outside, but actually there is no need to call the free if allnames is NULL.
In my opionion, it should be possible to simplify the code by installing the drivers with a for() cycle instead of doing tons of #ifdef...#endif.
The size of the binary code is basically the same as before, but the source lines are much less. I think that it could be done also for MIDI input drivers.
Actually, the function roundi() already returns an "int" type value, so in my opinion there is no need to use a floating point value for saturating the values in the range -32768/+32767. The generated assembly code looks more efficient after that.
- fluid_dsound_audio_run() and fluid_win32_error() are now static functions.
- WAVEFORMATEX is not required by DirectSound during the playback. We do not need it anymore after calling ::SetFormat(), so allocating this structure dynamically inside driver structure is useless.
- Implemented support for float sample type.
- Uses an event object for handling the end of thread, it allows to combine the quit event with the later wait in milliseconds in a single block.
- Calculates the amount of milliseconds to sleep rather than sleeping always for one millisecond.
- Fix an error into a FLUID_LOG() call.
- Fix handle leak of the thread, now it is correctly closed with CloseHandle().
- ExitThread() is a nonsense in that position, since the thread is already exiting.
- Fix error when compiling with WSDK 8.1, by defining NOBITMAP, in case NOGDI macro added somewhere
Since v 2.1 ,as recommended by soundfont 2.01/2.4 spec
ATTACK section is convex. So, when skiping from a
section above ATTACK to ATTACK, it is necessary to
correct current modulation envelope value to get
seamless transition.
adds a new setting "synth.effects-groups" that allows multiple effects
units, in order to render effects of each midi channel to a separate
audio channel
This reverts commit 29d1947ccc. Reading the spec again, the final gain amp should actually applied for the whole voice, not just single buffers (cf. sect. 9.1.8 Figure 2). Thus rvoice_mixer is not the correct place to implement this. It should instead be done in fluid_rvoice_calc_amp().
reopens#319closes#399
Changing the number of rendering threads on-the-fly is not considered to be a usecase. In fact it will cause glitchy audio if doing so while synthesizing because all rendering threads are killed and their mixdown buffers are reallocated. This change should fix glitchy audio that might occur at the beginning of synthesization, as the rvoice_event for thread allocation may be dispatched (too) late.
Remove fluid_channel_get_interp_method(), fluid_channel_set_interp_method(), fluid_channel_get_preset() and fluid_channel_get_num() as they are already defined as macros.