Bug 251091

Summary: Distorted audio after getUserMedia when playing with AudioWorkletNode
Product: WebKit Reporter: goldwaving <webkit>
Component: Web AudioAssignee: Chris Dumez <cdumez>
Status: RESOLVED FIXED    
Severity: Major CC: cdumez, eric.carlson, jer.noble, tobias.hegemann, webkit-bug-importer, youennf
Priority: P2 Keywords: InRadar
Version: Safari 16   
Hardware: Unspecified   
OS: iOS 16   
Bug Depends on:    
Bug Blocks: 235317    
Attachments:
Description Flags
Simple test to recreate the audio worklet bug on iOS none

Description goldwaving 2023-01-24 09:08:51 PST
If audio is played with a connected AudioWorkletNode after calling mediaDevices.getUserMedia, audio is badly distorted.

A demonstration of the problem is given here: https://goldwave.com/audio.html

Choose the Get Media button, then choose the Play button.  Audio is badly distorted.  Reload the page, choose the Play button, audio is clear.

This issue occurs on iOS devices and MacOS all fully updated (Safari 16.3)
Comment 1 Radar WebKit Bug Importer 2023-01-31 09:09:18 PST
<rdar://problem/104870451>
Comment 2 Tobias Hegemann 2023-02-03 07:43:38 PST
Created attachment 464823 [details]
Simple test to recreate the audio worklet bug on iOS
Comment 3 Tobias Hegemann 2023-02-03 07:50:27 PST
We also encountered this issue on iOS 16.2

It affects the whole web audio context or its nodes, e.g. OscillatorNode, AudioBufferSourceNode etc.

It can be reproduced when using the first AudioWorklet inside an audio context.

I've attached a simple test to reproduce and deployed it also on gh:

https://delude88.github.io/ios-audioworklet-sample-rate/

Be aware: It is playing sinus waves at full volume.

Besides: When closing and recreating another audio context, the issue is gone (until again the first AudioWorklet is used)
Comment 4 Chris Dumez 2023-02-06 08:47:13 PST
Looking at https://goldwave.com/audio.html, the issue we experience is that the rendering quantum becomes 960 frames instead of 128 frames, which our code doesn't deal with well.

Normally, as soon as WebAudio is in use, we request that CoreAudio uses a rendering quantum of 128. However, it is not working here and that's causing the issue.
Comment 5 Chris Dumez 2023-02-06 09:14:54 PST
It is because of this logic:
```
void RemoteAudioSessionProxyManager::updatePreferredBufferSizeForProcess()
{
#if ENABLE(MEDIA_STREAM)
    if (CoreAudioCaptureSourceFactory::singleton().isAudioCaptureUnitRunning()) {
        CoreAudioCaptureSourceFactory::singleton().whenAudioCaptureUnitIsNotRunning([weakThis = WeakPtr { *this }] {
            if (weakThis)
                weakThis->updatePreferredBufferSizeForProcess();
        });
        return;
    }
#endif
   // ...
```

If we're capturing (which we are here since we called getUserMedia), then we defer the setting of the preferred buffer size (128) until we're done capturing. Since capturing is ongoing, we just keep using 960, which breaks Web Audio.
Comment 6 Chris Dumez 2023-02-06 09:15:34 PST
(In reply to Chris Dumez from comment #5)
> It is because of this logic:
> ```
> void RemoteAudioSessionProxyManager::updatePreferredBufferSizeForProcess()
> {
> #if ENABLE(MEDIA_STREAM)
>     if
> (CoreAudioCaptureSourceFactory::singleton().isAudioCaptureUnitRunning()) {
>        
> CoreAudioCaptureSourceFactory::singleton().
> whenAudioCaptureUnitIsNotRunning([weakThis = WeakPtr { *this }] {
>             if (weakThis)
>                 weakThis->updatePreferredBufferSizeForProcess();
>         });
>         return;
>     }
> #endif
>    // ...
> ```
> 
> If we're capturing (which we are here since we called getUserMedia), then we
> defer the setting of the preferred buffer size (128) until we're done
> capturing. Since capturing is ongoing, we just keep using 960, which breaks
> Web Audio.

This is a regression from Youenn's Bug 235317.
Comment 7 Chris Dumez 2023-02-06 13:58:26 PST
Pull request: https://github.com/WebKit/WebKit/pull/9711
Comment 8 EWS 2023-02-07 09:49:36 PST
Committed 259964@main (87395a602807): <https://commits.webkit.org/259964@main>

Reviewed commits have been landed. Closing PR #9711 and removing active labels.