Avoid garbling the sound if the volume slider is moved fast
ClosedPublic

Authored by kezik on Jul 8 2019, 12:07 AM.

Details

Summary

The audio should not be garbled if you move fast the audio slider (it distorts because it stops and plays the feedback sound every few milliseconds)

An alternative approach is to return; if the ca_context_playing says that the sound is still playing, but that gives less "resolution"

BUG: 409525
BUG: 410716
FIXED-IN: 5.17.0

Diff Detail

Repository
R115 Plasma Audio Volume Applet
Lint
Lint Skipped
Unit
Unit Tests Skipped
kezik created this revision.Jul 8 2019, 12:07 AM
Restricted Application added a subscriber: plasma-devel. ยท View Herald TranscriptJul 8 2019, 12:07 AM
kezik requested review of this revision.Jul 8 2019, 12:07 AM
kezik added a comment.Jul 8 2019, 12:16 AM

I don't know why it is not showing the context of the patch ๐Ÿคทโ€โ™‚๏ธ
I selected the plasma-pa project

davidedmundson added inline comments.
src/qml/volumefeedback.cpp
33

This object leaks.

You're better off just making it a member var directly.

Also, see QElapsedTimer

34

Why? This will block the first noise?

kezik updated this revision to Diff 61337.Jul 8 2019, 1:19 PM

Thanks @davidedmundson for the feedback,
I fixed what you suggested, but thinking about this again, the 50ms timer fixed the audio garbling but the sounds felt "too frequent", increasing the timer gave the same exact result as disabling the function altogether, so here's that.
It wasn't worth the extra complexity of the timer

I don't know why it is not showing the context of the patch ๐Ÿคทโ€โ™‚๏ธ
I selected the plasma-pa project

Because you didn't use arc to submit the patch and Phabricator is kinda dumb about this. This should get much better with GitLab.

filipf removed a reviewer: VDG.Jul 29 2019, 10:56 PM
filipf added a subscriber: filipf.

Removed VDG as the reviewer, seems like a technical issue all together. Also wanted to contribute, but I don't really perceive any issues when moving the slider fast :/

Removed VDG as the reviewer, seems like a technical issue all together.

Sorry

Also wanted to contribute, but I don't really perceive any issues when moving the slider fast :/


This is what I am referring to

As you can see in the picture, the waveform of the feedback sound gets truncated in a "violent" way, and the abrupt truncation generates a broadband sound spike that's clearly audible
Also, having the sound start and truncate 10 times when you move the slider a bit feels less polished
Maybe a better option is to have the sound play when you release the mouse button from the slider

Ah I can definitely reproduce it. I agree, it sounds bad. +1 for fixing it.

davidedmundson accepted this revision.Jul 31 2019, 12:28 PM

Should it queue up a sound so that it plays one sound at the final volume when you've stopped dragging?

This revision is now accepted and ready to land.Jul 31 2019, 12:28 PM
kezik updated this revision to Diff 62863.Jul 31 2019, 3:21 PM

Should it queue up a sound so that it plays one sound at the final volume when you've stopped dragging?

I made that it plays the sound at the final volume when you release the mouse button

ngraham requested changes to this revision.Aug 1 2019, 10:01 PM

With this change, if I press the volume up and volume down key on my keyboard, feedback only plays every second or third time I hit the button (depending on how fast I press it).

This revision now requires changes to proceed.Aug 1 2019, 10:01 PM
kezik added a comment.Aug 1 2019, 11:19 PM

With this change, if I press the volume up and volume down key on my keyboard, feedback only plays every second or third time I hit the button (depending on how fast I press it).

True

For some reason, if I measure the amount of time that it takes for ca_context_playing to switch back from 1 to 0, by busy waiting, it blocks for about two seconds, even though the actual sound lasts about 0.07 seconds
With the volume slider, for some other reason, the ca_context_playing goes back to 0 sooner, but with the volume keys it blocks the whole two seconds.

I have no idea on why it does that

cfeck edited the summary of this revision. (Show Details)Aug 1 2019, 11:31 PM

updateTimer uses slider value and it takes 200 ms to react, so you can sync the timer with keyboard one by increase the interval https://phabricator.kde.org/source/plasma-pa/browse/master/applet/contents/ui/ListItemBase.qml$198

kezik updated this revision to Diff 63008.Aug 2 2019, 11:43 PM

I talked with 4-5 people and they all said that giving real time feedback in the slider is useless and bad, so here's that, the feedback is given on mouse release, and every problem is automatically solved.

If you want more technical details about the alternative version, read the rest of this comment, otherwise just ignore, now everything is fine.

useless part of the comment:

updateTimer uses slider value and it takes 200 ms to react, so you can sync the timer with keyboard one by increase the interval https://phabricator.kde.org/source/plasma-pa/browse/master/applet/contents/ui/ListItemBase.qml$198

I'm not sure if I am understanding this, the timer seems to only provide feedback to the slider .. ?

The main issue here is inside libcanberra (or pulseaudio): in some conditions (I found that the bug occurs mostly if no other sound is playing) ca_context_playing simply does not work correctly, i'm fairly sure that my patch is correct, I tested libcanberra independently and I can confirm that "bug"

I tested that by setting CA_PROP_CANBERRA_CACHE_CONTROL to "never", the problem seems to go away, that's probably suboptimal but it's the only decent workaround I can come up with

diff --git a/applet/contents/ui/ListItemBase.qml b/applet/contents/ui/ListItemBase.qml
index d962eb5..6bdbcb7 100644
--- a/applet/contents/ui/ListItemBase.qml
+++ b/applet/contents/ui/ListItemBase.qml
@@ -190,6 +190,10 @@ PlasmaComponents.ListItem {
                                 // whereas PA rejected the volume change and is
                                 // still at v15 (e.g.).
                                 updateTimer.restart();
+
+                                if (type == "sink") {
+                                    playFeedback(Index);
+                                }
                             }
                         }
 
diff --git a/src/qml/volumefeedback.cpp b/src/qml/volumefeedback.cpp
index 69bc260..3e5abae 100644
--- a/src/qml/volumefeedback.cpp
+++ b/src/qml/volumefeedback.cpp
@@ -55,9 +55,9 @@ void VolumeFeedback::play(quint32 sinkIndex)
 
     // NB Depending on how this is desired to work, we may want to simply
     // skip playing, or cancel the currently playing sound and play our
-    // new one... for now, let's do the latter.
+    // new one... for now, let's do the former.
     if (playing) {
-        ca_context_cancel(context, cindex);
+        return;
     }
 
     char dev[64];
@@ -70,7 +70,7 @@ void VolumeFeedback::play(quint32 sinkIndex)
         cindex,
         CA_PROP_EVENT_DESCRIPTION, "Volume Control Feedback Sound",
         CA_PROP_EVENT_ID, "audio-volume-change",
-        CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+        CA_PROP_CANBERRA_CACHE_CONTROL, "never",  // XXX workaround a libcamberra bug
         CA_PROP_CANBERRA_ENABLE, "1",
         nullptr
     );
ngraham accepted this revision.Aug 3 2019, 1:39 AM

Much better!

This revision is now accepted and ready to land.Aug 3 2019, 1:39 AM

@davidedmundson and/or @drosca, are you good with this new approach?

ngraham edited the summary of this revision. (Show Details)Aug 8 2019, 3:24 PM
Closed by commit R115:a420dd6be1a9: Avoid garbling the sound if the volume slider is moved fast (authored by Kezi Olio <keziolio123@gmail.com>, committed by ngraham). ยท Explain WhyAug 8 2019, 4:35 PM
This revision was automatically updated to reflect the committed changes.