ankidroid / Anki-Android

AnkiDroid: Anki flashcards on Android. Your secret trick to achieve superhuman information retention.
GNU General Public License v3.0
8.66k stars 2.24k forks source link

[Bug] Some sounds are not played from html/javascript #8082

Closed Arthur-Milchior closed 11 months ago

Arthur-Milchior commented 3 years ago
Reproduction Steps
  1. Import http://milchior.fr/anki/metronome.apkg
  2. Open the only card
Expected Result

A metronome, playing 80 beats by minutes, with a strong beat every three beats. As in Anki.

Actual Result

Almost expected result, but some beats missings. Which render the metronome useless.

Debug info

Current master. No personal branches in it. Samsung Tab SM T-515

Research

when I run this, logcat states:

W/AudioManager: Use of stream types is deprecated for operations other than volume control See the documentation of requestAudioFocus() for what to use instead with android.media.AudioAttributes to qualify your playback use case

It seems to do it only on the missing beats.

The actual beats are short enough that they can be played at least four time by second without overlapping (e.g. less than .25 seconds each)

requestAudioFocus is called only in our code in Sound.java#playSoundInternal however, it seems unrelated. Indeed, I added a debug break, ran the debugger, and it did not stop the run. So I assume it's related to webview.

Another solution would be to add a metronome directly in ankidroid, as whiteboard. Maybe other people would like it. However, I am less fan of this idea, simply because I love having parameter in fields

mikehardy commented 3 years ago

Are you able to run this code on mobile devices just as a simple HTML/JS page opened directly in Chrome? This may have nothing to do with AnkiDroid

krmanik commented 3 years ago

I found some useful info here. https://stackoverflow.com/questions/42100658/accuracy-of-settimeout-in-react-native

Comments https://stackoverflow.com/a/42100696/13986833

The delay that you configure for setTimeout and setInterval should never be thought of as an exact delay time. They represent the "minimum" amount of time that you'll wait before the function is executed. This is because the user-agent places the callback into the event queue when the time has elapsed, but if the user-agent is still working on some other task, the callback will sit there.

You should also know that there is a built-in absolute minimum time that you are never going to be able to go under of roughly 9-14ms. This is due to the internals of the user-agent.

mikehardy commented 3 years ago

I just read some info about this (it's an interesting problem, intellectually: precise multi-work-unit scheduling in Android in general - even at the java layer) and precise multi-unit work dispatch from the WebView

I don't think it's feasible in Java or Javascript because of the way the javascript event queue runs in the WebView as @infinyte7 mentioned - even if you posted the next work unit before the first finished (to avoid chaining delay together) the javascript event queue could delay any given work item

And at the Android level the problems would be smaller but you would still see jitter

All of the solutions I've seen involve synthesizing a long sound on the fly by stitching basic "metronome sound parts" together into a really long one then looping on the much longer sound. If you were to have say 10-20 measures of sound together even if there was some jitter as one finished before the next loop started, it wouldn't blow up your scale playing.

How to do that? No idea. Render a library of different metronome times (3/4 time, 4/4 time etc) crossed with bpm settings and then just reference one of these now statically rendered ones in a loop?

Ugly but functional perhaps.

Arthur-Milchior commented 3 years ago

Are you able to run this code on mobile devices just as a simple HTML/JS page opened directly in Chrome? This may have nothing to do with AnkiDroid

Good question. I'll try.

You should also know that there is a built-in absolute minimum time that you are never going to be able to go under of roughly 9-14ms. This is due to the internals of the user-agent.

Thanks. However, the problem is not delayed ticks (it would be a problem). the problem is missing ticks Normally, there is TttTttTtt, one out of three ticks are louder however, at least on my tablet, sometime there is TttT.tTttTt.Ttt.Tt.T where each "." gets replaced by a warning in logcat

How to do that? No idea. Render a library of different metronome times (3/4 time, 4/4 time etc) crossed with bpm settings and then just reference one of these now statically rendered ones in a loop?

I'm really not convinced I'll even be desesperate enough to try to add sound generation in js in anki card.

At least, I now understand why the code of js metronome I found online seemed complex. I thought it was just a lot of boiler plate... :s

github-actions[bot] commented 3 years ago

Hello πŸ‘‹, this issue has been opened for more than 2 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically

dae commented 1 year ago

@Arthur-Milchior still happening?

github-actions[bot] commented 11 months ago

Hello πŸ‘‹, this issue has been opened for more than 3 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically