Sound glitch when AudioBuffer has different sampling from device.
Reported by
pp.b...@gmail.com,
Aug 22
|
||||
Issue descriptionUserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0 Steps to reproduce the problem: 1. Open https://jsfiddle.net/4fmypg87/ 2. Click on button #2, a case that involves re-sampling 3. Notice sound glitches (in contrast to case #1 without re-sampling) What is the expected behavior? No (noticeable) difference in sound, regardless of whether re-sampling is involved or not. What went wrong? Audio has a noticeable glitch between queued buffers. Did this work before? N/A Does this work in other browsers? No - Safari: Sound glitch - Ms Edge 42: Sound glitch - Firefox 62: Works fine Chrome version: 70.0.3530.0 Channel: canary OS Version: 10.0 Flash Version: Shockwave Flash 27.0 r0
,
Aug 22
What's your device sample rate? We were able reproduce this only on some devices. What I'd expect is that result of re-sampling will have matching end and beginning with source data. When re-sampling is done on my side (Emscripten app), then this problem doesn't exits.
,
Aug 23
,
Aug 23
In the beginning I thought that it's connected to device 48kHz sampling. So I've changed sound device mode to 44kHz, but the bug is there. Currently I can reproduce this on: - MacBook Pro (Retina, 15-inch, Mid 2014) - Dell Precision 5520 + Windows 10. - Dell XPS15 9550 + Windows 10
,
Aug 23
Retried again on my MacBook Pro (Retina 15in) at sample rates of 44.1, 48, 88.2, and 96 kHz. Cannot hear any glitches using headphones. Also tried on my linux machine at 44.1 kHz (and headphones). No glitches. And I made a mistake in my reasoning for the glitches. I see you are creating a bunch of buffers that are samples from a sine wave. These should all fit together nicely. The only thing I can think of now is if buffer.duration is slightly off or if roundoff in updating timeBuffered is causing a buffer to start one (or a few) samples too early or too late. One way to test this (I can't do it because I don't hear any glitches), is to use buffer.length and update a totalFrames counter and set timeBuffered = totalFrames / context.sampleRate.
,
Aug 23
I've made some changes to emphasize this glitch: https://jsfiddle.net/4fmypg87/8/ It should be much more noticeable. Also I've created a footage: https://www.youtube.com/watch?v=ZHBStSlQBQo where you can hear a buzz on the top of sin-wave. The rounding precision problem was a first thought in my mind. I've tried to fix it with Math.fround on my operations, but without success.
,
Aug 23
Ok, that is very clear now. I think the best way to see what's happening is to use hoch.github.io/canopy to see the generated waveform. I'll try that out shortly.
,
Aug 23
Canopy shows a nice smooth waveform. Something about the real-time context makes it different from an offline context.
,
Aug 23
I'm glad that the issue is visible right now. The Canopy is really nice tool! I can confirm that Canopy can render samples into a smooth sound. Also I've tried to crate AudioContext with sampleRate that matches buffer sample rate, but it didn't work, as I assume that re-sapling will still occur to match the hardware device sampling rate. Do you see any obvious solution for this issue, what doesn't involve run-time re-sampling?
,
Aug 23
The WebAudio spec allows creating an AudioContext with a user-selectable sample rate. This would allow you to use your AudioBuffers without resampling (if they're all at the same rate). Of course, there has to be resampling to get that audio out to the HW if the HW doesn't support your selected rate. Unfortunately, Chrome hasn't implemented this yet.
,
Aug 25
Well, that was silly. In 876917-test.js I set the sample rate of the context to 43800; the same as the buffer. It should have been set to 44100 (@sampleRate). When I do that, I hear the glitches. If you zoom in, you can see glitches every 30 samples. I'm attaching the updated test.
,
Aug 25
Ok, I think there's confusion the the buffer source playback on where the output should start and end. I see that the first buffer produces output for frames 0-30, and frame 30 is 0.96648. The second buffer produces output for frames 30-60, and frame 30 is .948362. The output from these buffers get summed together at the destination to produce a value of 1.914842. And that's exactly what canopy shows as the output at frame 30. The second frame is scheduled to start at time 0.000684931506849315, which is also the duration of the first buffer. This time corresponds to a sample frame of 30.20547. Thus we output a sample at frame 30. But the buffer actually starts after frame 30, so the first output should happen at frame 31, not 30. I think that will fix this issue.
,
Sep 7
I think Chrome needs to implement sub-sample accurate start for ABSN. I think what's happening now is that if the start frame is 30.2, we output the first sample of the buffer at frame 30. Then we end up outputting an extra sample due to interpolation, and the extra sample gets added to the first sample of the next buffer. Instead, the first output should be at frame 31, and we need to interpolate the value because the source started at frame 30.2 and not 31. So some mix of sample 0 and 1 will be the output. This seems to work for the canopy test case (no glitches), but more testing needs to be done. |
||||
►
Sign in to add a comment |
||||
Comment 1 by rtoy@chromium.org
, Aug 22