Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Web Workers can't be initialized with NodeJs #662

Closed
1 task done
mlhoutel opened this issue Sep 24, 2021 · 10 comments
Closed
1 task done

Web Workers can't be initialized with NodeJs #662

mlhoutel opened this issue Sep 24, 2021 · 10 comments
Assignees
Labels
area-player Related to the audio playback engine. platform-javascript Related to the JavaScript version of alphaTab state-needs-discussion 💬

Comments

@mlhoutel
Copy link

mlhoutel commented Sep 24, 2021

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

While every needed ressources are loaded in the api object, the player is stuck with:

  • _workerIsReady: false
  • _workerIsReadyForPlayback: false

Expected Behavior

The player should be ready for playing, and the track hud (cursor) should be visible.

When launching the player with api.player.play(), the track sound should be audible.

Steps To Reproduce

  1. Initialize a typescript Vue project with Vuetify
  2. Import @coderline/alphatab with npm
  3. Use alphatab with import { AlphaTabApi, Settings } from "@coderline/alphatab
  4. Initialize a new Settings object
    4.1 Set settings.core engine = html5 and useWorkers = true
    4.2 Set settings.player enablePlayer = true and enableCursor = true
    4.3 Link settings.player.scrollElement to an html element
  5. Initialize a new AlphaTabApi with a context and the settings
  6. Load score with api.load(<Bytes buffer>)
  7. Load sound font with api.loadSoundFont(<Bytes buffer>)
  8. Render with api.renderTracks([api.score.tracks[0]])

Link to jsFiddle, CodePen, Project

https://github.com/mlhoutel/Tablatures

Found in Version

1.3-alpha

Platform

Node.js

Environment

- **OS**: Windows 10 
- **Browser**: Chrome 94.0.4606.61
- **Node**: v16.3.0
- **Webpack**: 4.46.0
- **Vue**: 2.6.11
- **Vuetify**: 2.4.0

I tried multiples versions of the npm package **@coderline/alphatab**, from **1.2.0** to **1.3.0-alpha.131**

Anything else?

Reader component: https://github.com/mlhoutel/Tablatures/blob/main/src/components/TabReader.vue
Log of the API object: at https://mlhoutel.github.io/Tablatures then click on the [TRY IMPORTING] button and load a tab file

@Danielku15
Copy link
Member

Does not look like a bug to me and also does not look really like something specific to NodeJS as you are using alphaTab from the browser. I think what you are missing is that you are not passing any soundfont to alphaTab to initialize.

https://github.com/mlhoutel/Tablatures/blob/0dd5697db13be83725cf02b6e6a276f4ec58fe77/src/components/TabReader.vue#L196-L205

You might want to read through https://alphatab.net/docs/tutorial-web/player

@Danielku15 Danielku15 added state-needs-discussion 💬 area-player Related to the audio playback engine. platform-javascript Related to the JavaScript version of alphaTab labels Sep 26, 2021
@mlhoutel
Copy link
Author

mlhoutel commented Sep 27, 2021

I'm currently loading the soundFont from bytes with api.loadSoundFont (this function called from here).

I also tryed loading the soundfont the way it's given in the doc, with:

settings.player.soundFont = "https://cdn.jsdelivr.net/npm/@coderline/alphatab@latest/dist/soundfont/sonivox.sf2"

But I keep having the same problem.

I may have missed something, because api.loadSoundFont return true but no log is emited in the process.

Also, I tryed to catch when the soundFont is loaded with api.player.soundFontLoaded.on but it seems it never occurs

@Danielku15
Copy link
Member

Can you try to prepare a minimal example of your issue and/or put some debug/unminimized version of your software somewhere? The current version is hardly debuggable in Chrome, the minimized code makes it struggle a lot.

But the code of https://github.com/mlhoutel/Tablatures/blob/0dd5697db13be83725cf02b6e6a276f4ec58fe77/src/components/TabReader.vue#L229-L235 looks suspiciously like the cause of the issue. You're using a raw loader of webpack it seems. Beside the fact that it seems to be deprecated I have a bad feeling converting such binary files into ES modules and then sending them through a TextEncoder to map it back to a Uint8Array. You might be better set loading such large assets manually via Ajax than relying on some webpack embedding.

Additionally you could try to add also a listener into the error and soundFontLoadFailed events and see if alphaTab is reporting some asynchronous errors we cannot see right now. At least from the logs I don't see that a soundfont loading would be triggered or failing with your current setup.

@mlhoutel
Copy link
Author

