Closed Bug 870174 Opened 12 years ago Closed 12 years ago

Eliminate resampler lag in Web Audio

Categories

(Core :: Web Audio, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla24

People

(Reporter: derf, Assigned: ehsan.akhgari)

References

Details

Attachments

(1 file, 2 obsolete files)

content/media/webaudio/AudioBufferSourceNode.cpp's CopyFromInputBufferWithResampling() and content/media/webaudio/MediaBufferDecoder.cpp's MediaDecodeTask::CopyBuffer() use the Speex resampler to resample a whole buffer/decoded file. By default, the Speex resampler inserts extra zeros at the start of the output so it can return an output block with the same duration as the input block (modulo fractional samples), but this means extra silence will be appended to the start of the file, and the last few samples of the file will be lost. You should use speex_resampler_skip_zeros() to avoid this. From the documentation: /** Make sure that the first samples to go out of the resamplers don't have * leading zeros. This is only useful before starting to use a newly created * resampler. It is recommended to use that when resampling an audio file, as * it will generate a file with the same length. For real-time processing, * it is probably easier not to use this call (so that the output duration * is the same for the first frame). * @param st Resampler state */ int speex_resampler_skip_zeros(SpeexResamplerState *st);
Well, I would say that speex_resampler_skip_zeros() is mostly useful for non-realtime applications. For anything real-time, it makes buffer management more complicated without reducing the overall delay.
(In reply to Jean-Marc Valin (:jmspeex) from comment #1) > Well, I would say that speex_resampler_skip_zeros() is mostly useful for > non-realtime applications. For anything real-time, it makes buffer Right, this is for, e.g., resampling an entire file after decoding. The real-time parts of the Web Audio API all run at 48 kHz, so they don't need resampling.
Yeah, for a file, it's definitely a good idea to not only use speex_resampler_skip_zeros(), but to also force the resampler to produce the missing samples at the end.
(In reply to Jean-Marc Valin (:jmspeex) from comment #3) > Yeah, for a file, it's definitely a good idea to not only use > speex_resampler_skip_zeros(), but to also force the resampler to produce the > missing samples at the end. Right, which means stuffing speex_resampler_get_input_latency() extra samples in at the end, I presume?
Correct.
Well, the resampling done in AudioBufferSourceNode is real-time, but in MediaBufferDecoder.cpp we resample a whole file. That being said, in AudioBufferSourceNode we are _also_ resampling a whole file, but we do it on the fly, to produce 128 samples every time. Not sure if that means we should use speex_resampler_skip_zeros or not... (In reply to comment #3) > Yeah, for a file, it's definitely a good idea to not only use > speex_resampler_skip_zeros(), but to also force the resampler to produce the > missing samples at the end. How should I do the latter? Honestly I'm not sure if I'm really interested in maintaining the same duration as the input buffer in either of the cases...
(In reply to Timothy B. Terriberry (:derf) from comment #4) > (In reply to Jean-Marc Valin (:jmspeex) from comment #3) > > Yeah, for a file, it's definitely a good idea to not only use > > speex_resampler_skip_zeros(), but to also force the resampler to produce the > > missing samples at the end. > > Right, which means stuffing speex_resampler_get_input_latency() extra > samples in at the end, I presume? To make sure I understand correctly, this means passing a silent buffer of size speex_resampler_get_input_latency as the last set of input frames and expect speex_resampler_get_output_latency samples out of the resampler, right? I experimented with a prototype of this idea and I'm getting a much better result in a test case that I have here. Also, I assume there's no way to call these two functions by just knowing the input and output sampling rates without allocating a SpeexResamplerState, is that correct?
(In reply to :Ehsan Akhgari (needinfo? me!) from comment #7) > To make sure I understand correctly, this means passing a silent buffer of > size speex_resampler_get_input_latency as the last set of input frames and > expect speex_resampler_get_output_latency samples out of the resampler, > right? Well, you will get *approximately* speex_resampler_get_output_latency samples out of the resampler, but otherwise that's correct. > Also, I assume there's no way to call these two functions by just knowing > the input and output sampling rates without allocating a > SpeexResamplerState, is that correct? Not right now. However, you can always pre-compute a table of useful values. IIRC, it depends only on the rates and the quality setting being used.
OK so I have a partial patch to make things a bit better, but I need JS_ReallocateArrayBufferContents which is landing in bug 866431.
Assignee: nobody → ehsan
Depends on: 866431
Attached patch WIP (obsolete) (deleted) — Splinter Review
Attached patch Patch (v1) (obsolete) (deleted) — Splinter Review
https://tbpl.mozilla.org/?tree=Try&rev=b3597859115f (Note that I might have to adjust the baselines for different platforms before landing.)
Attachment #747502 - Attachment is obsolete: true
Attachment #748276 - Flags: review?(roc)
Attached patch Patch (v2) (deleted) — Splinter Review
This fixes the build bustage on mobile.
Attachment #748276 - Attachment is obsolete: true
Attachment #748276 - Flags: review?(roc)
Attachment #748450 - Flags: review?(roc)
No longer depends on: 866431
Status: NEW → RESOLVED
Closed: 12 years ago
Flags: in-testsuite+
Resolution: --- → FIXED
Target Milestone: --- → mozilla24
Mass moving Web Audio bugs to the Web Audio component. Filter on duckityduck.
Component: Video/Audio → Web Audio
Depends on: 886653
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: