+ float minf;
+ float maxf;
+
+ TreeNodeChildren track_rows = _a_window->track_list.get_model ()->children ();
+
+ if (!_show_normalized) {
+ maxf = 0.0f;
+ minf = -108.0f;
+ } else {
+ minf = 999.0f;
+ maxf = -999.0f;
+ for (TreeIter i = track_rows.begin (); i != track_rows.end (); i++) {
+ TreeModel::Row row = *i;
+ FFTResult *res = row[_a_window->tlcols.graph];
+
+ // disregard fft analysis from empty signals
+ if (res->minimum (_show_proportional) == res->maximum (_show_proportional)) {
+ continue;
+ }
+ // don't include invisible graphs
+ if (!row[_a_window->tlcols.visible]) {
+ continue;
+ }
+
+ minf = std::min (minf, res->minimum (_show_proportional));
+ maxf = std::max (maxf, res->maximum (_show_proportional));
+ }
+ }
+
+ // clamp range, > -200dBFS, at least 24dB (two y-axis labels) range
+ minf = std::max (-200.f, minf);
+ if (maxf <= minf) {
+ return;
+ }
+
+ if (maxf - minf < 24) {
+ maxf += 6.f;
+ minf = maxf - 24.f;
+ }
+
+ cairo_t *cr;
+ cr = gdk_cairo_create (GDK_DRAWABLE (get_window ()->gobj ()));
+ cairo_set_line_width (cr, 1.5);
+ cairo_translate (cr, hl_margin + 1, yoff);
+
+ float fft_pane_size_w = width - hl_margin - hr_margin;
+ float fft_pane_size_h = height - v_margin - 1 - yoff;
+ double pixels_per_db = (double)fft_pane_size_h / (double)(maxf - minf);
+
+ // draw y-axis dB
+ cairo_set_source_rgba (cr, .8, .8, .8, 1.0);
+
+ int btm_lbl = fft_pane_size_h;
+ {
+ // y-axis legend
+ layout->set_text (_("dBFS"));
+ int lw, lh;
+ layout->get_pixel_size (lw, lh);
+ cairo_move_to (cr, -2 - lw, fft_pane_size_h - lh / 2);
+ pango_cairo_update_layout (cr, layout->gobj ());
+ pango_cairo_show_layout (cr, layout->gobj ());
+ btm_lbl = fft_pane_size_h - lh;
+ }
+
+ for (int x = -6; x >= -200; x -= 12) {
+ float yp = 1.5 + fft_pane_size_h - rint ((x - minf) * pixels_per_db);
+
+ assert (layout);
+ std::stringstream ss;
+ ss << x;
+ layout->set_text (ss.str ());
+ int lw, lh;
+ layout->get_pixel_size (lw, lh);
+
+ if (yp + 2 + lh / 2 > btm_lbl) {