deskjet / chiptune2.js

much like chiptune.js - but newer and neater
375 stars 52 forks source link

chiptune2.js and IOS #25

Closed bigrck64 closed 6 years ago

bigrck64 commented 6 years ago

Hello !

I'm not able to make chiptune2.js works with iOS 10 :( Is the demo page working for someone on iOS ? http://deskjet.github.io/chiptune2.js/

I know that AudioContext is working fine with iOS, because some other mod js projects are working fine. Examples:

But I need chiptune2.js who have the best lib for mods replay ! If anyone know a fix, please share :)

deskjet commented 6 years ago

Try replacing line 2 in chiptune2.js with

ChiptuneAudioContext = window.AudioContext || window.webkitAudioContext;

Let me know if that works. I don't have a iOS device to test.

bigrck64 commented 6 years ago

Thanks for the quick reply deskjet :) I just try your fix, but unfortunatly it's not changing anything (tested on iOS10 and iOS11), how can I help you to debug ?

bigrck64 commented 6 years ago

haxor.fi use this to create AudioContext, is seems similar, but maybe I could try this syntax ?

// create the web audio context
Modplayer.prototype.createContext = function()
{
  if ( typeof AudioContext !== 'undefined') {
    this.context = new AudioContext();
  } else {
    this.context = new webkitAudioContext();
  }
deskjet commented 6 years ago

You can always try :)

However, xm.js creates the context like I suggested earlier. So It's probably not a problem with the AudioContext.

Can you try the desktop version of Safari? It would be easier to debug than a mobile device. If it doesn't work, please open the Web Inspector and make a screenshot of the Console tab. There should be error messages in there.

If Safari on desktop is not affected by the problem, please try remote debugging with your iOS device. Here is a guide to set it up: https://developer.telerik.com/featured/a-concise-guide-to-remote-debugging-on-ios-android-and-windows-phone/#ios Again, I'm interested in the error displayed on the console.

bigrck64 commented 6 years ago

Ok, let's try first with Safari 10.1 on macOS Sierra 10.12 :)

I have the latest chiptune2.js project with the following modification at http://mods.abime.net/chip2/ ChiptuneAudioContext = window.AudioContext || window.webkitAudioContext; It's not working as expected, and the javascript error is the following: image image

deskjet commented 6 years ago

Ok. I think this is caused by a bug in webkit. Webkit doesn't auto-select a suitable buffer-size and fails creating the ScriptProcessor.

Please try this.context.createScriptProcessor(2048, 0, 2); to create the ScriptProcessor.

Webkit bug tracker: https://bugs.webkit.org/show_bug.cgi?id=173022

bigrck64 commented 6 years ago

Good, this fix is working well for Safari 10.1 on macOS Sierra 10.12, thanks ! Unfortunatly, it's now good enough for iOS 10 :) I will try iOS11 and if it's not OK I will connect usb cable and try to remote debug mobile safari.

bigrck64 commented 6 years ago

on iOS10, this time I tried to directly load the player with this simple code: image And I got one error into libopenmpt.js:1:17188 ! image

deskjet commented 6 years ago

Thank you for investigating. This could be a hard one. Maybe a iOS/emscripten incompatibility. Would you mind trying the latest libopenmpt build from https://builds.openmpt.org/builds/auto/libopenmpt/dev.js/ ? You just have to replace js/libopenmpt.js and libopenmpt.js.mem with the ones from the zip file.

2017-10-31 14:05 GMT+01:00 RCK notifications@github.com:

always on iOS10, this time I tried to directly load the player with this simple code: [image: image] https://user-images.githubusercontent.com/9383270/32225171-7edb35f2-be44-11e7-8a7d-5cd3b5f790bf.png And I got one error into libopenmpt.js:1:17188 ! [image: image] https://user-images.githubusercontent.com/9383270/32225106-4ceeed0e-be44-11e7-9fd9-e6ffefb15ee6.png

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/deskjet/chiptune2.js/issues/25#issuecomment-340755882, or mute the thread https://github.com/notifications/unsubscribe-auth/ACYqlAlG8L7-mPHB8fsIZwY0MvpBM2W2ks5sxxsOgaJpZM4QFrQF .

bigrck64 commented 6 years ago

Hum, I tried the latest build libopenmpt-0.4.0-pre.1+r9172 and have this error on iOS10: image Do you think I should try other branch ?

bigrck64 commented 6 years ago

I confirmed the problem on iOS10 and iOS11. Just to check emscripten, I alsot tested chiptune.js (libxmp.js) on iOS10, and it's working well ! http://deskjet.github.io/chiptune.js/

What version of emscripten did you use to generate the 2015 libxmp.js file ? Maybe I can test the same version over libopenmpt and see if it works on iOS ?

bigrck64 commented 6 years ago

Just to be sure, I tested the following autobuild of libopenmpt and always have one error in .js on iOS Safari: libopenmpt-0.2.6919 libopenmpt-0.3.0+release libopenmpt-0.4.0-pre.2+r9206

