diff --git a/404.html b/404.html new file mode 100644 index 0000000..f8414f0 --- /dev/null +++ b/404.html @@ -0,0 +1,3 @@ + +404 Not Found +

404 Not Found

diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..fd7e50e --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +maia-sdr.org \ No newline at end of file diff --git a/about/index.html b/about/index.html new file mode 100644 index 0000000..3f84006 --- /dev/null +++ b/about/index.html @@ -0,0 +1,204 @@ + + + + + + About | Maia SDR + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + +
+ + +
+ +
+ + +
+ +
About Maia SDR
+

Maia SDR is an open-source project started by Daniel +Estévez in 2022 with the goal of developing radio +applications whose signal processing runs mainly on an FPGA. In this sense, Maia +SDR is an FPGA-based SDR (see the FAQ if you find this term +strange).

+

There are several motivations that led to this project:

+
    +
  1. There is a thriving open-source SDR community, which develops great pieces of +software. However, not many people are doing FPGA development (though there are +some notable exceptions).
  2. +
  3. There is an open-source FPGA community doing amazing work and projects. Most +of these projects are not related to radio or signal processing, and the +interaction between the FGPA and SDR communities is minimal (with a few +exceptions).
  4. +
  5. Affordable handheld and portable radios are not very flexible and do not +offer much variety in terms of how to explore the RF spectrum and have fun with +it. A PC running SDR software is vastly superior in capabilities to a compact +solution.
  6. +
  7. Portable solutions should use FPGA processing as much as possible in order to +save power and offer capabilities which are not possible with embedded CPUs.
  8. +
+

With these ideas in mind, Maia SDR starts as a project with the long term goal +of building an open-source compact/portable radio that offers high flexibility +in the same sense that SDR software does, and that uses an FPGA for most of its +signal processing. The work-in-progress project will hopefully serve as a +stepping stone that people can extend or use as a base for their projects, and +will bring more FPGA development to the SDR community and more collaboration +between the FPGA and SDR communities.

+

The ideal hardware for this project would be an affordable board (or stack of +boards) with a relatively capable FPGA that supports an open-source toolchain, +an RFIC of some sort, some kind of RISC-V SoC or microcontroller, and UI +hardware (touchscreen, etc.). Unfortunately, something like this does not +currently exist. This is a chicken and egg problem, in the sense that there are +not enough open-source FPGA designs yet to make this hardware interesting, so +the hardware does not get developed, and so there is no hardware to develop the +FPGA designs for. If I started by developing the hardware, I would probably +never finish. Instead of dreaming about this hardware, a good way to kickstart +these activities is to focus on an existing, affordable, and widely available +hardware that can serve as a "good enough replacement".

+

I have decided to focus on the ADALM +Pluto +because it is a very popular and common SDR, and it has a fairly capable Zynq +FPGA + ARM SoC. Together with a smartphone for the UI, this pair of devices give +a portable solution for which already many hobbyists have the required +hardware. This platform serves to develop a "product" that can have useful +features right from the start, rather than having something in a +work-in-progress state that people cannot use until (and if) it is finished.

+

Maia SDR attempts to bring more interest in FPGA delopment for radio +applications, and to serve as a starting point for other projects, by dealing +with things which are usually entry barriers (such as how to move data around +with DMAs or how to compute an FFT). It also serves as a playground to explore +novel technologies and ideas.

+

The HDL code of Maia SDR is written in +Amaranth, which is a Python-based +HDL and toolchain. This is one of the flagship projects of the open-source FPGA +community, and there have already been some small projects using Amaranth for +radio applications (see an SDR transmitter tutorial at EU GNU Radio +days and a post about how to use +Amaranth for radio +astronomy).

+

The software of Maia SDR runs on the Zynq ARM CPU and serves to control the FPGA +and to provide an interface to a smartphone (or other device) connected to the +Pluto. It does so by spawning an HTTP server that has a web application as UI, a +RESTful API for control, and uses WebSockets to stream data. The software is +written in Rust using asynchronous programming. I +think that Rust is a very good language for systems development, and has a +wonderful open-source community behind. Perhaps this choice of technology will +give at some point a link between Maia SDR and +FutureSDR, which is a very interesting SDR runtime +project that is also implemented in asynchronous Rust.

+

The UI of Maia SDR is a web application that uses WebGL2 to render the waterfall +display. It is implemented in Rust using WebAssembly.

+ + +
+ + + +
+ + + + + + + diff --git a/faq/index.html b/faq/index.html new file mode 100644 index 0000000..4c23646 --- /dev/null +++ b/faq/index.html @@ -0,0 +1,179 @@ + + + + + + FAQ | Maia SDR + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + +
+ + + + +
+ + + +
+ + +
+ +
FAQ
+

Why the name "Maia SDR"?

+

Maia is a star in the +Pleiades cluster. I chose the name +because I like how it sounds, and because it is related to astronomy. The name +vaguely hints at radio astronomy, which is a topic dear to me. Even though Maia +SDR has not been developed with radio astronomy in mind as a potential use case, +it could potentially be of interest to the radio astronomy FPGA community.

+

Isn't "FPGA-based SDR" a misnomer?

+

Sure. If most of the digital signal processing is done in FPGA, it is not done +in software. I know and partly share comments in the SDR community about how the +term "SDR" is often used inappropriately and has become somewhat of a +buzzword. In this sense, calling Maia SDR an "SDR" is not very +appropriate. However, I cannot think of a better term. I do not know of a word +other than SDR that evokes the same ideas in terms of functionality, hardware +devices, community, etc.

+

Also, in a certain sense I think that "SDR" is not a very bad name for Maia +SDR. As a project, it strives to explore in the future concepts such as +relatively fast-synthesis using open source FPGA toolchains, on demand +reconfiguration, and other concepts related to flexibility in terms of +functionality. In this sense, Maia SDR has more in common with a software radio +application than with a silicon radio. Ultimately, the flexibility might matter +more than whether the DSP computations are done in LUTs or in an ALU.

+

How is "Maia SDR" pronounced?

+

Maia is pronounced in English as /ˈmeɪə/, but I often use the Spanish +pronunciation /'maja/ (English my-ah). This is closer to the original Greek and Latin +pronunciations. You can use whichever you prefer.

+ + +
+ + + +
+ + + + + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..487652f --- /dev/null +++ b/index.html @@ -0,0 +1,219 @@ + + + + + + Maia SDR + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ +
+ + +
+
+ Maia SDR +
+
+ An open-source FPGA-based SDR project focusing on the ADALM Pluto +
+
+ Star + Fork +
+
+
+ A screenshot of Maia SDR, showing a waterfall in the web browser +
+
+ More ⇩ +
+ +
+ + + +
+ + + + +
+ +
+ +
+ Demo +
+ + +
+ Overview +
+ + +
+ +
+ + +
+ +

Demo

+ +

Overview

+

Maia SDR currently provides a firmware image for the ADALM +Pluto +with the following functionality:

+ +

Though this is still limited functionality (more will come in the future), it +already provides a "minimum viable product" that demonstrates some features that +cannot be easily accomplished with other portable and affordable solutions.

+

Here is a deployment diagram of Maia SDR used with a portable device running a +web browser.

+

Maia SDR deployment diagram

+

The FPGA design (maia-hdl) is written in +Amaranth and includes:

+ +

A software application (maia-httpd) written in asynchronous Rust runs on the +Zynq ARM CPU. It provides:

+ +

The UI is a web application (maia-wasm) written in Rust with WebAssembly. It +uses WebGL2 to render the waterfall (see the waterfall demo).

