Skip to content

Sound effects

nari.effect({
id = "underwater",
name = "Underwater",
icon = "underwater.svg",
pitch = 0.9,
chain = {
{ type = "lowpass", frequency = 500 },
{ type = "reverb", mix = 0.6, decay = 4 },
{ type = "gain", db = 3 },
},
})

Plugin effects show up in Now Playing’s Effects tab, on their own page after the built-in ones. Only one effect plays at a time, plugin or built-in.

The sound is processed by Nari’s audio engine, not by Lua, so effects keep working while Android pauses the app and cost nothing on the main thread.

An effect is a chain of up to 16 stages applied in order, plus optional pitch and speed factors (0.25 to 4, like the built-in Helium and Senior). Every stage has a type; the other keys are optional unless noted.

type Keys What it does
lowpass frequency (Hz, required) Removes everything above frequency.
highpass frequency (Hz, required) Removes everything below frequency.
peak frequency (Hz), gain (dB, -24 to 24), both required Boosts or cuts a band, like one equalizer slider.
reverb mix (0 to 1, 0.5), decay (seconds, 2.8) Hall reverb.
echo time (seconds up to 2, 0.3), feedback (0 to 0.95, 0.4), mix (0 to 1, 0.5) Repeating echo.
distortion drive (1 to 100, 4) Soft clipping.
bitcrush bits (1 to 16, 8), rate (Hz) Fewer bits and a lower sample rate, for lo-fi and chiptune sounds.
tremolo rate (Hz, 5), depth (0 to 1, 0.5) Volume wobble.
ring frequency (Hz, required), mix (0 to 1, 1) Ring modulation, for robotic voices.
width amount (0 to 4, required) Stereo width: 0 is mono, 1 leaves it as is, more widens it.
gain db (-24 to 24, required) Volume.

A chain with an unknown type or a missing required key doesn’t play, and Nari logs a warning when it’s picked.

MediaPlayer:get_music_effect_state().custom is the id of the plugin effect that’s on ("<plugin id>.<effect id>"), or an empty string.