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.
Fix for https://github.com/gopxl/beep/issues/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 newpos
, 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 afloat64
. 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 be6*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 theDoppler
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 theif
statement with afor
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.