+ + +
+ + + +
+ + + + + + + diff --git a/installation/index.html b/installation/index.html new file mode 100644 index 0000000..b893264 --- /dev/null +++ b/installation/index.html @@ -0,0 +1,331 @@ + + + + + + Installation | Maia SDR + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + +
+ + + + +
+ + + +
+ + +
+ +
Installation instructions
+

These instructions describe how to install and use Maia SDR on an +ADALM Pluto +that is running the default ADI firmware image. It is also possible to follow +the same instructions with a Pluto that has the Maia SDR firmware image, in +order to update it with a newer version of Maia SDR.

+

Download the firmware image

+

Go to the +latest Maia SDR Pluto firmware release +and download the file plutosdr-fw-maia-sdr-v[version].zip. This zip file contains the +firmware images that are used below (such as pluto.frm).

+

Flash the firmware image

+

The firmware image can be flashed in the same way as the default ADI +firmware. See the +upgrade instructions +in the +ADI Pluto firmware wiki. +The Maia SDR firmware images include the mass storage device, in the same way as +the default ADI images, so it is possible (and recommended) to use the Mass +Storage Update method with the file pluto.frm.

+

Set up the u-boot environment

+

Maia SDR requires an additional Linux kernel command line parameter in +comparison to the default ADI firmware, because it uses the +uio_pdrv_genirq +kernel module. This kernel command line parameter is configured through the +u-boot environment.

+

The u-boot version included in the Maia SDR boot.frm and boot.dfu already +includes the modified environment variables as defaults. However, flashing +boot.frm or boot.dfu is not recommended for inexperienced users, because an +error during the bootloader flashing could brick the device (JTAG access will be +needed to recover it).

+

A safer way to modify these environment variables is to use fw_setenv. Doing +this does not interfere with the default ADI firmware image and can be done at any time, +before or after flashing a Maia SDR firmware image. Moreover, the environment +variables are not modified when pluto.frm is flashed, so it is only necessary +to follow these steps once. Afterwards, newer versions of the Maia SDR +pluto.frm image can be flashed without the need to use fw_setenv.

+

All the following commands should be run in the Pluto via ssh or serial.

+

To check if the u-boot environment variables have been modified already to allow +Maia SDR to be used, we can run

+
fw_printenv | grep uio_pdrv_genirq
+
+

This will print a few lines of text if the variables have been modified (in +which case it is not necessary to do anything else), and +nothing if not (in which case it is necessary to follow the next steps in this +section).

+

The following three commands are used to modify the required u-boot environment +variables to include the uio_pdrv_genirq.of_id=uio_pdrv_genirq kernel command +line parameter. When copying and pasting, take note that the commands are quite +long. It is necessary to enter the commands one at a time in the Pluto shell +because there is a character count limit.

+
fw_setenv ramboot_verbose 'adi_hwref;echo Copying Linux from DFU to RAM... && run dfu_ram;if run adi_loadvals; then echo Loaded AD936x refclk frequency and model into devicetree; fi; envversion;setenv bootargs console=ttyPS0,115200 maxcpus=${maxcpus} rootfstype=ramfs root=/dev/ram0 rw earlyprintk clk_ignore_unused uio_pdrv_genirq.of_id=uio_pdrv_genirq uboot="${uboot-version}" && bootm ${fit_load_address}#${fit_config}'
+
+fw_setenv qspiboot_verbose 'adi_hwref;echo Copying Linux from QSPI flash to RAM... && run read_sf && if run adi_loadvals; then echo Loaded AD936x refclk frequency and model into devicetree; fi; envversion;setenv bootargs console=ttyPS0,115200 maxcpus=${maxcpus} rootfstype=ramfs root=/dev/ram0 rw earlyprintk clk_ignore_unused uio_pdrv_genirq.of_id=uio_pdrv_genirq uboot="${uboot-version}" && bootm ${fit_load_address}#${fit_config} || echo BOOT failed entering DFU mode ... && run dfu_sf'
+
+fw_setenv qspiboot 'set stdout nulldev;adi_hwref;test -n $PlutoRevA || gpio input 14 && set stdout serial@e0001000 && sf probe && sf protect lock 0 100000 && run dfu_sf;  set stdout serial@e0001000;itest *f8000258 == 480003 && run clear_reset_cause && run dfu_sf; itest *f8000258 == 480007 && run clear_reset_cause && run ramboot_verbose; itest *f8000258 == 480006 && run clear_reset_cause && run qspiboot_verbose; itest *f8000258 == 480002 && run clear_reset_cause && exit; echo Booting silently && set stdout nulldev; run read_sf && run adi_loadvals; envversion;setenv bootargs console=ttyPS0,115200 maxcpus=${maxcpus} rootfstype=ramfs root=/dev/ram0 rw quiet loglevel=4 clk_ignore_unused uio_pdrv_genirq.of_id=uio_pdrv_genirq uboot="${uboot-version}" && bootm ${fit_load_address}#${fit_config} || set stdout serial@e0001000;echo BOOT failed entering DFU mode ... && sf protect lock 0 100000 && run dfu_sf'
+
+

After these commands have been entered, it is possible to use fw_printenv as +indicated above to check that the changes have been applied correctly. It is +necessary to reboot the Pluto (for instance by using the reboot command) in +order for the changes to be effective.

+

Set up 1R1T AD9364 mode

+

Maia SDR assumes that the Pluto is configured for 1R1T (one receive channel, one +transmit channel) mode and that an AD9364 device (frequency range 70 MHz - 6 +GHz, 61.44 Msps maximum sampling rate) is used. These options are stored in the +u-boot environment and can be modified using fw_setenv as indicated in the +updating to the AD9364 +instructions in the +customizing the Pluto ADI wiki.

+

Check that fw_printenv returns the appropriate values:

+
# fw_printenv attr_name attr_val mode
+attr_name=compatible
+attr_val=ad9364
+mode=1r1t
+
+

Update the configuration if necessary:

+
fw_setenv attr_name compatible
+fw_setenv attr_val ad9364
+fw_setenv mode 1r1t
+
+

It is necessary to reboot the Pluto for these changes to be effective. As +indicated in the previous section, the u-boot environment variables are +preserved even when a new pluto.frm firmware image is flashed, so these +changes need to be applied only once.

+

Configure the Pluto USB Ethernet

+

As in the default ADI firmware image, the Ethernet compatibility mode needs to +be configured depending on the operating system that will use the Pluto USB +Ethernet. In general, CDC-ECM should be used for Android, CDC-NCM for iOS and +macOS, and RNDIS for Windows. See the +ADI wiki instructions to change the USB Ethernet.

+

More information about how to use the Pluto USB Ethernet from an Android device +is available in the +Connecting the Pluto SDR to an Android phone +blog post. One of the key steps is to use

+
fw_setenv ipaddr 192.168.xx.1
+
+

to change the IP of the Pluto to one in the same subnet used by the Android +Ethernet tethering.

+

The Maia SDR wiki +contains more information about Android support in different devices.

+

In some Android devices, the IP that is used for Ethernet tethering may be +chosen randomly each time that the device is rebooted. An address from the +subnet 192.168.xxx.0/24 is chosen, where xxx can change. To deal with this +situation, the Maia SDR firmware has an option that is used to assign multiple +IP addresses to the usb0 interface of the Pluto: 192.168.0.1/24, +192.168.1.1/24, 192.168.2.1/24, ..., 192.168.254.1/24. One of these +address will be on the correct subnet.

+

This option can be enabled with

+
fw_setenv ipaddrmulti 1
+
+

It can be disabled with

+
fw_setenv ipaddrmulti 0
+
+

or

+
fw_setenv ipaddrmulti
+
+

A reboot is necessary to apply these changes.

+

Open Maia SDR in the web browser and install it as a web app

+

