xybrid/xybrid/audio/audioengine.h

80 lines
2.2 KiB
C++

#pragma once
#include <memory>
#include <list>
#include <vector>
#include <atomic>
#include <QIODevice>
#include <QAudioOutput>
class QThread;
namespace Xybrid::Data {
class Project;
}
namespace Xybrid::Audio {
class AudioEngine : public QIODevice {
Q_OBJECT
explicit AudioEngine(QObject *parent = nullptr);
public:
enum PlaybackMode {
Stopped, // stopped
Playing, // playing track
Paused, // paused during playback
Previewing, // instrument live preview
Rendering, // rendering to file
};
private:
QThread* thread;
std::unique_ptr<QAudioOutput> output;
int sampleRate = 48000;
std::vector<float> buffer[2];
size_t bufPos = 0;
static const constexpr size_t tickBufSize = (1024*1024*5); // 5mb should be enough
std::unique_ptr<int[]> tickBuf;
std::atomic<int*> tickBufPtr;
int* tickBufEnd;
PlaybackMode mode = Stopped;
size_t tickId = 0;
std::shared_ptr<Data::Project> project;
// playback timing and position
float tempo = 140.0;
int seqPos;
int curRow;
int curTick;
double tickAcc; // accumulator for tick remainder
void postInit();
void initAudio(bool startNow = false);
void deinitAudio();
void nextTick();
public:
static void init();
inline constexpr PlaybackMode playbackMode() const { return mode; }
inline constexpr const std::shared_ptr<Data::Project>& playingProject() const { return project; }
void play(std::shared_ptr<Data::Project>);
void stop();
void* tickAlloc(size_t size);
inline size_t curTickSize() { return buffer[0].size(); }
// QIODevice functions
qint64 readData(char* data, qint64 maxlen) override;
qint64 writeData(const char*, qint64) override { return 0; }
qint64 bytesAvailable() const override { return 0; } // not actually used by QAudioOutput
volatile int note = 12*5;
signals:
void playbackModeChanged();
public slots:
};
extern AudioEngine* audioEngine;
}