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

Rewrite resampler #166

Merged
merged 8 commits into from
Jul 31, 2024
Merged

Rewrite resampler #166

merged 8 commits into from
Jul 31, 2024

Conversation

MarkKremer
Copy link
Contributor

@MarkKremer MarkKremer commented Jul 11, 2024

Fix for #20

Rewritten the Resampler to make the code easier to read & fix some bugs:

  • When the source streamer didn't conform the Streamer interface by returning a drained signal & then returning samples again, the internal buffer could be resized and unsuitable to do the job causing an out of range panic. The new resampler keeps track of the end of the stream. When the end is reached, it will simply stay in a drained state.

  • SetRatio with a big enough ratio could cause an out of range panic. This was because during the calculation of the new pos, the result was cast to an int. If the ratio was so big that this rounding down caused a different of more than the buffer size, the buffer would be indexed with a negative value. I don't expect any reasonable application to run into this error, but it's nice to not get panics when playing around with the speedy-player example. That said, I've added some limits to the values that can be selected in that example.

    pos is now a float64. I expect this to carry enough precision for most use-cases. Say you have a resample ratio of 1/6 (from 8000 to 48000), 48000 samples per seconds, 86400 seconds in a day, 365 days in a year, the number of unique values would be 6*48000*86400*365 = 9.082368×10^12. float64 has enough precision to hold a bit less than 16 decimal digits so even though I'm not entirely sure how much we need, there is still a bunch of wiggle room. SetRatio being more precise is probably good for the Doppler streamer. Less samples will be skipped over.

  • Stream fetches new samples from the source streamer to fill the buffer when it detects that the samples needed for the interpolation are after the currently loaded buffers. However, when the ratio is larger than the buffer size, the needed samples could be more than one buffer away. I've replaced the if statement with a for loop so it keeps streaming samples until it reaches the right index. This solves another out of range panic.

I've added a fuzz test to confirm weird resample ratios don't cause panics anymore.

It seems that the doppler example is now easier to crash. But the Doppler streamer is experimental and was giving the resampler invalid ratios. It probably needs a rewrite as well, but that something for another day.

The original length of pts made sense because when wantPos is a decimal position like 3.5, you want the window for quality 1 to contain positions 3 and 4. Having a window of 1 more doesn't make sense for that. My previous reasoning for increasing the window size was arguing from the point of wantPosition always being an integer value, which isn't the case.
Two bugs:
- SetRatio() could cause out of range panic when the ratio was sufficiently big. This happens when the newly calculated position was casted to an int. This caused the value to be rounded down. If difference times the ratio was bigger than the buffer, the calculated wantPos could be a negative index in buf1.
- When the ratio is sufficiently big, the Stream function may not only need to fill the buffers with new data once, but multiple times. The if statement has been replaced with a for loop, so the check is executed until the desired samples are reached.
@MarkKremer MarkKremer marked this pull request as ready for review July 11, 2024 18:29
resample.go Show resolved Hide resolved
resample.go Outdated Show resolved Hide resolved
Copy link
Contributor

@dusk125 dusk125 left a comment

Choose a reason for hiding this comment

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

lgtm

@MarkKremer MarkKremer merged commit bfe9021 into main Jul 31, 2024
1 check passed
@MarkKremer MarkKremer deleted the resampler-rewrite branch July 31, 2024 13:42
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