Maia SDR listens on TCP port 8000 using HTTP. Once the Pluto has booted up and a +USB Ethernet or other network connection to the Pluto has been established, we +can open http://192.168.2.1:8000 in a web browser +(replace the IP address by the appropriate address of the Pluto if you have +modified it).

+

In mobile operating systems such as Android and iOS, web applications (also +called progressive web apps, or PWAs) can be installed as an icon to the home +screen. It is recommended to do this for Maia SDR, because the web application +will not display the web browser toolbar (which occupies precious screen real +state) when accessed through the home screen icon. +MDN has some instructions about how to +install a web +app +in several web browsers.

+

It is not necessary to install Maia SDR as a web app again if the Maia SDR +firmware image is updated.

+

Differences between the Maia SDR firmware and the default ADI firmware

+

The Maia SDR firmware is based on the ADI firmware. The main changes are the +following:

+ +

This means that a Pluto running the Maia SDR firmware cannot be used to +send/receive IQ samples to an SDR application running on a PC (using either USB +libiio or USB Ethernet libiio), because the required FPGA components (DMAs, +FIFOs...) are missing. The default ADI firmware needs to be installed again to +use the Pluto "normally".

+

On the other hand, from the software perspective there are little changes. The +IP address and other settings are configured in the same way, the same root +password is used, and almost the same packages are available in the +rootfs. Users can modify the rootfs to add additional packages or configurations +in the same way as for the default ADI image.

