From 326471d561a5bdec283968571eb627915b93667d Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sat, 13 Aug 2016 22:47:26 +0200 Subject: [PATCH] Hook up the per-bus VU meters. --- audio_mixer.cpp | 42 ++++++++++++++++++++++++++++++++++++------ audio_mixer.h | 8 ++++++++ mainwindow.cpp | 14 ++++++++++++-- mainwindow.h | 3 ++- 4 files changed, 58 insertions(+), 9 deletions(-) diff --git a/audio_mixer.cpp b/audio_mixer.cpp index 5a78045..afff6f3 100644 --- a/audio_mixer.cpp +++ b/audio_mixer.cpp @@ -350,12 +350,16 @@ vector AudioMixer::get_output(double pts, unsigned num_samples, Resamplin } // TODO: Move lo-cut etc. into each bus. - vector samples_out; + vector samples_out, left, right; samples_out.resize(num_samples * 2); samples_bus.resize(num_samples * 2); for (unsigned bus_index = 0; bus_index < input_mapping.buses.size(); ++bus_index) { fill_audio_bus(samples_card, input_mapping.buses[bus_index], num_samples, &samples_bus[0]); + // TODO: We should measure post-fader. + deinterleave_samples(samples_bus, &left, &right); + measure_bus_levels(bus_index, left, right); + float volume = from_db(fader_volume_db[bus_index]); if (bus_index == 0) { for (unsigned i = 0; i < num_samples * 2; ++i) { @@ -483,6 +487,15 @@ vector AudioMixer::get_output(double pts, unsigned num_samples, Resamplin return samples_out; } +void AudioMixer::measure_bus_levels(unsigned bus_index, const vector &left, const vector &right) +{ + const float *ptrs[] = { left.data(), right.data() }; + { + lock_guard lock(audio_measure_mutex); + bus_r128[bus_index]->process(left.size(), const_cast(ptrs)); + } +} + void AudioMixer::update_meters(const vector &samples) { // Upsample 4x to find interpolated peak. @@ -492,7 +505,7 @@ void AudioMixer::update_meters(const vector &samples) vector interpolated_samples; interpolated_samples.resize(samples.size()); { - unique_lock lock(audio_measure_mutex); + lock_guard lock(audio_measure_mutex); while (peak_resampler.inp_count > 0) { // About four iterations. peak_resampler.out_data = &interpolated_samples[0]; @@ -509,7 +522,7 @@ void AudioMixer::update_meters(const vector &samples) deinterleave_samples(samples, &left, &right); float *ptrs[] = { left.data(), right.data() }; { - unique_lock lock(audio_measure_mutex); + lock_guard lock(audio_measure_mutex); r128.process(left.size(), ptrs); correlation.process_samples(samples); } @@ -519,7 +532,7 @@ void AudioMixer::update_meters(const vector &samples) void AudioMixer::reset_meters() { - unique_lock lock(audio_measure_mutex); + lock_guard lock(audio_measure_mutex); peak_resampler.reset(); peak = 0.0f; r128.reset(); @@ -533,13 +546,19 @@ void AudioMixer::send_audio_level_callback() return; } - unique_lock lock(audio_measure_mutex); + lock_guard lock(audio_measure_mutex); double loudness_s = r128.loudness_S(); double loudness_i = r128.integrated(); double loudness_range_low = r128.range_min(); double loudness_range_high = r128.range_max(); - audio_level_callback(loudness_s, to_db(peak), + vector bus_loudness; + bus_loudness.resize(input_mapping.buses.size()); + for (unsigned bus_index = 0; bus_index < bus_r128.size(); ++bus_index) { + bus_loudness[bus_index] = bus_r128[bus_index]->loudness_S(); + } + + audio_level_callback(loudness_s, to_db(peak), bus_loudness, loudness_i, loudness_range_low, loudness_range_high, gain_staging_db, to_db(final_makeup_gain), @@ -611,6 +630,17 @@ void AudioMixer::set_input_mapping(const InputMapping &new_input_mapping) } } + { + lock_guard lock(audio_measure_mutex); + bus_r128.resize(new_input_mapping.buses.size()); + for (unsigned bus_index = 0; bus_index < bus_r128.size(); ++bus_index) { + if (bus_r128[bus_index] == nullptr) { + bus_r128[bus_index].reset(new Ebu_r128_proc); + } + bus_r128[bus_index]->init(2, OUTPUT_FREQUENCY); + } + } + input_mapping = new_input_mapping; } diff --git a/audio_mixer.h b/audio_mixer.h index 75b468a..31611af 100644 --- a/audio_mixer.h +++ b/audio_mixer.h @@ -202,6 +202,7 @@ public: } typedef std::function bus_level_lufs, float global_level_lufs, float range_low_lufs, float range_high_lufs, float gain_staging_db, float final_makeup_gain_db, float correlation)> audio_level_callback_t; @@ -229,6 +230,7 @@ private: void reset_alsa_mutex_held(DeviceSpec device_spec); std::map get_devices_mutex_held() const; void update_meters(const std::vector &samples); + void measure_bus_levels(unsigned bus_index, const std::vector &left, const std::vector &right); void send_audio_level_callback(); unsigned num_cards; @@ -273,6 +275,12 @@ private: CorrelationMeasurer correlation; // Under audio_measure_mutex. Resampler peak_resampler; // Under audio_measure_mutex. std::atomic peak{0.0f}; + + // Under audio_measure_mutex. Note that Ebu_r128_proc has a broken + // copy constructor (it uses the default, but holds arrays), + // so we can't just use raw Ebu_r128_proc elements, but need to use + // unique_ptrs. + std::vector> bus_r128; }; #endif // !defined(_AUDIO_MIXER_H) diff --git a/mainwindow.cpp b/mainwindow.cpp index 28f0393..c1a3836 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -217,7 +217,7 @@ void MainWindow::mixer_created(Mixer *mixer) global_mixer->get_audio_mixer()->set_compressor_enabled(state == Qt::Checked); }); connect(ui->reset_meters_button, &QPushButton::clicked, this, &MainWindow::reset_meters_button_clicked); - mixer->get_audio_mixer()->set_audio_level_callback(bind(&MainWindow::audio_level_callback, this, _1, _2, _3, _4, _5, _6, _7, _8)); + mixer->get_audio_mixer()->set_audio_level_callback(bind(&MainWindow::audio_level_callback, this, _1, _2, _3, _4, _5, _6, _7, _8, _9)); struct sigaction act; memset(&act, 0, sizeof(act)); @@ -240,15 +240,18 @@ void MainWindow::setup_audio_miniview() delete item->widget(); delete item; } + audio_miniviews.clear(); // Set up brand new ones from the input mapping. InputMapping mapping = global_mixer->get_audio_mixer()->get_input_mapping(); + audio_miniviews.resize(mapping.buses.size()); for (unsigned bus_index = 0; bus_index < mapping.buses.size(); ++bus_index) { QWidget *channel = new QWidget(this); Ui::AudioMiniView *ui_audio_miniview = new Ui::AudioMiniView; ui_audio_miniview->setupUi(channel); ui_audio_miniview->bus_desc_label->setFullText( QString::fromStdString(mapping.buses[bus_index].name)); + audio_miniviews[bus_index] = ui_audio_miniview; // TODO: Set the fader position. ui->faders->addWidget(channel); @@ -396,7 +399,8 @@ void MainWindow::reset_meters_button_clicked() ui->peak_display->setStyleSheet(""); } -void MainWindow::audio_level_callback(float level_lufs, float peak_db, float global_level_lufs, +void MainWindow::audio_level_callback(float level_lufs, float peak_db, vector bus_level_lufs, + float global_level_lufs, float range_low_lufs, float range_high_lufs, float gain_staging_db, float final_makeup_gain_db, float correlation) @@ -413,6 +417,12 @@ void MainWindow::audio_level_callback(float level_lufs, float peak_db, float glo post_to_main_thread([=]() { ui->vu_meter->set_level(level_lufs); + for (unsigned bus_index = 0; bus_index < bus_level_lufs.size(); ++bus_index) { + if (bus_index < audio_miniviews.size()) { + audio_miniviews[bus_index]->vu_meter_meter->set_level( + bus_level_lufs[bus_index]); + } + } ui->lra_meter->set_levels(global_level_lufs, range_low_lufs, range_high_lufs); ui->correlation_meter->set_correlation(correlation); diff --git a/mainwindow.h b/mainwindow.h index a930cd9..b93470a 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -64,13 +64,14 @@ private: void report_disk_space(off_t free_bytes, double estimated_seconds_left); // Called from the mixer. - void audio_level_callback(float level_lufs, float peak_db, float global_level_lufs, float range_low_lufs, float range_high_lufs, float gain_staging_db, float final_makeup_gain_db, float correlation); + void audio_level_callback(float level_lufs, float peak_db, std::vector bus_level_lufs, float global_level_lufs, float range_low_lufs, float range_high_lufs, float gain_staging_db, float final_makeup_gain_db, float correlation); std::chrono::steady_clock::time_point last_audio_level_callback; Ui::MainWindow *ui; QLabel *disk_free_label; QPushButton *transition_btn1, *transition_btn2, *transition_btn3; std::vector previews; + std::vector audio_miniviews; int current_wb_pick_display = -1; }; -- 2.39.2