PipeWire sleep while not producing
Related discussion
No response
Is your feature request related to a problem?
No response
Describe the solution you'd like
It would be nice if FluidSynth when invoked as a 'server' (e.g. as invoked by systemd) let the output source node in PipeWire sleep while FluidSynth isn't receiving input - and hence isn't generating output. The fact that it doesn't sleep can be seen by adding set audio.driver pipewire to ~/.fluidsynth, restarting the service (systemctl restart --user fluidsynth.service) and looking at both htop and pw-top output.
Describe alternatives you've considered
No response
Additional context
No response
I see that this is essentially a duplicate of #338 - where it was stated by @derselbst that even without active voices, there may be some mixing (e.g. due to some effects).
Perhaps a user-specified timeout could be used if there have been (continuously) no active voices? By default there would be no timeout; but then for users who want the nodes to sleep - they could (e.g. 30 seconds or whatever they want)?
What is the benefit of letting pipewire sleep, or what is your use-case?
Essentially, it'd be nice to have a MIDI device on my laptop and so I can point e.g. DOSBox, retroarch, and others to it. When I'm not playing games and moving around: I want to avoid excess draw so that I can edit documents, browse, write code, watch media for longer stretches without having to be restricted by a power cable.
By sending a silent signal and keeping the audio device alive; FluidSynth increases the idle draw from about 10W to 12.5W on my system.
I realise, of course, that if I am watching media that the audio device will draw anyway - but for other tasks this is definitely wasted battery.
Ok, so putting pipewire to sleep saves 2.5W. But fluidsynth still renders audio in the background. So, how much do you save when you terminate fluidsynth?
@derselbst In short - I save 2.5W when fluidsynth is terminated. I didn't put pipewire to sleep in the above example - I was explaining the difference between fluidsynth.service being on vs off (masked).
Pipewire doesn't care if the PCM it receives is silent - unless the stream is paused it won't allow the audio (output) device to sleep. Pulseaudio will behave the same way now that pulseaudio servers are provided by pipewire on many distros.
I realise that 2.5W is the 'upper bound' on the power saved - the actual saving depends how often my audio hardware sleeps when I'm using the laptop (perhaps, like, 50% of the time without fluidsynth).
Still - it's nice to have the best possible battery life if it isn't too difficult to implement.
While I do understand your "best possible battery life" argument, this is a best effort open-source project, I'm the only maintainer around here, and my personal motivation to work on such a thing just to save 2.5W is pretty much non-existent, sry.
Lucky you, we've got something: #1006
There are two caveats about this:
- Only ALSA and PulseAudio are properly supported
- You must use the system-timer, i.e.
-o player.timing-source=system
You seem to be C/C++ affin, so you might want to give it a try to see if you can reproduce the 2.5W savings on this old branch. If you can't, it's probably much more difficult to implement.
If you can, the branch needs to be rebased against recent master, one should make sure that it also works with the sample timer (which is the default) and add suspend support for the other audio drivers we offer.
Also, I'm not sure if the introduced synth.idle-timeout is actually a good idea, or whether it would be better to analyse the gain of the generated audio output over time to see if it falls below noise floor of 96 or 144dB. Doing so would likely also allow to address #1408 properly.
From an outsider's perspective ... it probably isn't worth resurrecting a fix which has already been abandoned and there's debate about the approach.
It seems #1408 is considered a much more important issue; perhaps once that is settled then that will lead to ideas about how (or when) to sleep the service.
Hi, excuse me about cut in. Im doing it (in java code).
But awake require 0.5 secs if suspending after 60 secs. so, if you need realtime process. awake action still Requied (before 1.0sec etc).
long _touchTime;
long _spanForCheck = 16 * 1000;
long _spanForSuspend = 60 * 1000;
public synchronized void touch() {
if (_touchTime == 0) {
OneHelper.runOnUiThread(this::checkSuspend, _spanForCheck);
}
_touchTime = System.currentTimeMillis();
}
public synchronized void checkSuspend() {
if (OneDriverSoundFont._jfluid == null) {
return;
}
long tick = System.currentTimeMillis();
long diff = tick - _touchTime;
if (diff >= _spanForSuspend ) {
if (_handle >= 0) {
int voice = OneDriverSoundFont._jfluid.countActiveVoice(_handle);
if (voice == 0) {
OneDriverSoundFont._jfluid.suspend(_handle);
OneHelper.runOnUiThread(() -> {
try {
Context context = OneHelper.getApplicationContext();
Toast.makeText(context, "Suspended MIXandCC Audio", Toast.LENGTH_LONG).show();
}catch(NullPointerException ex) {
}
});
_touchTime = 0;
return;
}
}
}
OneHelper.runOnUiThread(this::checkSuspend, _spanForCheck);
}
void JNICALL jfluid_suspend(JNIEnv *env, jobject obj, jint id) {
if (id < 0) {
return;
}
fluid_handle_t *handle = getFluid(id);
if (handle->audio != nullptr) {
delete_fluid_audio_driver(handle->audio);
handle->audio = nullptr;
}
}
inline void jfluid_resume2(fluid_handle_t *handle) {
if (handle->audio == nullptr) {
handle->audio = new_fluid_audio_driver(handle->settings, handle->synth);
}
}