Note: There are a few cases of duplicates in user autocompletion which are being worked on.

AudioContext.currentTime doesn't update continuously

RESOLVED INVALID

Status

()

Core
Web Audio
RESOLVED INVALID
4 years ago
4 years ago

People

(Reporter: Michael Lelli, Unassigned)

Tracking

Trunk
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment)

(Reporter)

Description

4 years ago
Created attachment 785405 [details]
testcase

User Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0 (Beta/Release)
Build ID: 20130803030205

Steps to reproduce:

Go to the testcase and click the button


Actual results:

The two values for currentTime are the same


Expected results:

The two values should be about a second apart.

This might be related to bug 587465: if you are performing a lot of calculation before checking currentTime it can be off.
(Reporter)

Updated

4 years ago
Attachment #785405 - Attachment mime type: text/plain → text/html

Updated

4 years ago
OS: Windows 8 → All
Hardware: x86_64 → All
This is intentional, we do not update the value of the currentTime attribute until you yield to the event loop.
Status: UNCONFIRMED → RESOLVED
Last Resolved: 4 years ago
Resolution: --- → INVALID

Comment 2

4 years ago
Chrome does update the value, who is wrong?
(In reply to comment #2)
> Chrome does update the value, who is wrong?

Chrome, I believe.  There is no way to implement this the way that Chrome does without locking with the audio thread.  I believe I have raised this on public-audio but I cannot find a link to it right now... :(
Well, a number of client/server audio engines (PulseAudio, WASAPI, etc.) have the same problem, and simply interpolate linearly instead of locking to rendering/callback/audio hardware thread.

We could do the same thing if we agree that we should doing that. It is very common to drive webgl or canvas animation from the audio clock (for easy audio/video synchronisation), and I believe people would expect to have Date.now(), performance.now() and AudioContext.currentTime to work in the same way.
Resolution: INVALID → FIXED
(reverting the flag change).
Resolution: FIXED → INVALID
Yeah I guess so, but I'd prefer to wait for people to ask for this first.
(Reporter)

Comment 7

4 years ago
Would this be the proper place to ask for it? Right now I'm working around this bug using the performance counter, but I've been getting reports that it doesn't work for every browser/application, and having it act like it does in Chrome would fix it.

Comment 8

4 years ago
We are uncertain how best to work around the chrome/firefox difference in behavior here. Any help in

https://github.com/kripken/emscripten/pull/1493

would be welcome.
The emscripten issue seems to have tons of information on it, but it's not obvious to me what you're trying to use currentTime for here.  Can you please elaborate?  I'm interested in the usecase to see if it's something that many apps would want to do.
(Reporter)

Comment 10

4 years ago
My app tries to sync its execution speed based on audio playback. (Think V-Sync but with audio.) This makes audio playback smooth at the cost of an occasional dropped video frame. It allocated about 50-100ms of audio buffers and fills them up. When it can't push more audio into them, it blocks execution until another buffer is free and then continues. For the other audio libraries we support (like ALSA) we can count on the implementation for blocking but I don't know of any similar feature in Web Audio. To fake it, we use busywaits and currentTime to calculate when a buffer *should* finish, then treat it as open for new audio.

I know using busywaits is frowned upon, but we use this because A) there is no guarantee setTimeout will return in a reasonable time for audio playback to not skip and we usually only have to wait a couple milliseconds, and B) this is a compiled application, and there is no easy way to exit from it and then return to the middle of the application. It might be possible with coroutines, but I don't know if emscripten/javascript has the features for that.
Hmm, OK, so first things first, busy-waiting in Javascript is a big no-no.  Basically, JS has run-to-completion semantics, which means that each script will run until it reaches the end of its scope and cannot be interrupted in the mean time by the VM.  This means that if you busy-wait inside JS, then you're basically blocking at least that web page from running any other code, including the rest of your scripts, and the stuff that the browser has to do in order to keep things responsive, etc (such as processing user events.)

Also, it seems like you're trying to reimplement ScriptProcessorNode more or less.  ScriptProcessorNode is a callback based API which lets you receive a callback when Web Audio is ready to precompute N audio frames, and then your code will populate those N frames and hand it off to the browser for rendering to the audio hardware.  That doesn't fix the glitching problem completely, but the browser will always be in a better position in order to try to give you a glitch-free experience, as it can do stuff off of the main thread, and it knows about the precise timing of the audio graph, etc.

I think a better model to implement what you're working towards here would be to use ScriptProcessorNode to generate the audio, and keep track of how many audio frames you've pre-computed, and skip some frames in your requestAnimationFrame() callback if you detect that the rendering is running ahead, etc.  Would that be an option for you?
(Reporter)

Comment 12

4 years ago
I know about javascript not being interruptable, but we never block for more than one video frame so the busyloop is never really noticed by the end user.

It looks like ScriptProcessorNode would work but would require extra checks at the beginning of our main loop to see if we have to abort early and wait for buffers to open. I dislike having to split the audio logic but it seems like there's not a better way right now.
You need to log in before you can comment on or make changes to this bug.