buffered, tick-based audio generation
parent
c1e73b922a
commit
96c3c3bd19
|
@ -64,6 +64,8 @@ void AudioEngine::play(std::shared_ptr<Project> p) {
|
|||
output->setBufferSize(sampleRate*4*(10/1000)); // 10ms
|
||||
output->start(this);
|
||||
|
||||
for (auto& b : buffer) b.reserve(static_cast<size_t>(sampleRate/4));
|
||||
|
||||
mode = Playing;
|
||||
}, Qt::QueuedConnection);
|
||||
}
|
||||
|
@ -77,39 +79,44 @@ void AudioEngine::stop() {
|
|||
}
|
||||
|
||||
qint64 AudioEngine::readData(char *data, qint64 maxlen) {
|
||||
static double time = 0;
|
||||
const constexpr qint64 smp = 2;
|
||||
const constexpr qint64 stride = smp*2;
|
||||
qint64 sr = maxlen;
|
||||
|
||||
while (sr >= stride) {
|
||||
if (bufPos >= buffer[0].size()) nextTick(); // process next tick when end of buffer reached
|
||||
if (bufPos >= buffer[0].size()) break; // if held up still, let the event loop run another cycle
|
||||
|
||||
int16_t* l = reinterpret_cast<int16_t*>(data);
|
||||
int16_t* r = reinterpret_cast<int16_t*>(data+smp);
|
||||
data += stride;
|
||||
|
||||
*l = static_cast<int16_t>(buffer[0][bufPos] * 32767);
|
||||
*r = static_cast<int16_t>(buffer[1][bufPos] * 32767);
|
||||
|
||||
bufPos++;
|
||||
sr -= stride;
|
||||
}
|
||||
|
||||
return maxlen - sr;
|
||||
}
|
||||
|
||||
void AudioEngine::nextTick() {
|
||||
bufPos = 0;
|
||||
|
||||
buffer[0].clear();
|
||||
buffer[1].clear();
|
||||
buffer[0].resize(480);
|
||||
buffer[1].resize(480);
|
||||
|
||||
static double time = 0;
|
||||
const double PI = std::atan(1)*4;
|
||||
const double SEMI = std::pow(2.0, 1.0/12.0);
|
||||
|
||||
double vol = std::pow(.5, 4);
|
||||
|
||||
while (sr >= 4) {
|
||||
sr -= 4;
|
||||
|
||||
int16_t* l = reinterpret_cast<int16_t*>(data);
|
||||
int16_t* r = reinterpret_cast<int16_t*>(data+2);
|
||||
|
||||
vol = std::pow(.5 + std::sin(time * PI*2) * .15, 4);
|
||||
|
||||
/**l = static_cast<int16_t>(std::sin(time * PI*2 * 440 * std::pow(SEMI, 4)) * 32767 * vol);
|
||||
*r = static_cast<int16_t>(std::sin(time * PI*2 * 440) * 32767 * vol);
|
||||
*l += static_cast<int16_t>(std::sin(time * PI*2 * 440 * std::pow(SEMI, 11.9)) * 32767 * vol);
|
||||
*r += static_cast<int16_t>(std::sin(time * PI*2 * 440 * std::pow(SEMI, 7)) * 32767 * vol);*/
|
||||
*l = 0;
|
||||
//*l += static_cast<int16_t>(std::sin(time * PI*2 * 440 * std::pow(SEMI, 1)) * 32767 * vol);
|
||||
//*l += static_cast<int16_t>(std::sin(time * PI*2 * 440 * std::pow(SEMI, 1.1)) * 32767 * vol);
|
||||
*l += static_cast<int16_t>(std::clamp(std::sin(time * PI*2 * 440 * std::pow(SEMI, time - 48)) * 3, -1.0, 1.0) * 32767 * vol);
|
||||
*r = *l;
|
||||
for (size_t i = 0; i < buffer[0].size(); i++) {
|
||||
buffer[0][i] = static_cast<float>(std::sin(time * PI*2 * 440 * std::pow(SEMI, 0)) * .25);
|
||||
buffer[1][i] = static_cast<float>(std::sin(time * PI*2 * 440 * std::pow(SEMI, 3)) * .25);
|
||||
|
||||
time += 1.0/sampleRate;
|
||||
data += 4;
|
||||
}
|
||||
while (sr > 0) {
|
||||
sr--;
|
||||
*data = 0;
|
||||
++data;
|
||||
}
|
||||
//qDebug() << "audio engine requested:" << maxlen;
|
||||
return maxlen;
|
||||
}
|
||||
|
|
|
@ -27,9 +27,14 @@ namespace Xybrid::Audio {
|
|||
std::unique_ptr<QAudioOutput> output;
|
||||
int sampleRate = 48000;
|
||||
|
||||
std::vector<float> buffer[2];
|
||||
size_t bufPos = 0;
|
||||
|
||||
PlaybackMode mode = Stopped;
|
||||
std::shared_ptr<Data::Project> project;
|
||||
|
||||
void postInit();
|
||||
void nextTick();
|
||||
public:
|
||||
static void init();
|
||||
inline constexpr PlaybackMode playbackMode() const { return mode; }
|
||||
|
@ -38,9 +43,9 @@ namespace Xybrid::Audio {
|
|||
void stop();
|
||||
|
||||
// QIODevice functions
|
||||
qint64 readData(char* data, qint64 maxlen) override;// {return 0;}
|
||||
qint64 readData(char* data, qint64 maxlen) override;
|
||||
qint64 writeData(const char*, qint64) override { return 0; }
|
||||
qint64 bytesAvailable() const override { return 1166; }
|
||||
qint64 bytesAvailable() const override { return 0; } // not actually used by QAudioOutput
|
||||
|
||||
signals:
|
||||
void playbackModeChanged(PlaybackMode);
|
||||
|
|
Loading…
Reference in New Issue