FluidSynth / fluidsynth

Software synthesizer based on the SoundFont 2 specifications
https://www.fluidsynth.org
GNU Lesser General Public License v2.1
1.89k stars 259 forks source link

MIDI file player ends before all notes have been played. #24

Open derselbst opened 14 years ago

derselbst commented 14 years ago

Originally created by: David Henningsson

Two problems must be addressed:

Reference:
http://lists.gnu.org/archive/html/fluid-dev/2009-03/msg00040.html

Reported by: *anonymous

Original Ticket: fluidsynth/tickets/24

derselbst commented 14 years ago

Original comment author: diwic

Here are my thoughts about this issue.

For problem 1: I'm a little hesitant about this part. I think it's more important that we don't lose a predictable endpoint / song length. That is important when a song loops. It could be that somebody has written a beat that he wants to repeat over and over again and practice to it, then he don't want extra delays every time the beat starts over. Or it could be that FluidSynth is used for game background music, where the music should loop seamlessly.

For problem 2: This should be pretty straight forward to implement. I suggest a new driver public API function fluid_audio_stop(boolean immediately) is added. If immediately is false, it waits for all buffers to be played before it returns. For the ALSA driver, that is the same as calling snd_pcm_drain. I could do it for ALSA, but I don't know how to implement/test it in the other audio drivers.

Original comment by: elementgreen

derselbst commented 14 years ago

In regards to snd_pcm_drain with ALSA and such. That seems more like a function of the audio driver, in that it should flush out any data when the driver is closed. I think problem 2 is actually not directly related to that. The required functionality can probably be summarized as the following:

  1. Ability to determine when a MIDI song ends
  2. Ability to determine when audio playback is silent
  3. Audio drivers should flush out already sent audio when closed

When playing many MIDI songs back to back, perhaps the player could add a configurable amount of delay between the songs.

Original comment by: elementgreen

derselbst commented 13 years ago

I accidentally duplicated this bug in ticket #101. The patch there addressed problem 1 -- FluidSynth now detects when the song officially ends (the EOT event for the longest track, which may be much later than the final note ends). I think we have agreed that FS should not "second-guess" the EOT event and attempt to keep playing until the channel is silent. For one thing, this has the potential of non-termination if the MIDI file has a NoteOn event without a corresponding NoteOff.

I haven't looked into Problem 2 but I suspect this hasn't been addressed, so this ticket probably should remain open.

Original comment by: mattgiuca

tstarling commented 4 years ago

I found this task because I was listening to some rendered audio files on Wikipedia and I was annoyed about the abrupt way that they terminate. See e.g. https://en.wikipedia.org/wiki/Mozart%27s_starling . Our Score extension uses LilyPond to generate MIDI files which are then converted to Ogg using FluidSynth with the -F option. I suppose I could add 500ms of silence as a second MIDI file to the command line, although it's a bit of a hack since we don't know how long the sound will take to decay.

I appreciate that it's nice to have a way to generate files that end exactly on the beat, for looping. For our purposes, it would be fine to have a command line option or config setting.

Foxy6670 commented 2 years ago

Hate to revive an old thread, but this is STILL HAPPENING in FluidSynth 2.1.7.

derselbst commented 2 years ago

Hate to revive an old thread, but this is STILL HAPPENING in FluidSynth 2.1.7.

That's why this ticket is still open. I welcome your PR.

topaz commented 2 years ago

Other than situations where FluidSynth reverb settings are high, I've alleviated big chunks of this issue in #1159 and #1167. They cause FluidSynth to wait for active voices to finish plus an additional two seconds (for effects like reverb) before stopping playback. Previously, FluidSynth would stop playback immediately once the last MIDI event was processed. The "wait two seconds" part would be better handled by a mechanism for detecting when audio actually drops below some minimum threshold, but I'm not equipped to implement such a feature at this time; ideas for that logic in particular are being captured in #1165.

36000000 commented 10 months ago

uname -a: Linux box 5.10.0-26-amd64 #1 SMP Debian 5.10.197-1 (2023-09-29) x86_64 GNU/Linux

Fluidsynth version 2.1.7.

These cases do work, reading directly: fluidsynth -a jack -g 1 TimGM6mb.sf2 download/Fur Elise.mid fluidsynth -F out.wav -g 1 TimGM6mb.sf2 download/Fur Elise.mid fluidsynth -a alsa -g 1 TimGM6mb.sf2 download/Fur Elise.mid

This works with alsa sequencer and alsa playback: fluidsynth -a alsa -m alsa_seq -g 1 TimGM6mb.sf2 pmidi -p 128:0 download/Fur Elise.mid

This don't (starting and configuring jack2 first with qjackctl): fluidsynth -a jack -m alsa_seq -g 1 TimGM6mb.sf2 pmidi -p 130:0 download/Fur Elise.mid

Same problem with other synthesizer playing via jack (connect synthesizers midi in with system capture midi out in qjackctl first) foo-yc20-cli pmidi -p 14:0 download/Fur Elise.mid In the foo-yc20-cli appers seversal time PANIC. I tryid it with setBfree and horgand with the same result (abort bevore EOF at the same position and PANIC in horgand).

I wonder how jack affects the alsa midi sequencer.