Files
2026-09-29 22:41:29 +08:00

63 lines
1.8 KiB
C++

#pragma once
#include <complex>
#include <cstddef>
#include <string>
#include <utility>
#include <vector>
namespace esp32_doa {
using Complex = std::complex<double>;
struct Config {
int sample_rate = 48000;
int channels = 8;
int nfft = 512;
int hop = 256;
double sound_speed_m_s = 343.0;
double radius_m = 0.056;
double min_frequency_hz = 500.0;
double max_frequency_hz = 4000.0;
int grid_points = 360;
double diagonal_loading = 1e-2;
std::vector<double> microphone_azimuths_deg = {
157.5, 202.5, 247.5, 292.5, 337.5, 22.5, 67.5, 112.5};
};
struct Stft {
int sample_count = 0;
int snapshots = 0;
int bins = 0;
int channels = 0;
// Layout is [snapshot][frequency bin][channel].
std::vector<Complex> spectra;
Complex &at(int snapshot, int frequency, int channel);
const Complex &at(int snapshot, int frequency, int channel) const;
};
struct DoaResult {
double angle_degrees = 0.0;
double peak_sharpness = 0.0;
std::vector<double> spectrum;
};
struct MvdrResult {
std::vector<double> audio;
};
Stft analyze_stft(const std::vector<double> &audio, int sample_count,
const Config &config);
DoaResult srp_phat(const Stft &stft, const Config &config);
DoaResult norm_music(const Stft &stft, const Config &config);
MvdrResult mvdr(const Stft &stft, const Config &config, double angle_degrees);
// Convenience functions for callers that already have samples in row-major
// samples x channels form.
DoaResult estimate(const std::vector<double> &audio, int sample_count,
const Config &config, const std::string &algorithm);
MvdrResult beamform(const std::vector<double> &audio, int sample_count,
const Config &config, double angle_degrees);
} // namespace esp32_doa