vector<BusLevel> bus_levels;
bus_levels.resize(input_mapping.buses.size());
- for (unsigned bus_index = 0; bus_index < bus_r128.size(); ++bus_index) {
- bus_levels[bus_index].loudness_lufs = bus_r128[bus_index]->loudness_S();
- bus_levels[bus_index].gain_staging_db = gain_staging_db[bus_index];
+ {
+ lock_guard<mutex> lock(compressor_mutex);
+ for (unsigned bus_index = 0; bus_index < bus_r128.size(); ++bus_index) {
+ bus_levels[bus_index].loudness_lufs = bus_r128[bus_index]->loudness_S();
+ bus_levels[bus_index].gain_staging_db = gain_staging_db[bus_index];
+ if (compressor_enabled[bus_index]) {
+ bus_levels[bus_index].compressor_attenuation_db = -to_db(compressor[bus_index]->get_attenuation());
+ } else {
+ bus_levels[bus_index].compressor_attenuation_db = 0.0;
+ }
+ }
}
audio_level_callback(loudness_s, to_db(peak), bus_levels,
struct BusLevel {
float loudness_lufs;
float gain_staging_db;
+ float compressor_attenuation_db; // A positive number; 0.0 for no attenuation.
};
typedef std::function<void(float level_lufs, float peak_db,
on_pixmap = QPixmap(width(), height());
QPainter on_painter(&on_pixmap);
on_painter.fillRect(0, 0, width(), height(), parentWidget()->palette().window());
- draw_vu_meter(on_painter, width(), height(), margin, true, min_level, max_level);
+ draw_vu_meter(on_painter, width(), height(), margin, true, min_level, max_level, /*flip=*/false);
off_pixmap = QPixmap(width(), height());
QPainter off_painter(&off_pixmap);
off_painter.fillRect(0, 0, width(), height(), parentWidget()->palette().window());
- draw_vu_meter(off_painter, width(), height(), margin, false, min_level, max_level);
+ draw_vu_meter(off_painter, width(), height(), margin, false, min_level, max_level, /*flip=*/false);
}
});
slave_fader(audio_miniviews[bus_index]->fader, ui_audio_expanded_view->fader);
+
+ // Set up the compression attenuation meter.
+ VUMeter *reduction_meter = ui_audio_expanded_view->reduction_meter;
+ reduction_meter->set_min_level(0.0f);
+ reduction_meter->set_max_level(10.0f);
+ reduction_meter->set_ref_level(0.0f);
+ reduction_meter->set_flip(true);
}
}
Ui::AudioExpandedView *view = audio_expanded_views[bus_index];
view->vu_meter_meter->set_level(level.loudness_lufs);
+ view->reduction_meter->set_level(level.compressor_attenuation_db);
view->gainstaging_knob->blockSignals(true);
view->gainstaging_knob->setValue(lrintf(level.gain_staging_db * 10.0f));
view->gainstaging_knob->blockSignals(false);
return y;
}
-void draw_vu_meter(QPainter &painter, int width, int height, int margin, bool is_on, float min_level, float max_level)
+void draw_vu_meter(QPainter &painter, int width, int height, int margin, bool is_on, float min_level, float max_level, bool flip)
{
painter.fillRect(margin, 0, width - 2 * margin, height, Qt::black);
int r = lrintf(255 * pow(on_r * coverage, 1.0 / 2.2));
int g = lrintf(255 * pow(on_g * coverage, 1.0 / 2.2));
int b = lrintf(255 * pow(on_b * coverage, 1.0 / 2.2));
- painter.fillRect(margin, y, width - 2 * margin, 1, QColor(r, g, b));
+ int draw_y = flip ? (height - y - 1) : y;
+ painter.fillRect(margin, draw_y, width - 2 * margin, 1, QColor(r, g, b));
}
}
double lufs_to_pos(float level_lu, int height, float min_level, float max_level);
-void draw_vu_meter(QPainter &painter, int width, int height, int margin, bool is_on, float min_level, float max_level);
+void draw_vu_meter(QPainter &painter, int width, int height, int margin, bool is_on, float min_level, float max_level, bool flip);
#endif // !defined(_VU_COMMON_H)
float level_lu = level_lufs - ref_level_lufs;
int on_pos = lrint(lufs_to_pos(level_lu, height()));
- QRect off_rect(0, 0, width(), on_pos);
- QRect on_rect(0, on_pos, width(), height() - on_pos);
- painter.drawPixmap(off_rect, off_pixmap, off_rect);
- painter.drawPixmap(on_rect, on_pixmap, on_rect);
+ if (flip) {
+ QRect on_rect(0, 0, width(), height() - on_pos);
+ QRect off_rect(0, height() - on_pos, width(), height());
+
+ painter.drawPixmap(on_rect, on_pixmap, on_rect);
+ painter.drawPixmap(off_rect, off_pixmap, off_rect);
+ } else {
+ QRect off_rect(0, 0, width(), on_pos);
+ QRect on_rect(0, on_pos, width(), height() - on_pos);
+
+ painter.drawPixmap(off_rect, off_pixmap, off_rect);
+ painter.drawPixmap(on_rect, on_pixmap, on_rect);
+ }
}
void VUMeter::recalculate_pixmaps()
{
on_pixmap = QPixmap(width(), height());
QPainter on_painter(&on_pixmap);
- draw_vu_meter(on_painter, width(), height(), 0, true, min_level, max_level);
+ draw_vu_meter(on_painter, width(), height(), 0, true, min_level, max_level, flip);
off_pixmap = QPixmap(width(), height());
QPainter off_painter(&off_pixmap);
- draw_vu_meter(off_painter, width(), height(), 0, false, min_level, max_level);
+ draw_vu_meter(off_painter, width(), height(), 0, false, min_level, max_level, flip);
}
this->ref_level_lufs = ref_level_lufs;
}
+ void set_flip(bool flip)
+ {
+ this->flip = flip;
+ recalculate_pixmaps();
+ }
+
private:
void resizeEvent(QResizeEvent *event) override;
void paintEvent(QPaintEvent *event) override;
std::mutex level_mutex;
float level_lufs = -HUGE_VAL;
float min_level = -18.0f, max_level = 9.0f, ref_level_lufs = -23.0f;
+ bool flip = false;
QPixmap on_pixmap, off_pixmap;
};