Maybe I can try to build it myself with "-s ASSERTIONS=1" to have more information ?

iOS Safari Console Error with libopenmpt-0.2.6919.js : image

deskjet commented 6 years ago

Compiling libopenmpt to JavaScript is actually not that hard. You need to install the Emscripten SDK. You can follow the Getting Started guide on https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html.

Once the SDK is installed, grab the libopenmpt source (makefile), make sure emcc is in your current $PATH and compile using make CONFIG=emscripten.

If you want to change compilation flags you can create your own emscripten-debug.mk configuration file in build\make\. I suggest you copy the emscripten config, disable optimizations (remove -O2) and add -s ASSERTIONS=1 and -g4 for assertions, debug information and source maps.
To use your new debug configuration compile using make CONFIG=emscripten-debug. This will generate very large (and slow) .js files.

Thanks for your effort. I hope we can figure this out.

bigrck64 commented 6 years ago

Ok, let's try :

deskjet commented 6 years ago

No error message with the debug build on iOS Safari? That's wired. The prep time message indicates that the js is loaded and ready.

You can reduce file size by lowering the lowering the debug information level (e.g. -g3, -g2 ...). I hope it helps to figure this out. Perhaps some combination of flags (-O and -g) runs on iOS Safari works or gives a meaningful error message.

Since this seems not to be directly related to the chiptune.js wrapper around libopenmpt, you might want to get in touch with the libopenmpt developers. They have a forum (https://forum.openmpt.org) and a bug tracker (https://bugs.openmpt.org).

bigrck64 commented 6 years ago

Yep you are right, I will continue this over openmpt.org :) With the addition of the -O2 tag, the debug build size decrease to 12Mo, which let me reload the remote web inspector with no problem. 1 time over 4, I have the following error message on iOS, but most of time, no error message, and no sound :( image

deskjet commented 6 years ago

So emscripten is not initialized yet when calling libopenmpt?

There is something about that in the Emscripten FAQ. https://kripken.github.io/emscripten-site/docs/getting_started/FAQ.html#how-can-i-tell-when-the-page-is-fully-loaded-and-it-is-safe-to-call-compiled-functions

I think we have to wait for the onRuntimeInitialized callback before calling any libopenmpt functions.

Update: Can you try this code in your simplified test page?

Module.onRuntimeInitialized = function() {
        var player;
        player = new ChiptuneJsPlayer(new ChiptuneJsConfig(-1));
        player.load('tunes/Art_of_Chrome.xm', function(buffer) {
          player.play(buffer);
        });
    }
bigrck64 commented 6 years ago

Thanks for your permanent support Deskjet :) I added the onRuntimeInitialized() to http://mods.abime.net/test/, and it's better because now I don't have any more errors into webinspector JS console.

The only problem is that I don't have any JS errors, but don't have any sound on iOS Safari ! and I don't really know what I can do more to find out the problem :( Maybe I can test other compilation option ? like -g3 or -g2, but without -O2 ? I'm not really sure who can help us now.

deskjet commented 6 years ago

I think found something.

On iOS, the Web Audio API requires sounds to be triggered from an explicit user action, such as a tap. Calling noteOn() from an onload event will not play sound.

https://developer.apple.com/library/content/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/PlayingandSynthesizingSounds/PlayingandSynthesizingSounds.html#//apple_ref/doc/uid/TP40009523-CH6-SW5

So we need a play button for iOS.

bigrck64 commented 6 years ago

Thanks for this idea ! I tried the following html code with no success on iOS10 (with 3.1 in release mode) When I click PLAY I see the network loading the .xm but that's all, no sound and no error after :( Do you think this play button js code is okay for Apple ? image

deskjet commented 6 years ago

The AudioContext is still in suspended state. Try adding player.context.resume() after the call to player.play().

photonstorm commented 6 years ago

Here you go, I've fixed chiptune2.js so it works properly on iOS. I've tested iOS10 and iOS11 and it plays fine in both of them. Just drop this file in and change the index.html to point to it and it'll just work.

https://gist.github.com/photonstorm/87df3c595879cb1620ed6d8a232e213a

photonstorm commented 6 years ago

Also, can confirm this works with libopenmpt-0.4.0-pre2 as well (I tested with r9233 but unless it drastically changes all releases should be safe!)

deskjet commented 6 years ago

Thank you, photonstorm! I'll merge this when bigrck64 confirms it works for him.

bigrck64 commented 6 years ago

Awesome photonstorm ! it's working perfectly :) Deskjet: on iOS, you still need to have a "PLAY" button, but once clicked it's working flawlessly with photonstorm's change to chiptune2.js !

I will now close this issue, and give you both a big thanks for your investigation time on this ! Cheers

photonstorm commented 6 years ago

No worries :) It could do a lot more internal tests for when things fail (especially in the code that creates the Module object) but essentially it works and that's what matters!