#include <stdio.h>
#include <cmath>
+#include "db.h"
#include "flags.h"
#include "timebase.h"
set_compressor_enabled(global_flags.compressor_enabled);
set_limiter_enabled(global_flags.limiter_enabled);
set_final_makeup_gain_auto(global_flags.final_makeup_gain_auto);
+
+ // Generate a very simple, default input mapping.
+ InputMapping::Input input;
+ input.name = "Main";
+ input.input_source_type = InputSourceType::CAPTURE_CARD;
+ input.input_source_index = 0;
+ input.source_channel[0] = 0;
+ input.source_channel[1] = 1;
+
+ input_mapping.inputs.push_back(input);
}
void AudioMixer::reset_card(unsigned card_index)
num_samples,
rate_adjustment_policy);
}
+
+ float volume = from_db(cards[card_index].fader_volume_db);
if (card_index == 0) {
for (unsigned i = 0; i < num_samples * 2; ++i) {
- samples_out[i] = samples_card[i];
+ samples_out[i] = samples_card[i] * volume;
}
} else {
for (unsigned i = 0; i < num_samples * 2; ++i) {
- samples_out[i] += samples_card[i];
+ samples_out[i] += samples_card[i] * volume;
}
}
}
float ratio = 20.0f;
float attack_time = 0.5f;
float release_time = 20.0f;
- float makeup_gain = pow(10.0f, (ref_level_dbfs - (-40.0f)) / 20.0f); // +26 dB.
+ float makeup_gain = from_db(ref_level_dbfs - (-40.0f)); // +26 dB.
level_compressor.process(samples_out.data(), samples_out.size() / 2, threshold, ratio, attack_time, release_time, makeup_gain);
- gain_staging_db = 20.0 * log10(level_compressor.get_attenuation() * makeup_gain);
+ gain_staging_db = to_db(level_compressor.get_attenuation() * makeup_gain);
} else {
// Just apply the gain we already had.
- float g = pow(10.0f, gain_staging_db / 20.0f);
+ float g = from_db(gain_staging_db);
for (size_t i = 0; i < samples_out.size(); ++i) {
samples_out[i] *= g;
}
#if 0
printf("level=%f (%+5.2f dBFS) attenuation=%f (%+5.2f dB) end_result=%+5.2f dB\n",
- level_compressor.get_level(), 20.0 * log10(level_compressor.get_level()),
- level_compressor.get_attenuation(), 20.0 * log10(level_compressor.get_attenuation()),
- 20.0 * log10(level_compressor.get_level() * level_compressor.get_attenuation() * makeup_gain));
+ level_compressor.get_level(), to_db(level_compressor.get_level()),
+ level_compressor.get_attenuation(), to_db(level_compressor.get_attenuation()),
+ to_db(level_compressor.get_level() * level_compressor.get_attenuation() * makeup_gain));
#endif
// float limiter_att, compressor_att;
// The real compressor.
if (compressor_enabled) {
- float threshold = pow(10.0f, compressor_threshold_dbfs / 20.0f);
+ float threshold = from_db(compressor_threshold_dbfs);
float ratio = 20.0f;
float attack_time = 0.005f;
float release_time = 0.040f;
// Finally a limiter at -4 dB (so, -10 dBFS) to take out the worst peaks only.
// Note that since ratio is not infinite, we could go slightly higher than this.
if (limiter_enabled) {
- float threshold = pow(10.0f, limiter_threshold_dbfs / 20.0f);
+ float threshold = from_db(limiter_threshold_dbfs);
float ratio = 30.0f;
float attack_time = 0.0f; // Instant.
float release_time = 0.020f;
// limiter_att = limiter.get_attenuation();
}
- // printf("limiter=%+5.1f compressor=%+5.1f\n", 20.0*log10(limiter_att), 20.0*log10(compressor_att));
+ // printf("limiter=%+5.1f compressor=%+5.1f\n", to_db(limiter_att), to_db(compressor_att));
}
// At this point, we are most likely close to +0 LU, but all of our
// something we get out per-sample.
//
// Note that there's a feedback loop here, so we choose a very slow filter
- // (half-time of 100 seconds).
+ // (half-time of 30 seconds).
double target_loudness_factor, alpha;
double loudness_lu = loudness_lufs - ref_level_lufs;
- double current_makeup_lu = 20.0f * log10(final_makeup_gain);
- target_loudness_factor = pow(10.0f, -loudness_lu / 20.0f);
+ double current_makeup_lu = to_db(final_makeup_gain);
+ target_loudness_factor = final_makeup_gain * from_db(-loudness_lu);
// If we're outside +/- 5 LU uncorrected, we don't count it as
// a normal signal (probably silence) and don't change the
} else {
// Formula adapted from
// https://en.wikipedia.org/wiki/Low-pass_filter#Simple_infinite_impulse_response_filter.
- const double half_time_s = 100.0;
+ const double half_time_s = 30.0;
const double fc_mul_2pi_delta_t = 1.0 / (half_time_s * OUTPUT_FREQUENCY);
alpha = fc_mul_2pi_delta_t / (fc_mul_2pi_delta_t + 1.0);
}
return samples_out;
}
+
+vector<string> AudioMixer::get_names() const
+{
+ vector<string> names;
+ for (unsigned card_index = 0; card_index < num_cards; ++card_index) {
+ const CaptureCard *card = &cards[card_index];
+ unique_lock<mutex> lock(card->audio_mutex);
+ names.push_back(card->name);
+ }
+ return names;
+}
+
+void AudioMixer::set_name(unsigned card_index, const string &name)
+{
+ CaptureCard *card = &cards[card_index];
+ unique_lock<mutex> lock(card->audio_mutex);
+ card->name = name;
+}
+
+void AudioMixer::set_input_mapping(const InputMapping &input_mapping)
+{
+ lock_guard<mutex> lock(mapping_mutex);
+ this->input_mapping = input_mapping;
+}
+
+InputMapping AudioMixer::get_input_mapping() const
+{
+ lock_guard<mutex> lock(mapping_mutex);
+ return input_mapping;
+}