-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Uncaught Error: Converting base64 string to bytes failed. #20349
Comments
I encountered the same problem with the same emcc 3.1.46. As a reality check, I tried the example here: https://github.com/GoogleChromeLabs/web-audio-samples/tree/gh-pages/audio-worklet/design-pattern/wasm-supersaw. One way to do this is:
This example works, but if you use the corresponding Makefile in https://github.com/GoogleChromeLabs/web-audio-samples/tree/main/src/audio-worklet/design-pattern/wasm-supersaw to make a new To explore further, since there is a working However, execution proceeds and I now get the error:
and I see that _malloc is defined differently in the 2023 emscripten-generated Is there any example with source code that builds a working audio worklet using wasm? I guess I can revert to emcc 3.1.11 which worked for me in May 2022. |
It looks like your issue with |
@wxfred, can you set a breakpoint on the error to see what the root cause was? Is it that |
It seems like the error is strictly worse than just letting the exception propagate out. For example, we have a report of someone hitting this error but I can't tell what the root cause was: emscripten-core#20349 This try/catch and this error message was part of the original function back emscripten-core#5296 but I don't see any reason for them.
I'm using (recent) Google Chrome Version 117.0.5938.132 (Official Build) (arm64). Not sure what ECMAScript this implies. I found that atob is conditionally defined in synth.wasm.js just above intArrayFromBase in synth.wasm.js, but since the definition (or I guess more properly the binding of symbol atob) takes place in a top-level statement, hoisting does not ensure that things are defined properly. When I manually moved the atob code near the top of synth.wasm.js (just after the "var Module = ..." declaration, but probably doesn't matter), the wasm-supersaw example runs. Why is atob not defined? Near the end of the generated synth.wasm.js, it says:
followed by a conditionally binding of atob, which in simplified form looks like:
Since moving this to the top of the file makes things work, it seems clear that it is defined too late. In fact, looking at the call stack when the error occurs, the computation seems to be initiated by the declaration:
which occurs before the definition of atob(). This explains why atob() is undefined. Reverting to an earlier emscripten seems to require an earlier version of Python3 and I gave up on making it work. The bottom line is I see no way to use emcc 3.1.46 for audio worklets. Can this be? |
Ah, you are trying build and audio worklet. That makes sense why atob would be missing then. I was looking for I guess we need fix the https://github.com/GoogleChromeLabs/web-audio-samples to use that option since you are not the first person to try to build without |
When I added |
The There are some tests for it here: https://github.com/emscripten-core/emscripten/tree/main/test/webaudio |
It seems like the error is strictly worse than just letting the exception propagate out. For example, we have a report of someone hitting this error but I can't tell what the root cause was: emscripten-core#20349 This try/catch and this error message was part of the original function back emscripten-core#5296 but I don't see any reason for them.
It seems like the error is strictly worse than just letting the exception propagate out. For example, we have a report of someone hitting this error but I can't tell what the root cause was: #20349 This try/catch and this error message was part of the original function back #5296 but I don't see any reason for them.
I was off for a week but spent today trying to make a wasm audio worklet. I looked at test/webaudio but I couldn't find any information about it or how to run it. I was able to use instructions in #20410 to compile it, and it generates a test.htm file, but it doesn't work because
Eventually I found "test/runner interactive" to run the test and it actually runs, but things are so wrapped up inside a test framework, that it's very hard to understand. Even the source code is huge and automatically generated. I'm still looking for any example of a web audio wasm program. |
Make sure you're setting the CORS headers in your local web server. |
I think I'm setting CORS headers correctly. At the point where the error occurs, windows.isSecureContext is true (see Feature Detection in https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts, referenced by https://developer.mozilla.org/en-US/docs/Web/API/AudioWorklet), although I'm not certain that's a correct or sufficient test. |
|
Good call. Even though I was using some python to set CORS headers, and I even copied the server code from someone working with audio worklets, crossOriginIsolated was false. It would be great for the emscripten-generated code to simply test or assert conditions for SharedArrayBuffer to exist before referencing it -- even trying to set headers properly and then test for proper conditions can both fail if my experience is any indication, and if the error message directly said CORS headers are not set, it would be much simpler to deal with. OK, back to work, and thanks again. |
@rbdannenberg, is the reference to SharedArrayBuffer coming some emscripten code? Can you see what function it is part of? (I'm trying to add the assertion you mention but I can't see where that is coming from). |
@sbc100, in
Then, in web/test.js, there's a reference to SharedArrayBuffer. |
Now that I can make and run a minimal wasm web audio module, I'm trying to figure out how to invoke a compiled C++ function in the scope of the audio node so that I can get information in and out. The AudioParam feature does not solve the problem because it provides only float-valued input signals and cannot, for example, represent a message such as [pitch, amp, mode, dur] either as input or output. Last year, I was using EMSCRIPTEN_BINDINGS to add a function interface to web audio modules, but the new code generated by -sAUDIO_WORKLET=1 is completely different, and I'm lost figuring out how to call it. For more context, what worked before, based on Google's examples, created an Audio Worklet in Javascript that took audio input as JavaScript arrays, converted to float arrays, invoked a C++ function compiled to WASM to do DSP, converted results back to JavaScript float arrays, and finally returned to the Web Audio caller. It seemed inefficient to have a layer of JavaScript as a wrapper around a WASM function, but it was easy to export more WASM functions, and the JavaScript wrapper could be extended to post messages back and forth with the main JavaScript thread. It looks like the current -sAUDIO_WORKLET=1 scheme hands off the main WASM DSP function directly to Web Audio, so we do not have the intervening layer of JavaScript as an Audio Worklet that we can extend to call other WASM functions. |
With emscripten, the audio thread behaves like a normal desktop audio thread, and you'll use a message passing system, like usual. For example, here is the audio thread for this webpage:
Note that If you need a SPSC queue, then pipewire has a correct one, cubeb has a correct one, and I have one, but many of the others online have subtle synchronization bugs. So you should copy from one of these three sources. |
@ad8e, thanks for the pointer. I was able to see in the referenced javascript that it's as simple as calling Module.fnname -- I thought there was more isolation going on and never even guessed you could directly call into audio worker functions like that. Examples I've seen all posted messages to an audio worklet thread in JavaScript, but maybe that was just to deal with synchronization. I was able to complete the picture with EMSCRIPTEN_BINDINGS and -lembind. I'm writing a guide for anyone seeing this since there are apparently no working source code examples for web audio nodes using C++. |
You can't (or at least, I didn't). If you continue down this road, here was my compile command:
Some of those flags do necessary or helpful things. |
And watch out that it's |
What I meant was you can directly call a function in the Module from outside the worker -- I didn't even think you could access the function or variables inside the module and was imagining relocatable code or base registers that had to be set to cross into the worker space. Online docs I've found sort of leave everything to your imagination and I was imagining much worse. But I totally understand that these functions are not running on the audio thread, and I understand the fifo message passing scheme.
That's interesting because I just created some tests and used this:
to call into a simple WASM audio worklet. It uses
and |
Right; you are using embind and I'm exporting them raw. So you don't need the Module._ syntax. |
I have a context in JavaScript -- how do I pass it to Update: For anyone reading, I found related discussion at #18853 (comment) and posted a similar question there. |
For anyone reading, here are some working examples you might find useful: webaudiowasm-blog19oct2023. |
MODULARIZE can create multiple modules, I think. https://emscripten.org/docs/tools_reference/emcc.html?highlight=modularize No idea about sharing AudioContexts. |
Reiterating what was mentioned by rbdannenberg #20349 (comment): Using build options:
We use the resulting wasm js inside of a javascript AudioWorkletProcessor. The missing Function createWasm() is defined in module.append("var wasmExports = createWasm();\n") The problem is that the atob polyfill has not yet been included when createWasm() is invoked. That doesn't happen until It seems like the atob polyfill should really be instantiated earlier in the wasm js, since createWasm() relies on it. This would certainly solve the problem for us. |
In this configuration the `atob` polfill is required but was not being installed until after `createWasm` which (in the case of SINGLE_FILE) depends on `atob`. See emscripten-core#20349
In this configuration the `atob` polfill is required but was not being installed until after `createWasm` which (in the case of SINGLE_FILE) depends on `atob`. See emscripten-core#20349
I can confirm that #20587 solves our problem. |
@sbc100 I updated to 3.1.48, the new problem appeared
and the difference between @nwsw's and my is ENVIRONMENT, my project is using I compiled my project with these two settings, the result of |
@sbc100 The compiled result of
|
@wxfred if you are trying run the generated code in an audio worklet you currently either need to build See https://github.com/emscripten-core/emscripten/issues/20581for more info. @juj is working on adding a new |
@sbc100 Thanks for reply, yes, i'm using audio worklet. I followed your recommands and tried
I got Although the first way is the solution, i'm curious about, why not just add atob definition when use |
Because web browsers all have It also happens to be missing from the audio worklet environment but we don't (yet) have any way for your to tell emscripten that you are planning on running you code in an audio worklet (other than |
@sbc100 Thanks, learned a lot. |
I was searching for the same answer. What I figured out is you can export similar functions from your C++ code like this: |
Hey @sbc100, I'm hitting the same I'm in a similar situation, compiling via emscripten to produce code that will run in an audio worklet, but I don't want to use |
@nick-thompson can you share the full link command line you are using and also the generated JS code? Any time Another option is that you could simply include the atob polyfill yourself, either using |
It looks like I was falling for the same thing as in #20587. I've updated to the latest Emscripten version and I get past the missing atob error. I am hitting a separate issue now that I don't think is related but I'll write here in case it is; I'm now trying to polyfill a (Edit: I got around it by overwriting |
Please include the following in your bug report:
Version of emscripten/emsdk:
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.46 (1960782)
clang version 18.0.0 (https://github.com/llvm/llvm-project 75501f53624de92aafce2f1da698b249a7293dc7)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: C:\emsdk1\upstream\bin
I downloaded the entire emscripten project from github on 2023/9/28, the compiled xxx.wasmmodule.js by this new version came out a problem after being loaded:
Uncaught Error: Converting base64 string to bytes failed.
I locate the problem and compare it with the emscripten I downloaded on 2022, in xxx.wasmmodule.js, the 2023 version is
the 2022 version (which is no error) is
and
emcc -v
of the 2022 version isthe compile command is like
The text was updated successfully, but these errors were encountered: