Skip to content

Latest commit

 

History

History
113 lines (87 loc) · 3.94 KB

README.md

File metadata and controls

113 lines (87 loc) · 3.94 KB

SpectrumFFT

Displays audio FFT using color gradients.

Features

  • Choose from 21 preset color schemes or create your own

Creating Your Own Color Schemes

Overview

SpectrumFFT displays the volume level of each audio frequency as a color from a color scheme function of your choosing. A color scheme function takes a volume level value between 0 and 1, and outputs a color. When designing a color scheme, think of it as a set of color stops, e.g. transparent at 0% volume to red at 100% volume, and the blending between those color stops.

If a color scheme you make is interesting and unique enough, I'll include it as a default preset in SpectrumFFT!

If you can't figure out how to create a color scheme function, you can give me a list of color stops and their percentage positions, and I can create it for you.

Getting Started

Go to this directory:

Documents\Rainmeter\Skins\SpectrumFFT\@Resources\Presets\

Duplicate the file of an existing preset, and open it in your favorite text editor.

Function Outline

A basic visualization function (Red.lua is shown) looks like this:

local v = ...

return '255,0,0,'..(v^3 * 255)

SpectrumFFT will convert the above into this function:

function Preset(v, b, bands)
    return '255,0,0,'..(v^3 * 255)
end

Which will then be used like so:

SKIN:Bang('!SetVariable Color'..b..' '..Preset((mFFT[b]:GetValue() - levelMin) / levelRange, b, bands))

Functions are restricted to the use of these input variables:

  • v value of FFT at current band and row, ranging from 0 to 1
  • b number of current band, ranging from 0 to (bands - 1), usually unused
  • bands total number of bands, usually unused

Additionally, you can use any built-in Lua 5.1 functions. Global variables and external Lua libraries cannot be used. Rainmeter variables and measure values are allowed.

Functions must return a valid color in RGB, RGBA (meaning Red, Green, Blue, Alpha transparency), or hex color format.

Color Blending

Here is a color scheme with multiple color stops (Infrared.lua):

local v = ...

if v < 0 then
    return '0,0,0,0'
elseif v < 0.4 then
    --   0,  0,255 @ 0.4
    return '0,0,'..(v * 638)..','..(v * 638)
else
    -- 255,  0,  0 @ 0.8
    -- 255,255,  0 @ 1
    return ((v - 0.4) * 638)..','..((v - 0.8) * 1275)..','..((v - 0.8) * -638)
end

It is easier to understand in expanded form:

local v = ...

if v < 0 then
    return '0,0,0,0'
elseif v < 0.4 then
    --   0,  0,255 @ 0.4
    return '0,0,'..(v * 638)..','..(v * 638)
elseif v < 0.8 then
    -- 255,  0,  0 @ 0.8
    return ((v - 0.4) * 638)..',0,'..((v - 0.4) * -638 + 255)
else
    -- 255,255,  0 @ 1
    return '255,'..((v - 0.8) * 1275)..',0'
end

It consists of the following color stops:

  • '0,0,0,0' at v = 0
  • '0,0,255,255' at v = 0.4
  • '255,0,0,255' at v = 0.8
  • '255,255,0,255' at v = 1

An RGBA color has 4 color channels. The general formula for smoothly blending a color channel between 2 color stops is:

(v - range min of v) * ((change in color channel value) / (range of v)) + (color channel value at range min of v) = output color channel value

For example, to blend the red channel from 0 to 255 for range of v = 0.4 to v = 0.8, the formula is:

(v - 0.4) * (255 / 0.4) + 0 = (v - 0.4) * 638

This formula only covers linear blending. For smoother blending curves, adapt formulas from HoloFFT's tutorial. However, in my experience, linear blending is usually sufficient.

Color channel values below 0 are equivalent to 0 and values above 255 are equivalent to 255, so functions don't need to attempt to clamp values to the valid range.