+ + +
+ + + +
+ + + + + + + diff --git a/juice.css b/juice.css new file mode 100644 index 0000000..1f718aa --- /dev/null +++ b/juice.css @@ -0,0 +1 @@ +.text-center{text-align:center}.pos-absolute{right:0;left:0;position:absolute}.box-shadow{box-shadow:0 2px 10px 2px var(--shadow-color)}.heading-text{font-family:"Fira Sans", sans-serif;font-size:32px;font-weight:600;padding:10px 0 25px 0;color:var(--primary-text-color)}h1,.title-text{font-family:"Fira Sans", sans-serif;font-size:25px;font-weight:500;color:var(--primary-text-color);border-left:var(--primary-color) 8px solid;padding-left:10px}h2,.subtitle-text{font-family:"Fira Sans", sans-serif;font-size:20px;font-weight:500;color:var(--primary-text-color)}.text{font-family:"Fira Sans", sans-serif;font-size:18px;font-weight:400;line-height:26px;letter-spacing:0.2px;color:var(--primary-text-color)}.subtext{font-family:"Fira Sans", sans-serif;font-size:16px;font-weight:400;letter-spacing:0.1px}.content{padding:0 40px;display:flex;flex-direction:column;overflow-x:auto}.content pre{overflow-x:auto;padding:1.25em 1.5em;white-space:pre;word-wrap:normal;background-color:var(--code-background-color);color:var(--code-color);font-size:.875em;font-family:monospace}.content code{background-color:var(--code-background-color);color:var(--code-color);font-size:.875em;font-weight:normal;padding:0.25em 0.5em;font-family:monospace}.content pre code{padding:0}.content a{color:var(--primary-link-color)}.content a:hover{text-decoration:underline}.content blockquote{border-left:#e2dede 8px solid;margin:0;background-color:#f2f1f0;padding:0 20px}body{padding:0;margin:0;box-sizing:border-box;background-color:var(--secondary-color);display:flex;flex-direction:column;min-height:100vh}a{text-decoration:none}ul{margin-top:0.5rem}ul>li{padding:0.3rem 0}p>img{width:100%;height:auto}header{background-color:var(--primary-color);color:var(--primary-text-color);padding:20px 50px;display:flex;align-items:center;justify-content:space-between}.logo{font-family:"Alfa Slab One", serif;font-size:32px;color:var(--primary-text-color);display:flex;align-items:center;margin:0 40px}.logo img{width:60px;margin:0 25px}.nav-item{margin:0 10px;text-decoration:none;font-size:18px;font-weight:bold}.nav-item:hover{color:var(--primary-text-color-over);text-decoration:underline}.hero{display:flex;align-items:center;justify-content:space-evenly;height:100vh;background-color:var(--primary-color);overflow-x:hidden;padding:0 40px}.hero .explore-more{position:absolute;bottom:20px;cursor:pointer}main{display:flex;padding:50px 100px;flex-grow:1}main .toc{max-width:260px;min-width:240px}main .toc-item{padding:10px 20px;color:#424242}main .toc-item a,main .toc-item-child a{color:var(--secondary-text-color)}main .toc-item a:hover,main .toc-item-child a:hover{cursor:pointer;text-decoration:underline}main .toc-item a.active,main .toc-item-child a.active{color:var(--toc-highlight-text-color)}main .toc-item-child{padding:0 30px 5px;color:#424242}.toc-sticky{border-radius:3px;border-top:5px solid var(--primary-color);background-color:var(--toc-background-color);position:sticky;position:-webkit-sticky;position:-moz-sticky;position:-ms-sticky;position:-o-sticky;top:10px;padding:10px 0 20px;max-height:100vh;overflow:auto}footer{padding:50px;display:flex;flex-direction:column;justify-content:center;align-items:center;background-color:#202020;color:#fcfcfc}footer a{color:#fcfcfc;text-decoration:underline}@media screen and (min-width: 1280px){.content{max-width:60%;min-width:800px}}@media screen and (max-width: 768px){header{padding:10px 30px;flex-direction:column;align-items:center;justify-content:center}.logo{font-size:28px;margin:10px}.logo img{width:45px;margin:0 10px 0 0}.nav-item{margin:0 5px;font-size:14px}.hero{padding:40px 30px}main{padding:30px}.content{padding:0}.explore-more,.toc{display:none}}.logo{font-family:"Fira Sans", sans-serif;font-weight:600}.hero .hero-div{padding:0 5rem;flex:1}.hero-image{flex:0 55%}@media screen and (max-width: 768px){.hero .hero-div{padding:0 2rem}.hero-image{display:none}}.content pre{padding-top:0;padding-bottom:0}footer small{margin-top:2.5px;margin-bottom:2.5px} diff --git a/maia-icon-128x128.png b/maia-icon-128x128.png new file mode 100644 index 0000000..299096f Binary files /dev/null and b/maia-icon-128x128.png differ diff --git a/maia-icon-180x180.png b/maia-icon-180x180.png new file mode 100644 index 0000000..4e0a894 Binary files /dev/null and b/maia-icon-180x180.png differ diff --git a/maia-icon-192x192.png b/maia-icon-192x192.png new file mode 100644 index 0000000..81f2362 Binary files /dev/null and b/maia-icon-192x192.png differ diff --git a/maia-icon-32x32.png b/maia-icon-32x32.png new file mode 100644 index 0000000..779c3a0 Binary files /dev/null and b/maia-icon-32x32.png differ diff --git a/maia-sdr-deployment.svg b/maia-sdr-deployment.svg new file mode 100644 index 0000000..9f7c992 --- /dev/null +++ b/maia-sdr-deployment.svg @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ADALM Pluto Zynq 7010 + + + + + + FPGA + + + + + + ARM CPU + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Portable device + + + + + + Web browser + + + + + + USB Ethernet + + + + + + + + + + + + + + + + + + + + + + + + + + + maia-hdl + + + + + + maia-http + + + + + + maia-wasm + + + + + + + + \ No newline at end of file diff --git a/maia-sdr-screenshot.jpg b/maia-sdr-screenshot.jpg new file mode 100644 index 0000000..5cf200b Binary files /dev/null and b/maia-sdr-screenshot.jpg differ diff --git a/normalize.css b/normalize.css new file mode 100644 index 0000000..192eb9c --- /dev/null +++ b/normalize.css @@ -0,0 +1,349 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..aa366d2 --- /dev/null +++ b/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Disallow: +Allow: / +Sitemap: https://maia-sdr.org/sitemap.xml diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..49b92e5 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,18 @@ + + + + https://maia-sdr.org/ + + + https://maia-sdr.org/about/ + + + https://maia-sdr.org/faq/ + + + https://maia-sdr.org/installation/ + + + https://maia-sdr.org/waterfall-demo/ + + diff --git a/waterfall-demo/index.html b/waterfall-demo/index.html new file mode 100644 index 0000000..fbfb86a --- /dev/null +++ b/waterfall-demo/index.html @@ -0,0 +1,149 @@ + + + + + + Waterfall demo | Maia SDR + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + +
+ + +
+ +
+ + +
+ +
Demo of the Maia SDR waterfall
+ +

Below is a demo of the WebGL2 waterfall included in +maia-wasm. The +waterfall data has been generated from the +GRCon 2022 CTF signal identification challenge SigMF recording +and is stored as a JPEG file in order to reduce its size. Some JPEG artifacts are visible. +This only happens with this demo, and not with Maia SDR.

+

+ + +
+ + + +
+ + + + + + + diff --git a/waterfall_example/LICENSE-APACHE b/waterfall_example/LICENSE-APACHE new file mode 100644 index 0000000..1b5ec8b --- /dev/null +++ b/waterfall_example/LICENSE-APACHE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/waterfall_example/LICENSE-MIT b/waterfall_example/LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/waterfall_example/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/waterfall_example/README.md b/waterfall_example/README.md new file mode 100644 index 0000000..190525a --- /dev/null +++ b/waterfall_example/README.md @@ -0,0 +1,45 @@ +# maia-wasm waterfall example + +This crate contains an example of how to use the maia-wasm WebGL2 waterfall in a +standalone way. The spectrum data used in this example is stored in a JPEG file, +which is embedded into the wasm file. The JPEG is decoded when the waterfall is +created, and a closure called using `setInterval()` puts the spectrum data in the +waterfall one line at a time. + +Note that since the spectrum data is stored in JPEG format, there are visible +JPEG artifacts, specially in the noise floor and around narrowband +signals. These artifacts are only present in this example, and not in the normal +usage of maia-wasm. + +## Building + +The crate can be built with [wasm-pack](https://rustwasm.github.io/wasm-pack/) +by doing +``` +wasm-pack build -t web +``` + +## Running + +A HTTP server needs to be spawned in the crate root directory and the +`index.html` file must be loaded in a web browser. To run an HTTP server, it is possible to use +``` +python3 -m http.server +``` + +## License + +Licensed under either of + + * Apache License, Version 2.0 + ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) + * MIT license + ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/waterfall_example/package.json b/waterfall_example/package.json new file mode 100644 index 0000000..6f3b44e --- /dev/null +++ b/waterfall_example/package.json @@ -0,0 +1,32 @@ +{ + "name": "waterfall-example", + "collaborators": [ + "Daniel Estevez " + ], + "description": "Maia SDR waterfall example", + "version": "0.1.2", + "license": "MIT OR Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/maia-sdr/maia-sdr/" + }, + "files": [ + "waterfall_example_bg.wasm", + "waterfall_example.js", + "waterfall_example.d.ts", + "LICENSE-APACHE", + "LICENSE-MIT" + ], + "module": "waterfall_example.js", + "homepage": "https://maia-sdr.org/", + "types": "waterfall_example.d.ts", + "sideEffects": [ + "./snippets/*" + ], + "keywords": [ + "SDR", + "FPGA", + "wasm", + "WebGL2" + ] +} \ No newline at end of file diff --git a/waterfall_example/waterfall_example.d.ts b/waterfall_example/waterfall_example.d.ts new file mode 100644 index 0000000..f6ee42e --- /dev/null +++ b/waterfall_example/waterfall_example.d.ts @@ -0,0 +1,67 @@ +/* tslint:disable */ +/* eslint-disable */ +/** +* Initialize the wasm module. +* +* This function is set to run as soon as the wasm module is instantiated. It +* applies some settings that are needed for all kinds of usage of +* `maia-wasm`. For instance, it sets a panic hook using the +* [`console_error_panic_hook`] crate. +*/ +export function start(): void; +/** +* Starts the maia-wasm web application. +* +* This function starts the maia-wasm application. It should be called from +* JavaScript when the web page is loaded. It sets up all the objects and +* callbacks that keep the application running. +*/ +export function maia_wasm_start(): void; +/** +* @param {string} canvas +*/ +export function make_waterfall(canvas: string): void; + +export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; + +export interface InitOutput { + readonly memory: WebAssembly.Memory; + readonly start: () => void; + readonly maia_wasm_start: (a: number) => void; + readonly make_waterfall: (a: number, b: number, c: number) => void; + readonly __wbindgen_malloc: (a: number, b: number) => number; + readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; + readonly __wbindgen_export_2: WebAssembly.Table; + readonly _dyn_core__ops__function__Fn_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h9fedf4ecdfaef9fb: (a: number, b: number) => number; + readonly _dyn_core__ops__function__Fn_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h84a73a6c05432c52: (a: number, b: number) => void; + readonly wasm_bindgen__convert__closures__invoke1__h691e8e97cf9508d4: (a: number, b: number, c: number) => void; + readonly wasm_bindgen__convert__closures__invoke1_mut__h2114f6ea6548549c: (a: number, b: number, c: number) => void; + readonly wasm_bindgen__convert__closures__invoke1_mut__h220f418a7eac6941: (a: number, b: number, c: number) => void; + readonly wasm_bindgen__convert__closures__invoke0_mut__h77d7e03a9c772f50: (a: number, b: number) => void; + readonly __wbindgen_free: (a: number, b: number, c: number) => void; + readonly __wbindgen_exn_store: (a: number) => void; + readonly wasm_bindgen__convert__closures__invoke2_mut__h3c7d769e0d744879: (a: number, b: number, c: number, d: number) => void; + readonly __wbindgen_add_to_stack_pointer: (a: number) => number; + readonly __wbindgen_start: () => void; +} + +export type SyncInitInput = BufferSource | WebAssembly.Module; +/** +* Instantiates the given `module`, which can either be bytes or +* a precompiled `WebAssembly.Module`. +* +* @param {SyncInitInput} module +* +* @returns {InitOutput} +*/ +export function initSync(module: SyncInitInput): InitOutput; + +/** +* If `module_or_path` is {RequestInfo} or {URL}, makes a request and +* for everything else, calls `WebAssembly.instantiate` directly. +* +* @param {InitInput | Promise} module_or_path +* +* @returns {Promise} +*/ +export default function __wbg_init (module_or_path?: InitInput | Promise): Promise; diff --git a/waterfall_example/waterfall_example.js b/waterfall_example/waterfall_example.js new file mode 100644 index 0000000..49cb024 --- /dev/null +++ b/waterfall_example/waterfall_example.js @@ -0,0 +1,1183 @@ +let wasm; + +const heap = new Array(128).fill(undefined); + +heap.push(undefined, null, true, false); + +function getObject(idx) { return heap[idx]; } + +let heap_next = heap.length; + +function dropObject(idx) { + if (idx < 132) return; + heap[idx] = heap_next; + heap_next = idx; +} + +function takeObject(idx) { + const ret = getObject(idx); + dropObject(idx); + return ret; +} + +function addHeapObject(obj) { + if (heap_next === heap.length) heap.push(heap.length + 1); + const idx = heap_next; + heap_next = heap[idx]; + + heap[idx] = obj; + return idx; +} + +const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); + +if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; + +let cachedUint8Memory0 = null; + +function getUint8Memory0() { + if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) { + cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8Memory0; +} + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); +} + +let WASM_VECTOR_LEN = 0; + +const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } ); + +const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' + ? function (arg, view) { + return cachedTextEncoder.encodeInto(arg, view); +} + : function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; +}); + +function passStringToWasm0(arg, malloc, realloc) { + + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8Memory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8Memory0().subarray(ptr + offset, ptr + len); + const ret = encodeString(arg, view); + + offset += ret.written; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +function isLikeNone(x) { + return x === undefined || x === null; +} + +let cachedInt32Memory0 = null; + +function getInt32Memory0() { + if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) { + cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); + } + return cachedInt32Memory0; +} + +let cachedFloat64Memory0 = null; + +function getFloat64Memory0() { + if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) { + cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer); + } + return cachedFloat64Memory0; +} + +function debugString(val) { + // primitive types + const type = typeof val; + if (type == 'number' || type == 'boolean' || val == null) { + return `${val}`; + } + if (type == 'string') { + return `"${val}"`; + } + if (type == 'symbol') { + const description = val.description; + if (description == null) { + return 'Symbol'; + } else { + return `Symbol(${description})`; + } + } + if (type == 'function') { + const name = val.name; + if (typeof name == 'string' && name.length > 0) { + return `Function(${name})`; + } else { + return 'Function'; + } + } + // objects + if (Array.isArray(val)) { + const length = val.length; + let debug = '['; + if (length > 0) { + debug += debugString(val[0]); + } + for(let i = 1; i < length; i++) { + debug += ', ' + debugString(val[i]); + } + debug += ']'; + return debug; + } + // Test for built-in + const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); + let className; + if (builtInMatches.length > 1) { + className = builtInMatches[1]; + } else { + // Failed to match the standard '[object ClassName]' + return toString.call(val); + } + if (className == 'Object') { + // we're a user defined class or Object + // JSON.stringify avoids problems with cycles, and is generally much + // easier than looping through ownProperties of `val`. + try { + return 'Object(' + JSON.stringify(val) + ')'; + } catch (_) { + return 'Object'; + } + } + // errors + if (val instanceof Error) { + return `${val.name}: ${val.message}\n${val.stack}`; + } + // TODO we could test for more things here, like `Set`s and `Map`s. + return className; +} + +function makeClosure(arg0, arg1, dtor, f) { + const state = { a: arg0, b: arg1, cnt: 1, dtor }; + const real = (...args) => { + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + try { + return f(state.a, state.b, ...args); + } finally { + if (--state.cnt === 0) { + wasm.__wbindgen_export_2.get(state.dtor)(state.a, state.b); + state.a = 0; + + } + } + }; + real.original = state; + + return real; +} +function __wbg_adapter_24(arg0, arg1) { + const ret = wasm._dyn_core__ops__function__Fn_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h9fedf4ecdfaef9fb(arg0, arg1); + return takeObject(ret); +} + +function __wbg_adapter_27(arg0, arg1) { + wasm._dyn_core__ops__function__Fn_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h84a73a6c05432c52(arg0, arg1); +} + +function __wbg_adapter_32(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures__invoke1__h691e8e97cf9508d4(arg0, arg1, addHeapObject(arg2)); +} + +function makeMutClosure(arg0, arg1, dtor, f) { + const state = { a: arg0, b: arg1, cnt: 1, dtor }; + const real = (...args) => { + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + const a = state.a; + state.a = 0; + try { + return f(a, state.b, ...args); + } finally { + if (--state.cnt === 0) { + wasm.__wbindgen_export_2.get(state.dtor)(a, state.b); + + } else { + state.a = a; + } + } + }; + real.original = state; + + return real; +} +function __wbg_adapter_39(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures__invoke1_mut__h2114f6ea6548549c(arg0, arg1, arg2); +} + +function __wbg_adapter_44(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures__invoke1_mut__h220f418a7eac6941(arg0, arg1, addHeapObject(arg2)); +} + +function __wbg_adapter_47(arg0, arg1) { + wasm.wasm_bindgen__convert__closures__invoke0_mut__h77d7e03a9c772f50(arg0, arg1); +} + +function handleError(f, args) { + try { + return f.apply(this, args); + } catch (e) { + wasm.__wbindgen_exn_store(addHeapObject(e)); + } +} +function __wbg_adapter_66(arg0, arg1, arg2, arg3) { + wasm.wasm_bindgen__convert__closures__invoke2_mut__h3c7d769e0d744879(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3)); +} + +/** +* Initialize the wasm module. +* +* This function is set to run as soon as the wasm module is instantiated. It +* applies some settings that are needed for all kinds of usage of +* `maia-wasm`. For instance, it sets a panic hook using the +* [`console_error_panic_hook`] crate. +*/ +export function start() { + wasm.start(); +} + +/** +* Starts the maia-wasm web application. +* +* This function starts the maia-wasm application. It should be called from +* JavaScript when the web page is loaded. It sets up all the objects and +* callbacks that keep the application running. +*/ +export function maia_wasm_start() { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + wasm.maia_wasm_start(retptr); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + if (r1) { + throw takeObject(r0); + } + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } +} + +/** +* @param {string} canvas +*/ +export function make_waterfall(canvas) { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(canvas, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.make_waterfall(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + if (r1) { + throw takeObject(r0); + } + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } +} + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +function __wbg_get_imports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbg_new_abda76e883ba8a5f = function() { + const ret = new Error(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) { + const ret = getObject(arg1).stack; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) { + let deferred0_0; + let deferred0_1; + try { + deferred0_0 = arg0; + deferred0_1 = arg1; + console.error(getStringFromWasm0(arg0, arg1)); + } finally { + wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); + } + }; + imports.wbg.__wbindgen_object_drop_ref = function(arg0) { + takeObject(arg0); + }; + imports.wbg.__wbg_call_cb65541d95d71282 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).call(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_length_d7327c75a759af37 = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbindgen_memory = function() { + const ret = wasm.memory; + return addHeapObject(ret); + }; + imports.wbg.__wbg_buffer_085ec1f694018c4f = function(arg0) { + const ret = getObject(arg0).buffer; + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_d086a66d1c264b3f = function(arg0) { + const ret = new Float32Array(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_6146c51d49a2c0df = function(arg0, arg1, arg2) { + getObject(arg0).set(getObject(arg1), arg2 >>> 0); + }; + imports.wbg.__wbg_reportValidity_2557db89c42243ce = function(arg0) { + const ret = getObject(arg0).reportValidity(); + return ret; + }; + imports.wbg.__wbg_valueAsNumber_c5b647430655b1f5 = function(arg0) { + const ret = getObject(arg0).valueAsNumber; + return ret; + }; + imports.wbg.__wbg_new_43f1b47c28813cbd = function(arg0, arg1) { + try { + var state0 = {a: arg0, b: arg1}; + var cb0 = (arg0, arg1) => { + const a = state0.a; + state0.a = 0; + try { + return __wbg_adapter_66(a, state0.b, arg0, arg1); + } finally { + state0.a = a; + } + }; + const ret = new Promise(cb0); + return addHeapObject(ret); + } finally { + state0.a = state0.b = 0; + } + }; + imports.wbg.__wbg_alert_8c9ebcc791f5eaa8 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).alert(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_reportValidity_78a677e191a3c09b = function(arg0) { + const ret = getObject(arg0).reportValidity(); + return ret; + }; + imports.wbg.__wbg_value_c45528fab757534f = function(arg0, arg1) { + const ret = getObject(arg1).value; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_showModal_cb447f81d81c7b41 = function() { return handleError(function (arg0) { + getObject(arg0).showModal(); + }, arguments) }; + imports.wbg.__wbg_value_9423da9d988ee8cf = function(arg0, arg1) { + const ret = getObject(arg1).value; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_innerHTML_7957d4fb76221e5a = function(arg0, arg1) { + const ret = getObject(arg1).innerHTML; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_checked_5ccb3a66eb054121 = function(arg0) { + const ret = getObject(arg0).checked; + return ret; + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_6da8e527659b86aa = function(arg0, arg1, arg2) { + const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_texImage2D_07240affd06971e9 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + getObject(arg0).texImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, getObject(arg9)); + }, arguments) }; + imports.wbg.__wbg_generateMipmap_96d73b7b931b4cbf = function(arg0, arg1) { + getObject(arg0).generateMipmap(arg1 >>> 0); + }; + imports.wbg.__wbg_error_788ae33f81d3b84b = function(arg0) { + console.error(getObject(arg0)); + }; + imports.wbg.__wbindgen_cb_drop = function(arg0) { + const obj = takeObject(arg0).original; + if (obj.cnt-- == 1) { + obj.a = 0; + return true; + } + const ret = false; + return ret; + }; + imports.wbg.__wbg_localStorage_dbac11bd189e9fa0 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).localStorage; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_getItem_ed8e218e51f1efeb = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = getObject(arg1).getItem(getStringFromWasm0(arg2, arg3)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return addHeapObject(ret); + }; + imports.wbg.__wbg_removeItem_02359267b311cb85 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).removeItem(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_setTimeout_9434bde3b3009c3e = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).setTimeout(getObject(arg1)); + return ret; + }, arguments) }; + imports.wbg.__wbg_setInterval_5676632e4a58b04e = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).setInterval(getObject(arg1), arg2); + return ret; + }, arguments) }; + imports.wbg.__wbg_setonchange_60b11e3966320226 = function(arg0, arg1) { + getObject(arg0).onchange = getObject(arg1); + }; + imports.wbg.__wbg_setonclick_4e9c9187dbc33082 = function(arg0, arg1) { + getObject(arg0).onclick = getObject(arg1); + }; + imports.wbg.__wbg_setvalue_4c8843ef308f3553 = function(arg0, arg1, arg2) { + getObject(arg0).value = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_onchange_6673f2af8dd263c8 = function(arg0) { + const ret = getObject(arg0).onchange; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_setvalueAsNumber_5cc5143f6e5b0e6b = function(arg0, arg1) { + getObject(arg0).valueAsNumber = arg1; + }; + imports.wbg.__wbg_setvalue_1f95e61cbc382f7f = function(arg0, arg1, arg2) { + getObject(arg0).value = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_setchecked_e5a50baea447b8a8 = function(arg0, arg1) { + getObject(arg0).checked = arg1 !== 0; + }; + imports.wbg.__wbg_getElementById_cc0e0d931b0d9a28 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getElementById(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_instanceof_HtmlSelectElement_75d8a9ac3b088f08 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLSelectElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_instanceof_HtmlButtonElement_6bd3bcb5370764a5 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLButtonElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_instanceof_HtmlDialogElement_d32c74ed0c18dd2e = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLDialogElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_instanceof_HtmlInputElement_31b50e0cf542c524 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLInputElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_setinnerHTML_b089587252408b67 = function(arg0, arg1, arg2) { + getObject(arg0).innerHTML = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_setclassName_e7c93281fe6d80d6 = function(arg0, arg1, arg2) { + getObject(arg0).className = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_new_b51585de1b234aff = function() { + const ret = new Object(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithstrandinit_cad5cd6038c7ff5d = function() { return handleError(function (arg0, arg1, arg2) { + const ret = new Request(getStringFromWasm0(arg0, arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_headers_b439dcff02e808e5 = function(arg0) { + const ret = getObject(arg0).headers; + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_b34caba58723c454 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).set(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_fetch_336b6f0cb426b46e = function(arg0, arg1) { + const ret = getObject(arg0).fetch(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_instanceof_Response_fc4327dbfcdf5ced = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Response; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_ok_e3d8d84e630fd064 = function(arg0) { + const ret = getObject(arg0).ok; + return ret; + }; + imports.wbg.__wbg_status_ac85a3142a84caa2 = function(arg0) { + const ret = getObject(arg0).status; + return ret; + }; + imports.wbg.__wbg_setdisabled_56245c5cae114be3 = function(arg0, arg1) { + getObject(arg0).disabled = arg1 !== 0; + }; + imports.wbg.__wbg_call_01734de55d61e11d = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).call(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_text_a667ac1770538491 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).text(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbindgen_string_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'string' ? obj : undefined; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_fetch_25c13b73a41a6660 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).fetch(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_activeElement_2cf540415b6fcd5c = function(arg0) { + const ret = getObject(arg0).activeElement; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_id_0626af592e3fcac5 = function(arg0, arg1) { + const ret = getObject(arg1).id; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_type_0f4fee5293059bbf = function(arg0, arg1) { + const ret = getObject(arg1).type; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_type_bf6f116ae4f128a3 = function(arg0, arg1) { + const ret = getObject(arg1).type; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_now_9c5990bda04c7e53 = function() { + const ret = Date.now(); + return ret; + }; + imports.wbg.__wbg_setfont_3d2943420717ac87 = function(arg0, arg1, arg2) { + getObject(arg0).font = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_measureText_b5b4d14da44a57c5 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).measureText(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_width_5b91f61af2d11adc = function(arg0) { + const ret = getObject(arg0).width; + return ret; + }; + imports.wbg.__wbg_setwidth_a667a942dba6656e = function(arg0, arg1) { + getObject(arg0).width = arg1 >>> 0; + }; + imports.wbg.__wbg_setheight_a747d440760fe5aa = function(arg0, arg1) { + getObject(arg0).height = arg1 >>> 0; + }; + imports.wbg.__wbg_settextAlign_2601a967e1935930 = function(arg0, arg1, arg2) { + getObject(arg0).textAlign = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_settextBaseline_02044836ed42433f = function(arg0, arg1, arg2) { + getObject(arg0).textBaseline = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_clearRect_517d3360d8be8a55 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).clearRect(arg1, arg2, arg3, arg4); + }; + imports.wbg.__wbg_setfillStyle_401fa583a1c8863c = function(arg0, arg1) { + getObject(arg0).fillStyle = getObject(arg1); + }; + imports.wbg.__wbg_fillText_ba4313e6835ce7ea = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).fillText(getStringFromWasm0(arg1, arg2), arg3, arg4); + }, arguments) }; + imports.wbg.__wbg_pixelStorei_f3a24990aa352fc7 = function(arg0, arg1, arg2) { + getObject(arg0).pixelStorei(arg1 >>> 0, arg2); + }; + imports.wbg.__wbg_texImage2D_fbf003c99e11d9ad = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + getObject(arg0).texImage2D(arg1 >>> 0, arg2, arg3, arg4 >>> 0, arg5 >>> 0, getObject(arg6)); + }, arguments) }; + imports.wbg.__wbg_bindVertexArray_8863a216d7b0a339 = function(arg0, arg1) { + getObject(arg0).bindVertexArray(getObject(arg1)); + }; + imports.wbg.__wbg_pointerId_701aab7b4fb073ff = function(arg0) { + const ret = getObject(arg0).pointerId; + return ret; + }; + imports.wbg.__wbg_getUniformLocation_9f6eb60c560a347b = function(arg0, arg1, arg2, arg3) { + const ret = getObject(arg0).getUniformLocation(getObject(arg1), getStringFromWasm0(arg2, arg3)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_uniform1i_d2e61a6a43889648 = function(arg0, arg1, arg2) { + getObject(arg0).uniform1i(getObject(arg1), arg2); + }; + imports.wbg.__wbg_uniform1f_88379f4e2630bc66 = function(arg0, arg1, arg2) { + getObject(arg0).uniform1f(getObject(arg1), arg2); + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_69193e31c844b792 = function(arg0, arg1, arg2) { + const ret = new Float32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_texSubImage2D_d2841ded12a8aa66 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + getObject(arg0).texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, getObject(arg9)); + }, arguments) }; + imports.wbg.__wbg_useProgram_3683cf6f60939dcd = function(arg0, arg1) { + getObject(arg0).useProgram(getObject(arg1)); + }; + imports.wbg.__wbg_activeTexture_799bf1387e911c27 = function(arg0, arg1) { + getObject(arg0).activeTexture(arg1 >>> 0); + }; + imports.wbg.__wbg_bindTexture_92d6d7f8bff9531e = function(arg0, arg1, arg2) { + getObject(arg0).bindTexture(arg1 >>> 0, getObject(arg2)); + }; + imports.wbg.__wbg_drawElements_a9529eefaf2008bd = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).drawElements(arg1 >>> 0, arg2, arg3 >>> 0, arg4); + }; + imports.wbg.__wbg_requestAnimationFrame_d082200514b6674d = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).requestAnimationFrame(getObject(arg1)); + return ret; + }, arguments) }; + imports.wbg.__wbg_getContext_7c5944ea807bf5d3 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).getContext(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_WebGl2RenderingContext_f921526c513bf717 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof WebGL2RenderingContext; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_getContextAttributes_7232382011fdcbe9 = function(arg0) { + const ret = getObject(arg0).getContextAttributes(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_set_092e06b0f9d71865 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2)); + return ret; + }, arguments) }; + imports.wbg.__wbg_clientWidth_51ec21e3189f5656 = function(arg0) { + const ret = getObject(arg0).clientWidth; + return ret; + }; + imports.wbg.__wbg_clientHeight_09ec0b524d59c367 = function(arg0) { + const ret = getObject(arg0).clientHeight; + return ret; + }; + imports.wbg.__wbg_devicePixelRatio_f9de7bddca0eaf20 = function(arg0) { + const ret = getObject(arg0).devicePixelRatio; + return ret; + }; + imports.wbg.__wbg_getParameter_55b36a787dbbfb74 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).getParameter(arg1 >>> 0); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbindgen_number_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'number' ? obj : undefined; + getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_enable_195891416c520019 = function(arg0, arg1) { + getObject(arg0).enable(arg1 >>> 0); + }; + imports.wbg.__wbg_blendFunc_533de6de45b80a09 = function(arg0, arg1, arg2) { + getObject(arg0).blendFunc(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_createElement_4891554b28d3388b = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).createElement(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_HtmlCanvasElement_da5f9efa0688cf6d = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLCanvasElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_instanceof_CanvasRenderingContext2d_bc0a6635c96eca9b = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof CanvasRenderingContext2D; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_performance_2c295061c8b01e0b = function(arg0) { + const ret = getObject(arg0).performance; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createTexture_1bf4d6fec570124b = function(arg0) { + const ret = getObject(arg0).createTexture(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_texParameteri_85dad939f62a15aa = function(arg0, arg1, arg2, arg3) { + getObject(arg0).texParameteri(arg1 >>> 0, arg2 >>> 0, arg3); + }; + imports.wbg.__wbg_style_3801009b2339aa94 = function(arg0) { + const ret = getObject(arg0).style; + return addHeapObject(ret); + }; + imports.wbg.__wbg_setProperty_b95ef63ab852879e = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).setProperty(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_setonresize_b6c484bfc913a868 = function(arg0, arg1) { + getObject(arg0).onresize = getObject(arg1); + }; + imports.wbg.__wbg_setonwheel_4dd5875900789cd5 = function(arg0, arg1) { + getObject(arg0).onwheel = getObject(arg1); + }; + imports.wbg.__wbg_setonpointerdown_7c30c19e47de9d76 = function(arg0, arg1) { + getObject(arg0).onpointerdown = getObject(arg1); + }; + imports.wbg.__wbg_setonpointercancel_060d09d2902d9841 = function(arg0, arg1) { + getObject(arg0).onpointercancel = getObject(arg1); + }; + imports.wbg.__wbg_setonpointerout_d69dd87ee6086f97 = function(arg0, arg1) { + getObject(arg0).onpointerout = getObject(arg1); + }; + imports.wbg.__wbg_setonpointerleave_82ef754f86af3d56 = function(arg0, arg1) { + getObject(arg0).onpointerleave = getObject(arg1); + }; + imports.wbg.__wbg_setonpointerup_dfdac754cb3ce002 = function(arg0, arg1) { + getObject(arg0).onpointerup = getObject(arg1); + }; + imports.wbg.__wbg_setonpointermove_a51a67a5a4e4aeaa = function(arg0, arg1) { + getObject(arg0).onpointermove = getObject(arg1); + }; + imports.wbg.__wbg_document_f7ace2b956f30a4f = function(arg0) { + const ret = getObject(arg0).document; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_location_56243dba507f472d = function(arg0) { + const ret = getObject(arg0).location; + return addHeapObject(ret); + }; + imports.wbg.__wbg_hostname_b77e5e70d6ff6236 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).hostname; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_port_1b2b1249cacfca76 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).port; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_data_ab99ae4a2e1e8bc9 = function(arg0) { + const ret = getObject(arg0).data; + return addHeapObject(ret); + }; + imports.wbg.__wbg_instanceof_ArrayBuffer_39ac22089b74fddb = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof ArrayBuffer; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_now_0cfdc90c97d0c24b = function(arg0) { + const ret = getObject(arg0).now(); + return ret; + }; + imports.wbg.__wbg_new_b66404b6322c59bf = function() { return handleError(function (arg0, arg1) { + const ret = new WebSocket(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_setbinaryType_096c70c4a9d97499 = function(arg0, arg1) { + getObject(arg0).binaryType = takeObject(arg1); + }; + imports.wbg.__wbg_setonmessage_809f60b68c2a6938 = function(arg0, arg1) { + getObject(arg0).onmessage = getObject(arg1); + }; + imports.wbg.__wbg_setonclose_4210cf3908b79b31 = function(arg0, arg1) { + getObject(arg0).onclose = getObject(arg1); + }; + imports.wbg.__wbg_setItem_d002ee486462bfff = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).setItem(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_viewport_fad1ce9e18f741c0 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).viewport(arg1, arg2, arg3, arg4); + }; + imports.wbg.__wbg_preventDefault_24104f3f0a54546a = function(arg0) { + getObject(arg0).preventDefault(); + }; + imports.wbg.__wbg_deltaY_64823169afb0335d = function(arg0) { + const ret = getObject(arg0).deltaY; + return ret; + }; + imports.wbg.__wbg_clientX_1a480606ab0cabaa = function(arg0) { + const ret = getObject(arg0).clientX; + return ret; + }; + imports.wbg.__wbg_getBoundingClientRect_ac9db8cf97ca8083 = function(arg0) { + const ret = getObject(arg0).getBoundingClientRect(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_x_6c8af74c3b4d8c09 = function(arg0) { + const ret = getObject(arg0).x; + return ret; + }; + imports.wbg.__wbg_clientY_9c7878f7faf3900f = function(arg0) { + const ret = getObject(arg0).clientY; + return ret; + }; + imports.wbg.__wbg_createProgram_4eaf3b97b5747a62 = function(arg0) { + const ret = getObject(arg0).createProgram(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_attachShader_47256b6b3d42a22e = function(arg0, arg1, arg2) { + getObject(arg0).attachShader(getObject(arg1), getObject(arg2)); + }; + imports.wbg.__wbg_linkProgram_33998194075d71fb = function(arg0, arg1) { + getObject(arg0).linkProgram(getObject(arg1)); + }; + imports.wbg.__wbg_getProgramParameter_35522a0bfdfaad27 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getProgramParameter(getObject(arg1), arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_boolean_get = function(arg0) { + const v = getObject(arg0); + const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2; + return ret; + }; + imports.wbg.__wbg_getProgramInfoLog_b81bc53188e286fa = function(arg0, arg1, arg2) { + const ret = getObject(arg1).getProgramInfoLog(getObject(arg2)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_createShader_429776c9dd6fb87b = function(arg0, arg1) { + const ret = getObject(arg0).createShader(arg1 >>> 0); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_shaderSource_1cb7c64dc7d1a500 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).shaderSource(getObject(arg1), getStringFromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_compileShader_6bf78b425d5c98e1 = function(arg0, arg1) { + getObject(arg0).compileShader(getObject(arg1)); + }; + imports.wbg.__wbg_getShaderParameter_ac2727ae4fe7648e = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getShaderParameter(getObject(arg1), arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_getShaderInfoLog_968b93e75477d725 = function(arg0, arg1, arg2) { + const ret = getObject(arg1).getShaderInfoLog(getObject(arg2)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_createVertexArray_51d51e1e1e13e9f6 = function(arg0) { + const ret = getObject(arg0).createVertexArray(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_getAttribLocation_7dbdbad935433494 = function(arg0, arg1, arg2, arg3) { + const ret = getObject(arg0).getAttribLocation(getObject(arg1), getStringFromWasm0(arg2, arg3)); + return ret; + }; + imports.wbg.__wbg_enableVertexAttribArray_8804480c2ea0bb72 = function(arg0, arg1) { + getObject(arg0).enableVertexAttribArray(arg1 >>> 0); + }; + imports.wbg.__wbg_createBuffer_323425af422748ac = function(arg0) { + const ret = getObject(arg0).createBuffer(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_bindBuffer_24f6010e273fa400 = function(arg0, arg1, arg2) { + getObject(arg0).bindBuffer(arg1 >>> 0, getObject(arg2)); + }; + imports.wbg.__wbg_bufferData_21334671c4ba6004 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).bufferData(arg1 >>> 0, getObject(arg2), arg3 >>> 0); + }; + imports.wbg.__wbg_vertexAttribPointer_316ffe2f0458fde7 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + getObject(arg0).vertexAttribPointer(arg1 >>> 0, arg2, arg3 >>> 0, arg4 !== 0, arg5, arg6); + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_31ff1024ef0c63c7 = function(arg0, arg1, arg2) { + const ret = new Uint16Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { + const ret = debugString(getObject(arg1)); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + imports.wbg.__wbg_then_f7e06ee3c11698eb = function(arg0, arg1) { + const ret = getObject(arg0).then(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_then_b2267541e2a73865 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).then(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_resolve_53698b95aaf7fcf8 = function(arg0) { + const ret = Promise.resolve(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_self_1ff1d729e9aae938 = function() { return handleError(function () { + const ret = self.self; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_window_5f4faef6c12b79ec = function() { return handleError(function () { + const ret = window.window; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_globalThis_1d39714405582d3c = function() { return handleError(function () { + const ret = globalThis.globalThis; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_global_651f05c6a0944d1c = function() { return handleError(function () { + const ret = global.global; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbindgen_is_undefined = function(arg0) { + const ret = getObject(arg0) === undefined; + return ret; + }; + imports.wbg.__wbg_newnoargs_581967eacc0e2604 = function(arg0, arg1) { + const ret = new Function(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_object_clone_ref = function(arg0) { + const ret = getObject(arg0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_instanceof_Window_9029196b662bc42a = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Window; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbindgen_closure_wrapper958 = function(arg0, arg1, arg2) { + const ret = makeClosure(arg0, arg1, 49, __wbg_adapter_24); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper959 = function(arg0, arg1, arg2) { + const ret = makeClosure(arg0, arg1, 49, __wbg_adapter_27); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper960 = function(arg0, arg1, arg2) { + const ret = makeClosure(arg0, arg1, 49, __wbg_adapter_24); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1023 = function(arg0, arg1, arg2) { + const ret = makeClosure(arg0, arg1, 49, __wbg_adapter_32); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1029 = function(arg0, arg1, arg2) { + const ret = makeClosure(arg0, arg1, 49, __wbg_adapter_32); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1032 = function(arg0, arg1, arg2) { + const ret = makeClosure(arg0, arg1, 49, __wbg_adapter_32); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1035 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 49, __wbg_adapter_39); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1038 = function(arg0, arg1, arg2) { + const ret = makeClosure(arg0, arg1, 49, __wbg_adapter_32); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1166 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 49, __wbg_adapter_44); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1180 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 49, __wbg_adapter_47); + return addHeapObject(ret); + }; + + return imports; +} + +function __wbg_init_memory(imports, maybe_memory) { + +} + +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + __wbg_init.__wbindgen_wasm_module = module; + cachedFloat64Memory0 = null; + cachedInt32Memory0 = null; + cachedUint8Memory0 = null; + + wasm.__wbindgen_start(); + return wasm; +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + const imports = __wbg_get_imports(); + + __wbg_init_memory(imports); + + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + + const instance = new WebAssembly.Instance(module, imports); + + return __wbg_finalize_init(instance, module); +} + +async function __wbg_init(input) { + if (wasm !== undefined) return wasm; + + if (typeof input === 'undefined') { + input = new URL('waterfall_example_bg.wasm', import.meta.url); + } + const imports = __wbg_get_imports(); + + if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { + input = fetch(input); + } + + __wbg_init_memory(imports); + + const { instance, module } = await __wbg_load(await input, imports); + + return __wbg_finalize_init(instance, module); +} + +export { initSync } +export default __wbg_init; diff --git a/waterfall_example/waterfall_example_bg.wasm b/waterfall_example/waterfall_example_bg.wasm new file mode 100644 index 0000000..e461e00 Binary files /dev/null and b/waterfall_example/waterfall_example_bg.wasm differ diff --git a/waterfall_example/waterfall_example_bg.wasm.d.ts b/waterfall_example/waterfall_example_bg.wasm.d.ts new file mode 100644 index 0000000..d32e110 --- /dev/null +++ b/waterfall_example/waterfall_example_bg.wasm.d.ts @@ -0,0 +1,20 @@ +/* tslint:disable */ +/* eslint-disable */ +export const memory: WebAssembly.Memory; +export function start(): void; +export function maia_wasm_start(a: number): void; +export function make_waterfall(a: number, b: number, c: number): void; +export function __wbindgen_malloc(a: number, b: number): number; +export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number; +export const __wbindgen_export_2: WebAssembly.Table; +export function _dyn_core__ops__function__Fn_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h9fedf4ecdfaef9fb(a: number, b: number): number; +export function _dyn_core__ops__function__Fn_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h84a73a6c05432c52(a: number, b: number): void; +export function wasm_bindgen__convert__closures__invoke1__h691e8e97cf9508d4(a: number, b: number, c: number): void; +export function wasm_bindgen__convert__closures__invoke1_mut__h2114f6ea6548549c(a: number, b: number, c: number): void; +export function wasm_bindgen__convert__closures__invoke1_mut__h220f418a7eac6941(a: number, b: number, c: number): void; +export function wasm_bindgen__convert__closures__invoke0_mut__h77d7e03a9c772f50(a: number, b: number): void; +export function __wbindgen_free(a: number, b: number, c: number): void; +export function __wbindgen_exn_store(a: number): void; +export function wasm_bindgen__convert__closures__invoke2_mut__h3c7d769e0d744879(a: number, b: number, c: number, d: number): void; +export function __wbindgen_add_to_stack_pointer(a: number): number; +export function __wbindgen_start(): void;