Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
spectrum_analyzer_processor.h
1// SPDX-FileCopyrightText: © 2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include "dsp/audio_port.h"
7#include "dsp/engine.h"
8
9#include <QObject>
10#include <QTimer>
11#include <QVector>
12#include <QtQmlIntegration/qqmlintegration.h>
13
14#include <juce_wrapper.h>
15#include <kiss_fft.h>
16
17namespace zrythm::gui::qquick
18{
19
26class SpectrumAnalyzerProcessor : public QObject
27{
28 Q_OBJECT
29 Q_PROPERTY (
30 zrythm::dsp::AudioEngine * audioEngine READ audioEngine WRITE setAudioEngine
31 REQUIRED)
32 Q_PROPERTY (
33 zrythm::dsp::AudioPort * stereoPort READ stereoPort WRITE setStereoPort
34 NOTIFY stereoPortChanged REQUIRED)
35 Q_PROPERTY (
36 QVector<float> spectrumData READ spectrumData NOTIFY spectrumDataChanged)
37 Q_PROPERTY (int fftSize READ fftSize WRITE setFftSize NOTIFY fftSizeChanged)
38 Q_PROPERTY (
39 float sampleRate READ sampleRate WRITE setSampleRate NOTIFY sampleRateChanged)
40 QML_ELEMENT
42public:
43 explicit SpectrumAnalyzerProcessor (QObject * parent = nullptr);
44 ~SpectrumAnalyzerProcessor () override;
45
46 class KissFftConfig
47 {
48 public:
49 KissFftConfig (int fft_size)
50 {
51 cfg_ = kiss_fft_alloc (fft_size, 0, nullptr, nullptr);
52 }
54 {
55 if (cfg_ != nullptr)
56 {
57 kiss_fft_free (cfg_);
58 }
59 }
60 kiss_fft_cfg get_config () const { return cfg_; }
61
62 private:
63 kiss_fft_cfg cfg_{};
64 };
65
66 // ================================================================
67 // QML Interface
68 // ================================================================
69
70 dsp::AudioEngine * audioEngine () const { return audio_engine_; }
71 void setAudioEngine (dsp::AudioEngine * engine) { audio_engine_ = engine; }
72
73 dsp::AudioPort * stereoPort () const { return port_obj_; }
74 void setStereoPort (dsp::AudioPort * port_var);
75
76 QVector<float> spectrumData () const { return spectrum_data_; }
77 int fftSize () const { return static_cast<int> (fft_size_); }
78 float sampleRate () const { return sample_rate_; }
79
80 void setFftSize (int size);
81 void setSampleRate (float rate);
82
83 // Frequency scaling methods for QML
84 Q_INVOKABLE float getScaledFrequency (
85 int bin,
86 int num_bins,
87 float min_frequency,
88 float max_frequency) const;
89 Q_INVOKABLE float getFrequencyForBin (int bin, int num_bins) const;
90
91Q_SIGNALS:
92 void spectrumDataChanged ();
93 void fftSizeChanged ();
94 void sampleRateChanged ();
95 void stereoPortChanged ();
96
97 // ================================================================
98
99private:
100 void process_audio ();
101
102 // Port handling
103 QPointer<dsp::AudioPort> port_obj_;
104 std::optional<dsp::RingBufferOwningPortMixin::RingBufferReader> ring_reader_;
105
106 // FFT processing
107 QVector<float> spectrum_data_;
108 std::vector<float> left_buffer_;
109 std::vector<float> right_buffer_;
110 std::vector<float> mono_buffer_;
111 std::vector<float> new_spectrum_;
112
113 std::unique_ptr<KissFftConfig> fft_config_;
114 std::vector<kiss_fft_cpx> fft_in_;
115 std::vector<kiss_fft_cpx> fft_out_;
116
117 std::size_t fft_size_{};
118 float sample_rate_ = 44100.0f;
119 QTimer * update_timer_ = nullptr;
120
121 std::unique_ptr<juce::dsp::WindowingFunction<float>> windowing_func_;
122
123 // Temporary buffer for audio processing
124 juce::AudioSampleBuffer buffer_;
125
126 QPointer<dsp::AudioEngine> audio_engine_;
127};
128}
The audio engine.
Definition engine.h:22
Audio port specifics.
Definition audio_port.h:25