rserota / wad

Web Audio DAW. Use the Web Audio API for dynamic sound synthesis. It's like jQuery for your ears.
MIT License
1.88k stars 160 forks source link

WAD not Working on IOS #119

Closed frastlin closed 4 years ago

frastlin commented 4 years ago

Hello, I am unable to get WAD working on the latest Safari, Firefox, or Chrome on IOS. Here is my link: https://frastlin.github.io/Nonvisual-Modeling-and-Mapping/magicalbridge Press the speaker test button to try it out. I did some searching around and found: https://stackoverflow.com/questions/46363048/onaudioprocess-not-called-on-ios11/46534088#46534088

It looks like there needs to be some "resuming" of the audio context after user interaction. It looks like webkitAudioContext is handled though.

frastlin commented 4 years ago

I just did some more testing on Chrome on IOS and did the following:

  1. Added a console.log to the handleClick function that plays the sound and the console.log ran just fine.
  2. Changed the sound from an ogg to an mp3, because apparently ogg doesn't work on Safari (and I presume that also holds true for Chrome on IOS?) Once I changed the file from ogg to mp3, I was able to run the file on my desktop, but when I press the button to run on IOS, I get the following error: TypeError: context.createStereoPanner is not a function. context.createStereoPanner is undefined. In: setUpPanningOnPlay line 3493 in wad.js

that.panning.node = context.createStereoPanner()

Is there a function I can call to init Wad after a user event on the page?

rserota commented 4 years ago

Wad.js tries its best to resume the audio context automatically after a user interacts with the page. It shouldn't be necessary, but you can call Wad.audioContext.resume() to manually start the audio context.

For your second point, Safari on iOS does not support StereoPanner nodes. You'll have to use 3D panning instead. Wad is supposed to detect that stereo panning is unavailable and automatically use 3D panning instead, but there was a bug in that code. If you pull down version 4.7.6, panning should work better on iOS.

Thanks for raising this issue. I hope you're enjoying using Wad.js.

frastlin commented 4 years ago

Yes, it works! I wouldn't say the following code pans from the hard-left to hard right, so a warning about pannerNode not working would be very nice:

handleClick(e){
    this.sound.play({
        panning: -1
    })
    setTimeout(this.slide(this.sound, 0.5, 1), 1900)
}

slide(sound, time, end){
    return ()=>sound.setPanning(end, time)
}
frastlin commented 4 years ago

Wait, MDN says PannerNode works on Safari in IOS V14

rserota commented 4 years ago

The PannerNode that you linked is for 3D panning. Most of the properties/methods on that page are for positioning the sound source in 3D space. What you want is the StereoPannerNode, which is not available on iOS Safari.

Since stereo panning isn't actually available, the number you pass in for panning is the horizontal position of the sound source, in 3D space. You can't pan a sound 'hard-left' with 3D panning, because even if a sound is coming from the left side of your head, you still hear it with both ears, it just sounds quieter in your right ear. You can use values larger than 1 or smaller than -1, but that'll also make the sound quieter, since it's further away.

frastlin commented 4 years ago

I don't think the simulated stereo panning function takes into account the user's [Wad.audioContext.listener.positionX.value, Wad.audioContext.listener.positionY.value, Wad.audioContext.listener.positionZ.value] I now hear the sounds on IOS though, which is great!

frastlin commented 4 years ago

OK, I am going crazy, how does one get the Wad.audioContext.listener position in Safari? I've tried: listener.pos, listener.position, listener.x, listener.X, listener, but everything is empty.

rserota commented 4 years ago

It's not you, I think safari is crazy. If you check out the browser compatibility for audio listeners in safari, you can see that safari doesn't support any properties of the audio listener, except for speedOfSound and dopplerFactor, oddly enough.

As a workaround, you can assume that the listener's position starts at (0,0,0), and only changes when you call listener.setPosition(). If you keep track of what you set the position to, I think that should work.

frastlin commented 4 years ago

Could Wad add a Wad.listener object to keep track of the audio listener and make the interface uniform?

rserota commented 4 years ago

Thanks for contributing this feature!