#include "timebase.h"
#include "stereocompressor.h"
#include "filter.h"
+#include "input_state.h"
+#include "correlation_measurer.h"
class H264Encoder;
class QSurface;
typedef std::function<void(float level_lufs, float peak_db,
float global_level_lufs, float range_low_lufs, float range_high_lufs,
- float auto_gain_staging_db)> audio_level_callback_t;
+ float gain_staging_db, float final_makeup_gain_db,
+ float correlation)> audio_level_callback_t;
void set_audio_level_callback(audio_level_callback_t callback)
{
audio_level_callback = callback;
return theme->get_channel_name(channel);
}
+ int get_channel_signal(unsigned channel) const
+ {
+ return theme->get_channel_signal(channel);
+ }
+
+ int map_signal(unsigned channel)
+ {
+ return theme->map_signal(channel);
+ }
+
+ void set_signal_mapping(int signal, int card)
+ {
+ return theme->set_signal_mapping(signal, card);
+ }
+
bool get_supports_set_wb(unsigned channel) const
{
return theme->get_supports_set_wb(channel);
locut_cutoff_hz = cutoff_hz;
}
+ void set_locut_enabled(bool enabled)
+ {
+ locut_enabled = enabled;
+ }
+
float get_limiter_threshold_dbfs()
{
return limiter_threshold_dbfs;
compressor_enabled = enabled;
}
- void reset_meters();
+ void set_gain_staging_db(float gain_db)
+ {
+ std::unique_lock<std::mutex> lock(compressor_mutex);
+ level_compressor_enabled = false;
+ gain_staging_db = gain_db;
+ }
- struct BufferedFrame {
- RefCountedFrame frame;
- unsigned field_number;
- };
+ void set_gain_staging_auto(bool enabled)
+ {
+ std::unique_lock<std::mutex> lock(compressor_mutex);
+ level_compressor_enabled = enabled;
+ }
+
+ void set_final_makeup_gain_db(float gain_db)
+ {
+ std::unique_lock<std::mutex> lock(compressor_mutex);
+ final_makeup_gain_auto = false;
+ final_makeup_gain = pow(10.0f, gain_db / 20.0f);
+ }
- BufferedFrame get_buffered_frame(int card, int history_pos)
+ void set_final_makeup_gain_auto(bool enabled)
{
- return buffered_frames[card][history_pos];
+ std::unique_lock<std::mutex> lock(compressor_mutex);
+ final_makeup_gain_auto = enabled;
+ }
+
+ void schedule_cut()
+ {
+ should_cut = true;
+ }
+
+ void reset_meters();
+
+ unsigned get_num_cards() const { return num_cards; }
+
+ std::string get_card_description(unsigned card_index) const {
+ assert(card_index < num_cards);
+ return cards[card_index].usb->get_description();
}
private:
};
CaptureCard cards[MAX_CARDS]; // protected by <bmusb_mutex>
- // For each card, the last three frames (or fields), with 0 being the
- // most recent one. Note that we only need the actual history if we have
- // interlaced output (for deinterlacing), so if we detect progressive input,
- // we immediately clear out all history and all entries will point to the same
- // frame.
- BufferedFrame buffered_frames[MAX_CARDS][FRAME_HISTORY_LENGTH];
+ InputState input_state;
class OutputChannel {
public:
std::thread mixer_thread;
std::thread audio_thread;
std::atomic<bool> should_quit{false};
+ std::atomic<bool> should_cut{false};
audio_level_callback_t audio_level_callback = nullptr;
- std::mutex r128_mutex;
- Ebu_r128_proc r128; // Under r128_mutex.
+ std::mutex compressor_mutex;
+ Ebu_r128_proc r128; // Under compressor_mutex.
+ CorrelationMeasurer correlation; // Under compressor_mutex.
Resampler peak_resampler;
std::atomic<float> peak{0.0f};
- StereoFilter locut; // Default cutoff 150 Hz, 24 dB/oct.
+ StereoFilter locut; // Default cutoff 120 Hz, 24 dB/oct.
std::atomic<float> locut_cutoff_hz;
+ std::atomic<bool> locut_enabled{true};
// First compressor; takes us up to about -12 dBFS.
- StereoCompressor level_compressor;
- float last_gain_staging_db = 0.0f;
+ StereoCompressor level_compressor; // Under compressor_mutex. Used to set/override gain_staging_db if <level_compressor_enabled>.
+ float gain_staging_db = 0.0f; // Under compressor_mutex.
+ bool level_compressor_enabled = true; // Under compressor_mutex.
- static constexpr float ref_level_dbfs = -14.0f;
+ static constexpr float ref_level_dbfs = -14.0f; // Chosen so that we end up around 0 LU in practice.
+ static constexpr float ref_level_lufs = -23.0f; // 0 LU, more or less by definition.
StereoCompressor limiter;
std::atomic<float> limiter_threshold_dbfs{ref_level_dbfs + 4.0f}; // 4 dB.
std::atomic<float> compressor_threshold_dbfs{ref_level_dbfs - 12.0f}; // -12 dB.
std::atomic<bool> compressor_enabled{true};
+ double final_makeup_gain = 1.0; // Under compressor_mutex. Read/write by the user. Note: Not in dB, we want the numeric precision so that we can change it slowly.
+ bool final_makeup_gain_auto = true; // Under compressor_mutex.
+
std::unique_ptr<ALSAOutput> alsa;
struct AudioTask {