Open jcadduono opened 3 years ago
Why was this closed? I can't find any option for logarithmic volume control..
I think this would be a really nice addition. I've experimented with some manual code changes and adding the following row in AudioSink.setVolume() works well for me:
volumeNorm = (float) Math.pow(volumeNorm, 4) / 2;
I will run my custom build until this gets added (if ever). Could we reopen this issue? @jcadduono @devgianlu
sorry, the moment i found the rust version of librespot (with cubic volume control that works really well with my AVR) i flocked to that and closed this to pretend it never happened lol
No worries! I've run librespot for a few years, but it's just too buggy. This is the feature I'm missing in the Java version.
I have the same problem, and this improves it greatly. Power of 4 moves it too much in the other direction for me (why did you choose that value, @manfreddz?) but pow(volumeNorm, 2) is very nice. I'm not so sure about it mathematically, but if it works it works. :)
Would be great if this easy change could be integrated here!
I think this would be a really nice addition. I've experimented with some manual code changes and adding the following row in AudioSink.setVolume() works well for me:
volumeNorm = (float) Math.pow(volumeNorm, 4) / 2;
I will run my custom build until this gets added (if ever). Could we reopen this issue? @jcadduono @devgianlu
I migrated from librespot-org/librespot for the local API and immediately had this very loud problem. My Java is approximately 16 years out-of-date but this is the patch I'm running now to get something very similar to librespot-org/librespot's default logarithmic volume control. I used DB_RANGE = 40
here instead of 60 because 60 still seemed too loud/too much range but I think they default to 60.
--- a/player/src/main/java/xyz/gianlu/librespot/player/mixing/AudioSink.java
+++ b/player/src/main/java/xyz/gianlu/librespot/player/mixing/AudioSink.java
@@ -137,9 +137,22 @@ public final class AudioSink implements Runnable, Closeable {
if (volume < 0 || volume > Player.VOLUME_MAX)
throw new IllegalArgumentException("Invalid volume: " + volume);
- float volumeNorm = ((float) volume) / Player.VOLUME_MAX;
- if (output.setVolume(volumeNorm)) mixing.setGlobalGain(1);
- else mixing.setGlobalGain(volumeNorm);
+ double volumeNorm;
+ if (volume == 0) { // set to avoid fp/rounding error
+ volumeNorm = 0.0;
+ } else if (volume == Player.VOLUME_MAX) { // set to avoid fp/rounding error
+ volumeNorm = 1.0;
+ } else {
+ volumeNorm = ((double) volume) / Player.VOLUME_MAX;
+ double DB_RANGE = 40.0;
+ double DB_VOLTAGE_RATIO = 20.0;
+ double db_ratio = Math.pow(10.0, DB_RANGE / DB_VOLTAGE_RATIO);
+ double ideal_factor = Math.log(db_ratio);
+ volumeNorm = Math.exp(ideal_factor * volumeNorm) / db_ratio;
+ }
+
+ if (output.setVolume((float) volumeNorm)) mixing.setGlobalGain(1);
+ else mixing.setGlobalGain((float) volumeNorm);
}
@Override
@tofublock, if I remember correctly I found some research paper saying the value should be somewhere between 3 and 4. From that I just tested some values and liked 4 the most. I added the division just because it matched well with my clients and their speakers.
Is your feature request related to a problem? Please describe. Controlling the volume is a struggle because there's almost no difference between 25% and 100% and most of the normal listening range is from 0-15% on my system.
Describe the solution you'd like Add a volume control config option between linear and logarithmic.
Describe alternatives you've considered Sending audio to a mixer with a max volume set at 25%, but then I wouldn't be able to blast music when wanted.
Additional context I dunno maybe there's a better way to do this?