add grid to inline-spectrum
authorRobin Gareus <robin@gareus.org>
Sun, 3 Jul 2016 12:46:29 +0000 (14:46 +0200)
committerRobin Gareus <robin@gareus.org>
Sun, 3 Jul 2016 12:46:29 +0000 (14:46 +0200)
scripts/spectrogram.lua

index 94ae043914cf1c43114a1a6c7df82ad56556ee4b..f82d4fe4bb2f34bc1f0e4ecf6536ec9756ef9399 100644 (file)
@@ -145,6 +145,7 @@ local read_ptr = 0
 local line = 0
 local img = nil
 local fft_size = 0
+local last_log = false
 
 function render_inline (ctx, w, max_h)
        local ctrl = CtrlPorts:array () -- get control port array (read/write)
@@ -188,6 +189,12 @@ function render_inline (ctx, w, max_h)
                fft = ARDOUR.DSP.FFTSpectrum (fft_size, rate)
        end
 
+       if last_log ~= logscale then
+               last_log = logscale
+               img = nil
+               line = 0
+       end
+
        -- calc height
        if hmode == 0 then
                h = math.ceil (w * 10 / 16)
@@ -209,13 +216,19 @@ function render_inline (ctx, w, max_h)
        if not img or img:get_width() ~= w or img:get_height () ~= h then
                img = Cairo.ImageSurface (Cairo.Format.ARGB32, w, h)
        end
+       local ictx = img:context ()
+
+       local bins = fft_size / 2 - 1 -- fft bin count
+       local bpx = bins / w  -- bins per x-pixel (linear)
+       local fpb = rate / fft_size -- freq-step per bin
+       local f_e = rate / 2 / fpb -- log-scale exponent
+       local f_b = w / math.log (fft_size / 2) -- inverse log-scale base
+       local f_l = math.log (fft_size / rate) * f_b -- inverse logscale lower-bound
 
-       -- read ring-buffer, analyze
+       -- available samples in ring-buffer
        local write_ptr = shmem:atomic_get_int (0)
        local avail = (write_ptr + buf_size - read_ptr) % buf_size
 
-       local ictx = img:context ()
-
        while (avail >= fft_size) do
                -- process one line / buffer
                if read_ptr + fft_size < buf_size then
@@ -232,12 +245,8 @@ function render_inline (ctx, w, max_h)
                avail = (write_ptr + buf_size - read_ptr ) % buf_size
 
                -- draw spectrum
-               local bins = fft_size / 2 - 1
-               local bpx = bins / w
-               local fpb = rate / fft_size
                assert (bpx >= 1)
 
-               local f_e = rate / 2 / fpb
                -- scroll
                if line == 0 then line = h - 1; else line = line - 1; end
 
@@ -292,5 +301,34 @@ function render_inline (ctx, w, max_h)
                ctx:fill ()
        end
 
+
+       -- draw grid on top
+       function x_at_freq (f)
+               if logscale then
+                       return f_l + f_b * math.log (f)
+               else
+                       return 2 * w * f / rate;
+               end
+       end
+
+       function grid_freq (f)
+               -- draw vertical grid line
+               local x = .5 + math.floor (x_at_freq (f))
+               ctx:move_to (x, 0)
+               ctx:line_to (x, h)
+               ctx:stroke ()
+       end
+
+       -- draw grid on top
+       local dash3 = C.DoubleVector ()
+       dash3:add ({1, 3})
+       ctx:set_line_width (1.0)
+       ctx:set_dash (dash3, 2) -- dotted line
+       ctx:set_source_rgba (.5, .5, .5, .8)
+       grid_freq (100)
+       grid_freq (1000)
+       grid_freq (10000)
+       ctx:unset_dash ()
+
        return {w, h}
 end