MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ find_onset_positions()

std::vector< size_t > MayaFlux::Yantra::find_onset_positions ( std::span< const double >  data,
uint32_t  window_size,
uint32_t  hop_size,
double  threshold = 0.1 
)

Find onset positions using spectral flux.

Detects rapid increases in spectral energy (transients/attacks).

Parameters
dataInput data span
window_sizeFFT window size
hop_sizeHop between analysis frames
thresholdFlux threshold for onset detection
Returns
Vector of sample positions where onsets occur

Definition at line 267 of file AnalysisHelper.cpp.

272{
273 const size_t num_windows = (data.size() - window_size) / hop_size + 1;
274
275 if (num_windows < 2) {
276 return {};
277 }
278
279 std::vector<double> flux_values(num_windows - 1);
280
281 Eigen::VectorXd hanning_window(window_size);
282 for (uint32_t i = 0; i < window_size; ++i) {
283 hanning_window(i) = 0.5 * (1.0 - std::cos(2.0 * M_PI * i / (window_size - 1)));
284 }
285
286 Eigen::VectorXcd prev_spectrum;
287
288 for (size_t i = 0; i < num_windows; ++i) {
289 const size_t start_idx = i * hop_size;
290 const size_t end_idx = std::min(start_idx + window_size, data.size());
291 auto window = data.subspan(start_idx, end_idx - start_idx);
292
293 Eigen::VectorXd windowed_data = Eigen::VectorXd::Zero(window_size);
294 for (size_t j = 0; j < window.size(); ++j) {
295 windowed_data(j) = window[j] * hanning_window(j);
296 }
297
298 Eigen::FFT<double> fft;
299 Eigen::VectorXcd spectrum;
300 fft.fwd(spectrum, windowed_data);
301
302 if (i > 0) {
303 double flux = 0.0;
304 for (int j = 0; j < spectrum.size(); ++j) {
305 double curr_mag = std::abs(spectrum(j));
306 double prev_mag = std::abs(prev_spectrum(j));
307 double diff = curr_mag - prev_mag;
308 if (diff > 0) {
309 flux += diff;
310 }
311 }
312 flux_values[i - 1] = flux;
313 }
314
315 prev_spectrum = spectrum;
316 }
317
318 std::vector<size_t> positions;
319
320 double max_flux = *std::max_element(flux_values.begin(), flux_values.end());
321 if (max_flux > 0.0) {
322 for (size_t i = 0; i < flux_values.size(); ++i) {
323 flux_values[i] /= max_flux;
324 }
325 }
326
327 for (size_t i = 1; i < flux_values.size() - 1; ++i) {
328 if (flux_values[i] > threshold && flux_values[i] > flux_values[i - 1] && flux_values[i] >= flux_values[i + 1]) {
329
330 size_t sample_pos = (i + 1) * hop_size;
331 positions.push_back(sample_pos);
332 }
333 }
334
335 return positions;
336}

References find_onset_positions().

Referenced by MayaFlux::detect_onsets(), MayaFlux::detect_onsets(), MayaFlux::detect_onsets_per_channel(), extract_onset_data(), and find_onset_positions().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: