|
MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
|
MayaFlux is a C++20/23 framework for real-time computation across sound, geometry, image, and network. All data is the same numerical substrate; the domain annotation decides where a buffer cycle goes, not what the data is.
This guide covers environment setup and the structure of a MayaFlux program. Tutorials that build on this foundation are at mayaflux.org/tutorials.
Weave is the installer and project tool for MayaFlux. Download it from the Weave releases page.
Launch Weave and choose Install MayaFlux. Weave downloads the framework, installs all required dependencies, and configures your environment. Restart your terminal when it finishes.
Launch Weave and choose Create Project. Enter a name and pick a destination. Weave generates a ready-to-build project:
src/user_project.hpp is where you write your code. CMakeLists.txt is yours to edit; the MayaFlux integration lives in cmake/mayaflux.cmake and is included automatically.
CMakePresets.json ships with every project and defines debug and release presets. CLion, VS Code with the CMake extension, and Visual Studio all pick up the presets automatically when you open the project folder.
On Windows the binary lands in build\MyProject.exe.
Check Enable Live Coding (Lila) in the project creation dialog to embed the Lila JIT compiler in your process. Connect LilaCode (VS Code) or lila.nvim (Neovim) to evaluate C++ against your running application in real time.
Community modules are C++ source libraries that compile directly into your project with no plugin boundary. In Weave, open your project and choose Add Community Module. Weave fetches the community registry, checks version compatibility, clones the module into community/<name>/, and registers it in community.cmake. Rebuild after adding modules.
After Weave completes setup, jump to Program Structure.
Weave is the supported path for using MayaFlux; it downloads a prebuilt framework and generates a project against it, no compiler toolchain or dependency management on your end.
Building the framework itself from source is a different, separate task, for contributors modifying the engine, not for writing programs against it. If that's what you're doing, see `docs/Dev_Getting_Started.md` in the MayaFlux repository, which covers dependencies, setup scripts, build presets, and the in-tree run loop.
If you're not sure which you need: if you want to write music, visuals, or interactive pieces with MayaFlux, use Weave. If you want to change how MayaFlux itself works, build from source.
A MayaFlux program has two entry points defined in src/user_project.hpp:
settings() reaches every part of the engine, not only audio. The stream config sets the audio device, rate and buffer; the graphics config sets the frame rate and window surface; input, network and logging have their own. Leave settings() empty if the defaults suit you.
main.cpp calls settings(), Init(), Start(), compose(), Await(), and End() in order. If a config file is present it is loaded around settings(); see Engine Configuration for which one wins. You do not edit main.cpp unless you need custom engine configuration beyond what settings() exposes.
An exception thrown by settings() or by compose() is logged, and the engine carries on.
MayaFlux.hpp includes the common concrete types and namespace imports by default, so the examples can use names such as Sine without extra includes. To keep the global namespace clear and include only the types you use, define MAYAFLUX_NO_CONVENIENCE before including MayaFlux.hpp.
vega is the global Creator instance. It is the factory for all computation objects: generators, filters, networks, buffers, containers, mesh loaders, input nodes. Every object created through vega is registered with the engine automatically.
The | Audio and | Graphics operators are domain annotations. They attach a processing token that decides which subsystem drives the object and at what rate. They do not change what the object is.
Two more calls take a whole configuration and do the entire job in one step, including attaching rendering to a window. vega.mint builds a visible structure from a config (an object, a model, instances, an assembly or an isosurface). vega.evolve sets a system going: state that persists and a rule that advances it every cycle, such as a cellular grid, a volume of flow, or a network of particles driven by GPU fields. Both return the real object and both need a target_window.
The program below uses both: mint builds the form from a field, and evolve sets the swarm going.
The interesting power of the computer is precisely that it is programmable. Pretending otherwise is not a kindness; it is a limitation. MayaFlux makes common things fluent, not because complexity is undesirable, but because verbosity should not stand between an idea and its expression. Complexity is something else. It is where new possibilities emerge, where you can go beyond what the system's author imagined or provided. The aim is not to spare you from programming. It is to give you more freedom through it.
Before explaining how MayaFlux works, here is something made with it.
Most introductions begin with a hello world, or with a small example that isolates one idea. This one begins with something to play with. It is a complete piece, with sound, a moving form and a swarm, that you can run, disturb and change without understanding any of it. Play is a better way to learn than a single triangle on a screen: you try something, see or hear what moved, and the questions come from you instead of from the page.
Four voices emerge from different kinds of randomness and orbit through a shared space. Each owns a body of a different shape in a form carved on the GPU, and two hundred thousand particles stream toward the voices along its surface. Their activity is shared: the voices shape the form and the swarm, the form's changing size affects the voices, and the whole system develops its own irregular rhythms.
Nothing needs to be recorded, downloaded, or connected. No microphone or camera is required. When it starts it asks you to choose one image, which becomes the form's skin.
Copy the program into your Weave-created project, build it, and run it. Listen, watch, click to strike every voice, hold and drag to play them, and leave it running for a minute.
You do not need to understand the code yet. It is here to show you a direction, not to test your understanding.
This program is complete and runs as written, but it is deliberately not the shortest way to make this picture. It is built as a set of separate units: the voices, the scene they share, the form, the swarm, the camera, the Nexus wiring that gives each voice a place and a pulse, and the fields that tell the GPU what to draw. Each unit has one job and can be changed without touching the others. The fields near the end are the exception to easy reading: they are GLSL written as C++ lambdas, compiled once by the host and turned into a GPU shader function from the same text. Skip them at first and come back when you want to change how the form or the swarm look and move. Written by hand with every effect fused into one loop, it would be fewer lines, and it would also be a dead end: nothing in it could be extended. The extra length is the price of having this many places to change it, and a later tutorial takes each unit in turn and shows how to extend it.
What this shows:
UNIFORM, NORMAL, EXPONENTIAL, BROWNIAN) through a resonant filter, with a gain worked out from its decay. No oscillator makes a tone.Nexus::Presence moving on its own closed orbit near the origin. Its stereo position is where it is, not a separate oscillator.vega.mint(StructureConfig::Isosurface { ... }) turns a field into a live mesh. The field is written once with MF_FIELD_P and evaluated on the GPU. Each voice owns a body of its own shape (a sphere, a ring, a spike, a cube) at its position in the room, sized by its energy. Bodies merge when they come close or grow loud, and part when they do not.Emitter wired to the mouse button that strikes every voice and flares the scene. Holding and dragging lifts the voices and pans them toward the cursor.Change kinds to give the voices other randomness, voice_at (with the matching orbit expression in the fields) to change where they move, set_falloff_radius and set_falloff_curve for how far and how softly they reach each other, the core radius 0.85 for how often events fire, read_image() to choose the skin it wears, heard_form to change what the form is made of, flock to change what the swarm does, and voiced and grain for its colour and size. The number four appears in the constant arrays, in the Presence loop, and in the fields themselves, where a vec4 carries the four energies, so a fifth voice means widening all three.
doxygen doxyconfNo. MayaFlux compiles with Apple Clang from Xcode Command Line Tools. Homebrew LLVM is not used for compilation. LLVM is required as a runtime dependency for Lila (the JIT environment) and is installed by the setup script, but it is not your compiler. This applies to building MayaFlux itself from source; see `docs/Dev_Getting_Started.md`.
Weave-installed MayaFlux (currently 0.4.1) targets: Windows 10 version 1909+, Fedora 43, Ubuntu 25.10, macOS 15.
Building from source targets a newer floor, since source currently tracks 0.5-dev: Windows 10 version 1909+, Fedora 44, Ubuntu 26.04 LTS, macOS 26 (Tahoe) on Apple Silicon (ARM64). See `docs/Dev_Getting_Started.md` for the from-source requirement list.
The Windows floor is set by MSVC 2022's own minimum supported OS. Win32 windowing, WinMM, and WASAPI all predate this by a wide margin and impose no additional constraint.
Starting with 0.5-dev, MayaFlux supports macOS on Apple Silicon only, for both source builds and binary distributions. This does not change the hardware requirements of previously published releases.
The constraint comes from the dependency ecosystem, beyond MayaFlux's control. In September 2026, Homebrew stopped building new Intel macOS bottles and moved Intel Macs to Tier 3, without CI coverage or a commitment to fix platform-specific failures. Existing bottles may still work, but updated formulae may require source builds. Homebrew expects to remove Intel execution support in or after September 2027. Homebrew's release announcement also identifies Apple and GitHub's retreat from Intel support as infrastructure its volunteers cannot replace. MayaFlux cannot replace that infrastructure or maintain a separate binary dependency stack where much larger, better-funded platform providers are withdrawing support.
Building MayaFlux from source does not bypass this problem. Before reaching MayaFlux, a fresh Homebrew installation can require source builds of its dependency chain, including LLVM, FFmpeg, Vulkan components, and their dependencies where matching bottles are unavailable. Our Intel CI has already encountered a GCC source rebuild. GCC is not MayaFlux's macOS compiler, which remains Apple Clang; it can enter through dependency builds. The burden includes building the compiler's dependencies, packages that need it, and resolving failures on a platform Homebrew no longer tests. A cached CI installation can conceal that burden until the cache changes or expires; a new user's machine has no such protection.
This is not a practical installation path we can support. Current setup scripts and CMake configurations reject Intel macOS targets, and universal macOS builds are unsupported. Existing Intel installations may continue to work with older dependencies, but they do not provide a reliable path to current releases.
This applies to building MayaFlux itself from source. Weave-installed MayaFlux handles dependencies for you. See `docs/Dev_Getting_Started.md` for the from-source dependency list and setup scripts.
Yes. Lila is part of the engine but you do not have to use it. Programs written entirely in compose() and compiled normally do not touch the JIT path. Weave's live coding toggle controls whether Lila is embedded in your project at all.
In src/user_project.hpp. It is never overwritten by Weave updates. main.cpp is the engine entry point and should not be modified unless you need a custom startup sequence.