Skip to content

Releases: M0Rf30/lactea

v0.2.2

Choose a tag to compare

@github-actions github-actions released this 13 Oct 22:29
10d9627

Added

  • web: browser showcase on GitHub Pages (#20): playlist, drag-and-drop presets and textures, file / microphone / synthetic audio

Fixed

  • web: the wasm32 build no longer hangs on the motion-vector UV readback under WebGPU; it uses the CPU warp UVs

Full changelog: CHANGELOG.md

v0.2.1

Choose a tag to compare

@github-actions github-actions released this 13 Oct 14:32
c853877

Fixed

  • md2: BeatDrop shader inputs ported from source: BeatDrop's include.fx prelude, separate sampler_fft (1024x2) and sampler_wave (480x2) textures, host vars and FFT coefficients blended over soft cuts
  • hlsl: the remaining include.fx aliases (aspect_sd, SAMPLER*D, texture*D, trunc, tex1d, texcube)
  • capi: no dead-code warning for VulkanState::format on Apple targets

Full changelog: CHANGELOG.md

v0.2.0

Choose a tag to compare

@github-actions github-actions released this 13 Oct 11:43
5e83aee

Breaking

  • lactea: Engine::new returns Result<Engine, EngineError> (it sanitises the config: mesh clamp, size and fps of at least 1); Engine::resize returns Result<(), EngineError> and Engine::set_mesh_size Result<[u32; 2], EngineError>, both keep the old size on failure
  • lactea-render: Renderer::new, resize and set_mesh_size return RenderError::Invalid for a size beyond the device's max_texture_dimension_2d or a mesh beyond 300 cells
  • lactea-render: noise::generate and gen_noise_vol take &CompatRules; CompatRules gains max_rand_slot, rand_filter_raw_name, noisevol_row_stride, shader_time_wrap, md2_shader_inputs, md2_input_vars (the struct is #[non_exhaustive])
  • lactea-capi: LacteaCompat is an int32_t with LACTEA_COMPAT_{PROJECTM,MILKDROP2,MILKDROP3,AUTO} constants instead of an enum; an unknown value makes lactea_create return NULL; lactea_set_fps(0) and a non-finite preset_duration are InvalidArgument
  • lactea-preset: ParseError gains TooLarge, BinaryData and NoKeys; Flavor::ProjectM now rejects presets over 1 MiB, with a NUL byte, or without a key line, like projectM (the MilkDrop 2 flavour is unchanged)
  • lactea-jpeg: the image fallback for JPEGs stb rejects is gone (the jpeg feature of the C API and the CLI is removed); such files now fail to decode, as in projectM
  • lactea-hlsl: Options gains rand_max_slot and rand_strict_name
  • lactea-render, lactea-app, lactea-capi: wgpu is built without default features (std, parking_lot, wgsl plus one backend per platform); the OpenGL ES / WebGL backend is the opt-in gles feature of lactea-render, lactea-app and lactea-capi
  • lactea-abi: serde is an optional feature (enabled by lactea-cli and lactea-compare)
  • web example: resize() returns Result<(), JsValue>

Added

  • sprites: projectM user sprites: Engine::{sprite_create, sprite_destroy, sprite_destroy_all, sprite_count, sprite_ids, set_max_sprites, max_sprites, sprite_var, set_sprite_var}, lactea_preset::parse_user_sprite and the C API lactea_sprite_*; during a soft cut they are drawn after the blend onto the output and burn goes into both presets
  • playlist: lactea_playlist_*, a C API for every projectm_playlist_* call (a connected playlist loads files and answers the engine's switch requests); lactea_host::PlaylistFs::{add_path, insert_path} and scan_presets, .prjm accepted wherever presets are scanned
  • api: Engine::burn_texture / lactea_burn_texture_rgba, Engine::reload_textures / lactea_reset_textures, lactea::VCS_VERSION / lactea_vcs_version, lactea_set_log_callback / lactea_set_log_level (a log facade bridge), lactea_set_texture_load_callback
  • md2: BeatDrop inputs under Compat::MilkDrop2: mousex mousey mousedown mouseclick, ctrllt ctrlrt ctrldn ctrlup and year .. totalseconds expression variables, shader _c14 / _c15 / _c16, Engine::{set_date_time, clear_date_time, set_ctrl_keys, monitor} and their C exports, and BeatDrop's shader FFT (lactea_audio::BeatDropShaderFft, sampler_fft / sampler_wave, get_fft*, get_wave)
  • engine: PresetControl::preset_duration_sampled and Engine::set_loaded_preset_duration: progress runs over the sampled display time once a host reports it (the C API and the app do)
  • hlsl: wrapped_hlsl(kind, user, md3, projectm) and rand_slot
  • eel: Context::try_run
  • host: new crate lactea-host (directory textures with an optional decode cache, image / media / WAV decode, GPU setup, preset scanning) shared by the C API, the CLI and the app; new unpublished crate lactea-testutil (shared GPU test helpers)
  • render: readback_rgba8 is public

Changed

  • render: projectM-flavour shaders write alpha 1.0 (MilkdropShader.cpp:468); the noisevol_* textures use projectM's z * size slice stride (noisevol_row_stride); _c2.x is the raw time under MilkDrop 2 (projectM and MilkDrop 3 wrap it modulo 10000, shader_time_wrap)
  • engine: one randNN parser for samplers and texsize_randNN, slot range 15 (projectM) / 99 (MilkDrop 2); the pool prefix filter reads the raw sampler name in projectM mode (a quality prefix defeats it) and the peeled name in MilkDrop 2
  • engine: the first rendered frame has dt = 0; set_fps(0) is ignored; a transition of duration 0 reports progress 1
  • audio: non-finite PCM samples read as 0 (MD3: ±inf saturates, NaN is 0) and a non-finite volume sensitivity is ignored
  • app: the preset browser runs on Playlist and PresetControl (the app's Random can repeat the current preset, as Playlist's pick does; seeded display-time draws differ from before); textures come from lactea_host::DirTextures in projectM scan order (directory order, then path) and .dds files are indexed; --duration, --transition-duration and --duration-rand must be finite and at most 1e9 s; ResetRequired rebuilds the audio decoder from the new default track; symphonia is built with an explicit format list
  • jpeg: decoding is bounded to 2 GiB, allocations are fallible, and a frame without a scan is an error
  • wav: a short fmt chunk is an error
  • perf: release builds use fat LTO and strip symbols and wgpu keeps one backend per platform (the fdrender release binary shrinks from 87 MB to 7.3 MB); per-frame wave, overlay, motion-vector, border and vertex buffers are reused, blit and blur bind groups are cached, and the MD3 spectrum FFT is cached
  • refactor: lactea-render's renderer.rs is split into renderer/{mod, pipelines, uv_readback, orchestrate, passes, fixed, burn}.rs; the MD2 and MD3 blend patterns share gen_plasma (engine/blend_patterns.rs); wave, shader-snippet and sprite-fragment helpers are shared

Fixed

  • engine: Engine::new no longer panics on a zero size or a tiny mesh (an MD2 soft cut with mesh [3, 5] used to)
  • eel: parse paths no longer panic; Context::run returns 0 for a foreign program and Context::get / set, GlobalMemory::reg / set_reg ignore foreign variables and out-of-range registers; megabuf / gmegabuf blocks are allocated on first write
  • render: a zero-width volume_alpha_mod is a step, not NaN; the MD2 main wave and its raw geometry return nothing for fewer than 576 samples; the MD2 shape border gate is > 0; byte-length and read-back arithmetic uses usize / u64
  • preset: SpriteName= is read after its own key, not after the first =
  • capi: the read-back buffer is released on every error path; the lactea_set_texture_dir extension list and the LacteaConfig::compat documentation are corrected
  • sprites: a user sprite over a soft cut is no longer distorted by the transition

Full changelog: CHANGELOG.md

v0.1.2

Choose a tag to compare

@github-actions github-actions released this 12 Oct 19:47
062ea31

Added

  • md3: MilkDrop 3 (3.37) support behind Compat::MilkDrop3: .milk2 double presets, 30 MD3 blend patterns, preset sprites (11 blend modes, layers, GIF), get_fft / mouse / q33-q64 shader inputs, the ns-eel2 expression dialect, wave modes 0-16, 500-side shapes, .wave / .shape import and export, auto hard-cut modes 1-7 (#7)
  • md3: the _mxd3qxa.._d / _mxd3qsa.._c audio-envelope / beat-latch shader uniforms (and the MXD3QX1..16 / MXD3QS1..12 prelude macros) are computed per frame instead of being undeclared (#11)
  • app: --compat auto is the default: MD3 files are detected by content, and a preset falls back to MilkDrop 2 when projectM fails to compile its shaders (#9)
  • app: --shader-override-warp / --shader-override-comp HANDLE=FILE, as in fdrender (#11)

Changed

  • perf: output-identical renderer and VM work, 22-47 % fewer instructions (#9)
  • md2: code lines are joined without a separator, as in MilkDrop 2 (#7)

Fixed

  • lactea: in auto compat, a preset whose shader projectM cannot translate is retried under MilkDrop 2 (#10)
  • md3: robustness fixes and projectM fidelity fixes (#9)

Full changelog: CHANGELOG.md

Lactea 0.1.1

Choose a tag to compare

@github-actions github-actions released this 12 Oct 01:14
316bdcd

Lactea

First public release of Lactea (0.1.1: 0.1.0 crates were published but its Windows build failed, so this is the first release with binaries), a pure-Rust MilkDrop 2 / projectM-compatible music visualizer on wgpu (Vulkan, Metal, DX12, GL, WebGPU).

Matches the projectM reference on 99.8 % of the 4169 comparable presets of the projectM preset collection (method and details in docs/fidelity.md).

Highlights

  • Embeddable engine (lactea): renders into any wgpu texture the host provides. No windows, audio devices or filesystem access in the library; presets, textures and PCM come in as bytes.
  • projectM or MilkDrop 2 semantics (Compat::ProjectM, default, or Compat::MilkDrop2).
  • Soft preset transitions (projectM's six blend shaders), playlist, preset lock, beat-driven hard cuts, runtime mesh / fps / duration changes, idle preset.
  • Shaders: MilkDrop HLSL (ps_2 / ps_3 + include.fx) translated to WGSL; 1422 of 1423 corpus shaders.
  • Expressions: ns-eel2 / projectm-eval compatible VM, bitwise equal to projectm-eval and faster.
  • Standalone app (lactea): PipeWire "what you hear" capture (cpal elsewhere), audio file playback, preset browsing, fullscreen, soft cuts.
  • C API (lactea-capi): render to an RGBA8 buffer or into a host VkImage; cbindgen header lactea.h.
  • WebAssembly: the engine builds for wasm32-unknown-unknown and runs on WebGPU.

Crates

crate
lactea engine
lactea-render wgpu MilkDrop 2 frame pipeline
lactea-preset .milk parser
lactea-eel expression language
lactea-hlsl HLSL → WGSL
lactea-audio audio analysis
lactea-jpeg stb_image-exact JPEG decoder
lactea-abi shared contract
[dependencies]
lactea = "0.1"

Downloads

asset contents
lactea-v0.1.1-linux-x86_64.tar.gz lactea app (PipeWire + cpal), liblactea_capi.so/.a, lactea.h, desktop file, icon
lactea-v0.1.1-windows-x86_64.zip lactea.exe (cpal), lactea_capi.dll/.lib, lactea.h
lactea-v0.1.1-macos-arm64.tar.gz lactea app (cpal), liblactea_capi.dylib/.a, lactea.h
SHA256SUMS checksums

Windows and macOS builds are produced by CI but have not been tested on real machines yet; reports welcome.

Known limitations

  • Vulkan interop in the C API is not available on Apple platforms.
  • A handful of presets still differ from projectM by single pixels or float precision; see Open items.

Full changelog: CHANGELOG.md