MCPcopy Create free account
hub / github.com/0xShug0/audio.cpp / apply_activity_gate_in_place

Function apply_activity_gate_in_place

src/framework/audio/mixing.cpp:99–186  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

97}
98
99void apply_activity_gate_in_place(
100 std::vector<float> & samples,
101 const std::vector<float> & reference,
102 int channels,
103 int sample_rate,
104 float threshold_dbfs,
105 double window_seconds,
106 double margin_seconds,
107 double fade_seconds) {
108 if (channels <= 0 || sample_rate <= 0 || window_seconds <= 0.0 || margin_seconds < 0.0 || fade_seconds < 0.0) {
109 throw std::runtime_error("audio activity gate received invalid parameters");
110 }
111 if (samples.size() != reference.size() || samples.size() % static_cast<size_t>(channels) != 0) {
112 throw std::runtime_error("audio activity gate requires matching input and reference shapes");
113 }
114 const int64_t frames = static_cast<int64_t>(samples.size() / static_cast<size_t>(channels));
115 if (frames <= 0) {
116 return;
117 }
118 const int64_t window_frames =
119 std::max<int64_t>(1, static_cast<int64_t>(std::llround(window_seconds * static_cast<double>(sample_rate))));
120 const int64_t margin_frames =
121 std::max<int64_t>(0, static_cast<int64_t>(std::llround(margin_seconds * static_cast<double>(sample_rate))));
122 const int64_t fade_frames =
123 std::max<int64_t>(0, static_cast<int64_t>(std::llround(fade_seconds * static_cast<double>(sample_rate))));
124 const double threshold = std::pow(10.0, static_cast<double>(threshold_dbfs) / 20.0);
125 const double threshold_energy = threshold * threshold;
126 std::vector<uint8_t> active(static_cast<size_t>(frames), 0);
127 for (int64_t window_start = 0; window_start < frames; window_start += window_frames) {
128 const int64_t window_end = std::min(frames, window_start + window_frames);
129 double energy = 0.0;
130 int64_t count = 0;
131 for (int64_t frame = window_start; frame < window_end; ++frame) {
132 const size_t base = static_cast<size_t>(frame * channels);
133 for (int channel = 0; channel < channels; ++channel) {
134 const float sample = reference[base + static_cast<size_t>(channel)];
135 energy += static_cast<double>(sample) * static_cast<double>(sample);
136 ++count;
137 }
138 }
139 const double mean_energy = count > 0 ? energy / static_cast<double>(count) : 0.0;
140 if (mean_energy > threshold_energy) {
141 const int64_t begin = std::max<int64_t>(0, window_start - margin_frames);
142 const int64_t end = std::min<int64_t>(frames, window_end + margin_frames);
143 std::fill(
144 active.begin() + static_cast<std::ptrdiff_t>(begin),
145 active.begin() + static_cast<std::ptrdiff_t>(end),
146 static_cast<uint8_t>(1));
147 }
148 }
149
150 std::vector<int64_t> prev_active(static_cast<size_t>(frames), -1);
151 std::vector<int64_t> next_active(static_cast<size_t>(frames), frames);
152 int64_t prev = -1;
153 for (int64_t frame = 0; frame < frames; ++frame) {
154 if (active[static_cast<size_t>(frame)] != 0) {
155 prev = frame;
156 }

Callers 1

Calls 4

powFunction · 0.85
minFunction · 0.85
sizeMethod · 0.45
beginMethod · 0.45

Tested by

no test coverage detected