aluf/src/AudioEngine.h

127 lines
3.2 KiB
C++

// src/AudioEngine.h
#pragma once
#include <QObject>
#include <QAudioSink>
#include <QAudioDecoder>
#include <QBuffer>
#include <QFile>
#include <QTimer>
#include <QMutex>
#include <QThread>
#include <vector>
#include <complex>
#include <memory>
#include <atomic>
#include "Processor.h"
#include "complex_block.h"
// Shared Data Container (Thread-Safe via shared_ptr const correctness)
struct TrackData {
QByteArray pcmData; // For playback
std::vector<std::complex<double>> complexData; // For analysis
int sampleRate = 48000;
int frameSize = 4096;
bool valid = false;
};
// --- Audio Engine (Playback Only - High Priority) ---
class AudioEngine : public QObject {
Q_OBJECT
public:
AudioEngine(QObject* parent = nullptr);
~AudioEngine();
// Atomic position for Analyzer to poll (0.0 - 1.0)
std::atomic<double> m_atomicPosition{0.0};
// Shared pointer to current track data
std::shared_ptr<TrackData> getCurrentTrackData();
public slots:
void loadTrack(const QString& filePath);
void play();
void pause();
void stop();
void seek(float position);
// Called internally to clean up before thread exit
void cleanup();
signals:
void playbackFinished();
void trackLoaded(bool success);
void positionChanged(float position); // Restored signal
void analysisReady(float bpm, float confidence);
void trackDataChanged(std::shared_ptr<TrackData> data);
private slots:
void onBufferReady();
void onFinished();
void onError(QAudioDecoder::Error error);
void onTick();
private:
QAudioSink* m_sink = nullptr;
QBuffer m_buffer;
QAudioDecoder* m_decoder = nullptr;
QFile* m_fileSource = nullptr;
QTimer* m_playTimer = nullptr;
QString m_tempFilePath;
// Data Construction
QByteArray m_tempPcm;
int m_sampleRate = 48000;
// The authoritative track data
std::shared_ptr<TrackData> m_trackData;
mutable QMutex m_trackMutex;
};
// --- Audio Analyzer (DSP Only - Low Priority) ---
class AudioAnalyzer : public QObject {
Q_OBJECT
public:
AudioAnalyzer(QObject* parent = nullptr);
~AudioAnalyzer();
struct FrameData {
std::vector<float> freqs;
std::vector<float> db;
std::vector<float> primaryDb;
};
// Thread-safe pull for UI
bool getLatestSpectrum(std::vector<FrameData>& out);
public slots:
void start();
void stop();
void setTrackData(std::shared_ptr<TrackData> data);
void setAtomicPositionRef(std::atomic<double>* posRef);
void setDspParams(int frameSize, int hopSize);
void setNumBins(int n);
void setSmoothingParams(int granularity, int detail, float strength);
signals:
void spectrumAvailable();
private slots:
void processLoop();
private:
QTimer* m_timer = nullptr;
std::atomic<double>* m_posRef = nullptr;
std::shared_ptr<TrackData> m_data;
std::vector<Processor*> m_processors;
std::vector<Processor*> m_transientProcessors;
std::vector<Processor*> m_deepProcessors;
int m_frameSize = 4096;
int m_hopSize = 1024;
// Output Buffer
std::vector<FrameData> m_lastFrameDataVector;
mutable QMutex m_frameMutex;
};