mlhoutel commented Oct 3, 2021

I tryed do to a minimal exemple fetching the ressources with ajax here: https://jsfiddle.net/mlhoutel/svfdxq16/132/

I don't know if the problem come from the deprecated raw loader, the buffers are ok.

I must have missed something, do I have to call a particular function between the loading of the sf and the rendering for it to be applyed on the player?

@Danielku15
Copy link
Member

If you hook into the soundFontLoadFailed event as described above, you will notice that the bytes of the soundfont are not correct. AlphaTab reports an invalid file. Here a screenshot at the event source:
image

Looking one level higher on what Chrome loads from the Internet, you will notice that the URL does not point to the actual SF2 but the website of JsDelivr is served:
image

The URL you have in your Fiddle is https://www.jsdelivr.com/package/npm/@coderline/alphatab@1.2.1/dist/soundfont/sonivox.sf2 while the correct URL through which JsDelivr serves the file is: https://cdn.jsdelivr.net/npm/@coderline/alphatab@1.2.1/dist/soundfont/sonivox.sf2

This can be obtained through the following menu item on JsDelivr:
image

Regarding the deprecation I saw the notice here: https://v4.webpack.js.org/loaders/raw-loader/
So I guess in your compiled Vue app with the raw loader there is an issue with the SF2 too. Notice this references indicatingthat binary data might not be handled correctly:
https://stackoverflow.com/questions/61964120/how-do-i-load-binary-files-using-webpacks-raw-loader
https://github.com/webpack/webpack/tree/v4.46.0#loaders
https://github.com/webpack-contrib/raw-loader
https://github.com/webpack-contrib/raw-loader/blob/master/src/index.js#L14

@mlhoutel
Copy link
Author

Thank you very much for your help. I managed to get a minimal version working here: https://jsfiddle.net/mlhoutel/svfdxq16/146/.

Unfortunately, I couldn't get it to work in my project, even importing the same code from the minimal example.

I'll keep looking for what's wrong and give news here.

@Danielku15
Copy link
Member

@mlhoutel Any updates regarding your issues? Were you able to solve the problems in your project?

@mlhoutel
Copy link
Author

Unfortunately, I haven't had much time to work on it lately.

I have deployed the minimum functional example of jsfiddle here: https://mlhoutel.github.io/Tablatures/#/test.

I hope to get back to it soon

@Danielku15
Copy link
Member

Danielku15 commented Nov 28, 2021

I had a look and it seems one issue is related to the bundling: https://alphatab.net/docs/getting-started/installation-web#bundling In your setup you are bundling alphaTab which is not well supported due to the spawning of Workers which require Web Worker compatible code. Looking at your code the workers are launched with a wrong URL due to some bundling specific stuff in your environment:

image

I recommend disabling bundling for alphaTab completely and include it as standalone script to avoid any conflicts with other scripts it is bundled with, or that any bundler messes with the initialization routines of alphaTab.

alphaTab requires to run some initialization routine directly after it is included:

  1. On the main thread it needs to find the script file it is contained in to correctly spawn workers. Alternatively you can also configure the alphaTab script file manually to work around this detection.
  2. Within the WebWorker alphaTab needs to setup some global listeners on the worker context to actually handle the messages that are coming from the main thread.
  3. Just like on 2. there are also AudioWorklets spawned (if supported) to handle audio playback in the background.

Considering these aspect I recommend that you first try to get alphaTab running without webpack. If you have it running you are sure alphaTab is working fine without issues. When you then start introducing WebPack step-by-step you will have to find out what is wrong in your setup that makes alphaTab fail to launch. This I cannot do for you in your project, alphaTab is working fine and it is known that bundling causes various issues.

I have it on my agenda to document better how alphaTab can be best integrated into applications using WebPack and Rollup but I still have to dive into this topic myself to give out good recommendations. Until then the recommendation is: Don't merge alphaTab into bundles.

As you can see on this screenshot, alphaTab is initialized from the app.js instead of the chunk-vendors.js (notice the callstack), this means initialization routines are not executed correctly on script load (likely due to the fact that alphaTab is only registered as dependency). You might check the WebPack docs to find out how you can ensure that initialization code of bundles is executed on include of the bundle and not when only resolved.
image

@Danielku15
Copy link
Member

Closing this issue in favor of #759

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-player Related to the audio playback engine. platform-javascript Related to the JavaScript version of alphaTab state-needs-discussion 💬
Projects
None yet
Development

No branches or pull requests

2 participants