Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix(484) - ChannelVolume misbehaving #493

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

DivineGod
Copy link
Contributor

This PR will probably collect a few fixes that relate to #484 as I go through rodio to find all the issues that seem to prevent proper use of ChannelVolume.

I think I've identified a few areas that need attention, first being the ChannelCountConverter which is started with an Empty source when Sink::try_new is called. This would cause an issue where the channel converter had the wrong to count, as the actual source input channel count might not necessarily be 1 as the empty source was specifying. By setting Empty channels to 0 and handling the cases where they show up, we can more gracefully handle these issues.

Next issue is an issue with the sample rate converter where if there's a mismatch the ChannelVolume once again seem to be messed up and not produce the right results. This might also have been identified in other issues; I've not triaged them all yet.

Copy link
Collaborator

@dvdsk dvdsk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First thanks a lot for going after this issue. Does the example your PR adds reproduce the issue? I would love to have a test that reproduces it.

If I understand correctly your approach modifies the channel converter and sample rate converter to recognize the Empty source. They do so by checking for its now nonsensical channel count and sample rate of zero.

An alternative would be removing the use of empty in queue (used by Sink::try_new) here:

current: Box<dyn Source<Item = S> + Send>,

We could use a Option<()> there and make the None branch play 'empty' sounds.

On the other hand, Empty probably has other valid uses....

Quite a difficult one this. I do not have any more time right now, ill come back to this.

@@ -36,17 +39,17 @@ where
{
#[inline]
fn current_frame_len(&self) -> Option<usize> {
None
Some(0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this change. None means the frame length will not change going forward. I do not know what Some(0) means. Filters/wrappers around the Empty source will treat every new sample as a new frame and run code paths to handle that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't recall why I had that in there. I don't think it needs to be there. So I'll happily revert that change

@DivineGod
Copy link
Contributor Author

[...] Does the example your PR adds reproduce the issue? I would love to have a test that reproduces it.

Yes, it does, running the example on master produces a nasty clipped sound on all channels and then only output on channel 0. Note for reproducing is that the sample rate of the output device seems to have to be 48kHz on my setup. If it's not then I run into the sample rate issue that I mentioned.

@dvdsk
Copy link
Collaborator

dvdsk commented Apr 21, 2024

Yes, it does, running the example on master produces a nasty clipped sound on all channels and then only output on channel 0.

Nice, then I can try it out and play around a little with the PR

@dvdsk
Copy link
Collaborator

dvdsk commented Apr 21, 2024

I do not yet understand why ChannelVolume is misbehaving. I am gonna have to play with it a bit to find that out and to understand it better.

I can not merge this until I understand everything around it.

Unfortunately I do not have a lot of time allocated for this, so it could a bit. I'll keep you updated.

@DivineGod
Copy link
Contributor Author

That’s totally understandable. I am happy to help out getting it to a state where it fixes things and there’s an understanding of why it all works out

@dvdsk dvdsk force-pushed the master branch 3 times, most recently from b10961c to a7f67b3 Compare October 10, 2024 00:14
@dvdsk
Copy link
Collaborator

dvdsk commented Oct 17, 2024

I have some time now :)

If you still have time to help out, could you rebase or merge master to resolve the conflict?

As I understand the PR sample-rate & channel-count zero function as a sort of flag/placeholder. Then the behavior of various rodio parts change when they see it. Specifically the converters pick the output instead of the input as target count/rate. Would Option not work better for that role then zero?

@dvdsk
Copy link
Collaborator

dvdsk commented Oct 17, 2024

Oh and the changelog needs an update marking this is fixed now

move channel from fix to constructor, add test

Empty Source should not have a sample rate. Sample Rate Conversion to handle Empty source properly

add more doc around Empty
@DivineGod
Copy link
Contributor Author

If you still have time to help out, could you rebase or merge master to resolve the conflict?

Rebased to sort merge conflict

@DivineGod
Copy link
Contributor Author

Just rested the example after rebase; it has regressed to not sorting out the channel volumes correctly. I'll try to investigate and come up with some more in-depth unit tests as well to see if I can better isolate the issue.

A preliminary test in source/channel_volume is showing that that part is iterating correctly. But running a 6 channel output with the example distributes the first two provided volumes over the 6 total outputs.

@DivineGod

This comment was marked as resolved.

@DivineGod
Copy link
Contributor Author

I've added a test to sink.rs which reproduces my issue with the following assert:

---- sink::tests::test_channel_volume stdout ----
thread 'sink::tests::test_channel_volume' panicked at src/sink.rs:462:9:
assertion `left == right` failed
  left: Some(3.0517578e-5)
 right: Some(1.0)

I thought it repro'd but it didn't. I've pushed a working test for now.

@dvdsk dvdsk added this to the 0.20 milestone Oct 23, 2024
@dvdsk
Copy link
Collaborator

dvdsk commented Oct 23, 2024

I thought it repro'd but it didn't. I've pushed a working test for now.

thanks! and thank you very much for hunting for the bug!

@dvdsk dvdsk removed this from the 0.20 milestone Nov 2, 2024
@dvdsk dvdsk force-pushed the master branch 2 times, most recently from 9fc8241 to 8eb076c Compare November 8, 2024 00:54
@dvdsk dvdsk force-pushed the master branch 2 times, most recently from 0ee0413 to 073fdb1 Compare November 8, 2024 00:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants