mirror of
https://github.com/Boof2015/astra-mobile.git
synced 2026-08-12 05:10:52 +02:00
86 lines
2.6 KiB
C++
86 lines
2.6 KiB
C++
#pragma once
|
|
|
|
#include "dsp_utils.h"
|
|
#include <vector>
|
|
#include <cstdint>
|
|
|
|
namespace Visualizer {
|
|
|
|
struct OscilloscopeResult {
|
|
float triggerIndex;
|
|
int samplesToShow;
|
|
float detectedPitch;
|
|
};
|
|
|
|
// Circular buffer size (same as pulse-visualizer)
|
|
constexpr size_t OSCILLOSCOPE_BUFFER_SIZE = 32768;
|
|
|
|
class Oscilloscope {
|
|
public:
|
|
Oscilloscope();
|
|
|
|
// Configuration
|
|
void setSampleRate(float sampleRate);
|
|
void setPitchLock(bool enabled);
|
|
void setDisplaySamples(int samples);
|
|
|
|
// Push samples into circular buffer (continuous capture)
|
|
void pushSamples(const float* samples, size_t count);
|
|
|
|
// Process and find trigger point (uses circular buffer)
|
|
OscilloscopeResult process();
|
|
|
|
// Legacy: Process snapshot (for backwards compatibility)
|
|
OscilloscopeResult processSnapshot(const float* audioData, size_t length);
|
|
|
|
// Get current write position
|
|
size_t getWritePos() const { return writePos_; }
|
|
|
|
// Get samples from circular buffer (for rendering)
|
|
void getSamples(float* output, size_t startPos, size_t count) const;
|
|
|
|
// Get samples with sub-sample interpolation (preserves trigger precision)
|
|
void getSamplesInterpolated(float* output, float startPos, size_t count) const;
|
|
|
|
// Reset state
|
|
void reset();
|
|
|
|
private:
|
|
float sampleRate_;
|
|
bool pitchLock_;
|
|
int displaySamples_;
|
|
|
|
// Circular buffer for continuous audio
|
|
std::vector<float> circularBuffer_;
|
|
std::vector<float> filteredBuffer_;
|
|
size_t writePos_;
|
|
|
|
// Linear-phase FIR bandpass filter for stable trigger detection
|
|
DSP::FIRFilter bandpassFilter_;
|
|
float lastFilterPitch_; // Track pitch for filter redesign
|
|
|
|
// High shelf filter to reduce HF before pitch detection
|
|
DSP::BiquadFilter pitchAnalysisShelf_;
|
|
|
|
// Display filtering (high shelf + steep lowpass)
|
|
DSP::BiquadFilter displayShelf_; // High shelf for display
|
|
DSP::BiquadFilter displayLowpass1_; // First stage of cascaded lowpass
|
|
DSP::BiquadFilter displayLowpass2_; // Second stage (4th order total = 24dB/oct)
|
|
std::vector<float> displayBuffer_; // Lowpass filtered samples for tracking
|
|
std::vector<float> visualBuffer_; // Visual-only samples (display shelf applied)
|
|
|
|
// Pitch detection lowpass (after existing high shelf)
|
|
DSP::BiquadFilter pitchLowpass1_; // First stage
|
|
DSP::BiquadFilter pitchLowpass2_; // Second stage
|
|
|
|
float lastTrigger_;
|
|
float smoothedPitch_;
|
|
int pitchSamplesProcessed_; // Track samples for adaptive smoothing
|
|
|
|
// Internal helpers
|
|
void updateFiltered();
|
|
float findTriggerBackwards(size_t target, size_t range);
|
|
};
|
|
|
|
} // namespace Visualizer
|