omriharel / deej

Set app volumes with real sliders! deej is an Arduino & Go project to let you build your own hardware mixer for Windows and Linux
https://deej.rocks
MIT License
4.71k stars 433 forks source link

Continually set volume #100

Closed WorldTeacher closed 4 months ago

WorldTeacher commented 5 months ago

Hi,

I recently started using deej but have noticed a potential issue:

Certain applications like Firefox handle audio playback in a non-standard way. If you are playing a video on YouTube and use the slider to control the volume, it directly influences the audio level in pipewire. This causes the audio to suddenly jump to the level set by youtube/firefox and then jump to the level set by Deej, once Deej detects a change. This is generally accompanied by an error like this:

2024-04-04 19:47:02.445 DEBUG   deej.sessions               Stale session map detected on slider move, refreshing
2024-04-04 19:47:02.445 DEBUG   deej.sessions               Releasing and clearing all audio sessions
2024-04-04 19:47:02.445 DEBUG   deej.sessions.master        Releasing audio session
2024-04-04 19:47:02.445 DEBUG   deej.sessions.mic           Releasing audio session
2024-04-04 19:47:02.445 DEBUG   deej.sessions.firefox       Releasing audio session
2024-04-04 19:47:02.445 DEBUG   deej.sessions               Session map cleared
2024-04-04 19:47:02.445 DEBUG   deej.sessions.master        Created audio session instance  {"session": "<session: master, vol: 0.56>"}
2024-04-04 19:47:02.445 DEBUG   deej.sessions.mic           Created audio session instance  {"session": "<session: mic, vol: 1.00>"}
2024-04-04 19:47:02.445 DEBUG   deej.sessions.firefox       Created audio session instance  {"session": "<session: firefox, vol: 1.00>"}
2024-04-04 19:47:02.445 INFO    deej.sessions               Got all audio sessions successfully {"sessionMap": "<3 audio sessions>"}
2024-04-04 19:47:02.445 DEBUG   deej.sessions               Re-acquired sessions successfully
2024-04-04 19:47:02.450 DEBUG   deej.sessions.master        Adjusting session volume    {"to": "0.59"}
2024-04-04 19:47:06.441 DEBUG   deej.sessions.master        Adjusting session volume    {"to": "0.56"}
2024-04-04 19:47:09.800 DEBUG   deej.sessions.master        Adjusting session volume    {"to": "0.59"}

Now this caused me to wonder if it would be possible to create a setting in the config to auto set the volume at a certain interval in order to combat this.

I would try to implement something myself but have no prior experience in go and currently do not have the time to learn a new language.

omriharel commented 4 months ago

Hi @WorldTeacher, thanks for writing. This feature isn't necessarily specific to an application or OS, but I imagine that in the case you described it can have more impact than others.

I can confirm that the current behavior of only changing app volumes in response to a slider being moved is intended, and not expected to change or be made configurable in the near future. It is core to how deej is architected and besides serving an important performance objective it also guarantees that you're able to still change volumes in software without having deej conflict with them.

ornotermes commented 4 months ago

To @WorldTeacher , It's a bit hacky (and not fully tested), but you can do it in the firmware, You can create a jiggle that every once in a while changes the value of the pot/slider you want (forcing an update of the volume).

Put this before setup():

unsigned long jiggleLast; //Last time a jiggle happened
const int jiggleDelay = 1000; //how many ms to wait between jiggles
const int jiggleStep = 36; //depends on noise reduction in config, my math says 16, 26, or 36

And put this function somewhere after loop():

void jiggler(int sliders[], int count) { //jiggle a slider every once in a while
  if (millis() > jiggleLast + jiggleDelay){
    jiggleLast = millis();
    for (int i = 0; i < count; i++)
      analogSliderValues[sliders[i]] += analogSliderValues[sliders[i]] > 100 ? -jiggleStep : jiggleStep;
  }
}

And put this between updateSliderValues(); and sendSliderValues(); in main():

  int jiggleSliders[2] = {1,2}; //sliders you want to jiggle
  jiggler(jiggleSliders, sizeof(jiggleSliders));

It will manipulate your output every second or so:

803|0|1023|614|595
804|0|1023|614|595
804|0|1023|614|595
804|36|987|614|595
804|0|1023|614|595
804|0|1023|614|595
804|0|1023|614|595
WorldTeacher commented 4 months ago

Hi @ornotermes,

thanks for the code. I can confirm that it works, after setting the sliders to my mappings. There is some slight movement of the slider (+-3% each second) but it's not noticeable.

@omriharel Thanks for letting me know, I'm sorry I didn't answer yesterday, something came up. The points you mentioned are understandable.