Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Audio distortion (crackling) on iOS devices

Discussion in 'WebGL' started by RamblingCoder, May 18, 2021.

  1. RamblingCoder

    RamblingCoder

    Joined:
    Jul 13, 2013
    Posts:
    16
    Our app is built for webGL and works great in the browser on a PC or Mac. However, when we run it in any browser on an iPhone or iPad, it starts getting some significant sound distortion after running for a few minutes. It introduces a popping/clicking sound, that gets progressively louder the longer it plays.

    Has anyone else experienced this, and if so, were you able to find a solution?
     
  2. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    944
    This is known to Apple at https://bugs.webkit.org/show_bug.cgi?id=222098 , but unfortunately their engineers have not been able to work on the bug even though they have been able to reproduce it.

    If you have a project that fails, it would be great if you can share a link directly in that bug, to maybe help get their engineers attention.
     
  3. pierresusset

    pierresusset

    Joined:
    Feb 7, 2009
    Posts:
    60
    Hello Jukka,

    I am also facing the same problem on a project and I have tried many things to solve it.
    On my side, I managed to solve it by modifying the audio.js file present in
    /2020.3.13f1/PlaybackEngines/WebGLSupport/BuildTools/lib/Audio.js

    I realized that the SetVolume function is called at each frame even if the volume is not modified. I don't know if this is normal but it seems useless.
    So I added a check of the current gain and the desired gain in order to limit the modification of the latter.
    I also change the way the gain is set (don't use the setValueAtATime as I'm not sure it is really useful).
    Code (JavaScript):
    1. if(WEBAudio.audioInstances[channelInstance].gain.gain.value != v){
    2.             WEBAudio.audioInstances[channelInstance].gain.gain.value = v;
    3.         }
    After building my project with this change, I don't have the crackling sound anymore. I have also made the same check for the setPosition and setListenerPosition and Orientation but this changes was not enough to remove the bug.

    Could you advise us on why the SetVolume is called every frame and why the audio.js use the SetValueAtATime to set the volume ?

    Have a nice day,

    Pierre
     
  4. roka

    roka

    Joined:
    Sep 12, 2010
    Posts:
    584
  5. pierresusset

    pierresusset

    Joined:
    Feb 7, 2009
    Posts:
    60
    @roka,

    I was experiencing this issue only on iOS but it seems to be the same symptoms.
    I just check the 2021.1.14 version and I see that the SetPosition bug has been resolved but not the one from SetVolume.

    Here is the audio.js changes :
    Code (JavaScript):
    1. JS_Sound_SetPosition: function (channelInstance, x, y, z)
    2. {
    3.     if (WEBAudio.audioWebEnabled == 0)
    4.         return;
    5.  
    6.     var channel = WEBAudio.audioInstances[channelInstance];
    7.     // Work around Chrome performance bug https://bugs.chromium.org/p/chromium/issues/detail?id=1133233
    8.     // by only updating the PannerNode position if it has changed.
    9.     // See case 1270768.
    10.     if (channel.x != x || channel.y != y || channel.z != z) {
    11.         channel.panner.setPosition(x, y, z);
    12.         channel.x = x;
    13.         channel.y = y;
    14.         channel.z = z;
    15.     }
    16. },
    and
    Code (JavaScript):
    1. JS_Sound_SetVolume: function (channelInstance, v)
    2. {
    3.     if (WEBAudio.audioWebEnabled == 0)
    4.         return;
    5.  
    6.     try {
    7.         if(WEBAudio.audioInstances[channelInstance].gain.gain.value != v){
    8.             WEBAudio.audioInstances[channelInstance].gain.gain.value = v;
    9.         }
    10.     } catch(e) {
    11.         console.error('Invalid audio volume ' + v + ' specified to WebAudio backend!');
    12.     }
    13. },
     
    PieterAlbers and graycoder2020 like this.
  6. roka

    roka

    Joined:
    Sep 12, 2010
    Posts:
    584
    Thank you
     
  7. pierresusset

    pierresusset

    Joined:
    Feb 7, 2009
    Posts:
    60
    @roka, does it solved your crackling sound too ?
    @jukka_j, did you had the time to take a look at it ?

    All the best,

    Pierre
     
  8. roka

    roka

    Joined:
    Sep 12, 2010
    Posts:
    584
    I do not have tested yet, my holiday is coming, so i will be able to test only the second week of august.
    I think that jukka will not be available for few months as i have hear but i don't know why.
     
  9. BaspooGameDev

    BaspooGameDev

    Joined:
    Oct 3, 2016
    Posts:
    11

    you are my hero I ran into this problem a long time ago. and never fixed it
    I find you frequently answering useful questions in the forums. You are such a kind person.
     
  10. radiatoryang

    radiatoryang

    Joined:
    Jul 7, 2014
    Posts:
    19
    Just FYI anyone coming across this thread -- as of 2021.3.11f1 at least, these have been merged in officially to WebGLSupport ... Audio.js now looks like this

    (and I still get a lot of audio crackling that builds up over time)

    Code (JavaScript):
    1.     /**
    2.      * Set volume of channel
    3.      * @param {number} volume Volume of channel
    4.      */
    5.     channel.setVolume = function (volume) {
    6.         // Work around WebKit bug https://bugs.webkit.org/show_bug.cgi?id=222098
    7.         // Updating volume only if it changes reduces sound distortion over time.
    8.         // See case 1350204, 1348348 and 1352665
    9.         if (this.gain.gain.value == volume) {
    10.             return;
    11.         }
    12.  
    13.         this.gain.gain.value = volume;
    14.     }
    15.  
    16.     /**
    17.      * Set the 3D position of the audio channel
    18.      * @param {number} x
    19.      * @param {number} y
    20.      * @param {number} z
    21.      */
    22.     channel.setPosition = function (x, y, z) {
    23.         var p = this.panner;
    24.  
    25.         // Work around Chrome performance bug https://bugs.chromium.org/p/chromium/issues/detail?id=1133233
    26.         // by only updating the PannerNode position if it has changed.
    27.         // See case 1270768.
    28.         if (p.positionX) {
    29.             // Use new properties if they exist ...
    30.             if (p.positionX.value !== x) p.positionX.value = x;
    31.             if (p.positionY.value !== y) p.positionY.value = y;
    32.             if (p.positionZ.value !== z) p.positionZ.value = z;
    33.         } else if (p._x !== x || p._y !== y || p._z !== z) {
    34.             // ... or the deprecated set function if they don't (and shadow cache the set values to avoid re-setting later)
    35.             p.setPosition(x, y, z);
    36.             p._x = x;
    37.             p._y = y;
    38.             p._z = z;
    39.         }
    40.     }
     
    Last edited: Dec 9, 2022