prep for double-buffer switchover...

master
zetaPRIME 2022-03-23 19:25:16 -04:00
parent be67e02004
commit 8b020975cc
5 changed files with 24 additions and 15 deletions

5
xybrid/audio/audio.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
namespace Xybrid::Audio {
typedef float bufferType;
}

View File

@ -406,8 +406,8 @@ qint64 AudioEngine::readData(char *data, qint64 maxlen) {
// convert non-interleaved floating point into interleaved int16 // convert non-interleaved floating point into interleaved int16
int16_t* l = reinterpret_cast<int16_t*>(data); int16_t* l = reinterpret_cast<int16_t*>(data);
int16_t* r = reinterpret_cast<int16_t*>(data+smp); int16_t* r = reinterpret_cast<int16_t*>(data+smp);
*l = static_cast<int16_t>(std::clamp(buffer[0][bufPos] * 32768.0f, -32767.0f, 32767.0f)); *l = static_cast<int16_t>(std::clamp(buffer[0][bufPos] * 32768.0, -32767.0, 32767.0));
*r = static_cast<int16_t>(std::clamp(buffer[1][bufPos] * 32768.0f, -32767.0f, 32767.0f)); *r = static_cast<int16_t>(std::clamp(buffer[1][bufPos] * 32768.0, -32767.0, 32767.0));
bufPos++; bufPos++;
data += stride; data += stride;
@ -470,7 +470,7 @@ void AudioEngine::nextTick() {
processNodes(); processNodes();
if (auto p = std::static_pointer_cast<AudioPort>(project->rootGraph->port(Port::Output, Port::Audio, 0)); p) { if (auto p = std::static_pointer_cast<AudioPort>(project->rootGraph->port(Port::Output, Port::Audio, 0)); p) {
p->pull(); p->pull();
size_t bufs = ts * sizeof(float); size_t bufs = ts * sizeof(bufferType);
memcpy(buffer[0].data(), p->bufL, bufs); memcpy(buffer[0].data(), p->bufL, bufs);
memcpy(buffer[1].data(), p->bufR, bufs); memcpy(buffer[1].data(), p->bufR, bufs);
} }
@ -654,7 +654,7 @@ void AudioEngine::nextTick() {
processNodes(); processNodes();
if (auto p = std::static_pointer_cast<AudioPort>(project->rootGraph->port(Port::Output, Port::Audio, 0)); p) { if (auto p = std::static_pointer_cast<AudioPort>(project->rootGraph->port(Port::Output, Port::Audio, 0)); p) {
p->pull(); p->pull();
size_t bufs = ts * sizeof(float); size_t bufs = ts * sizeof(bufferType);
memcpy(buffer[0].data(), p->bufL, bufs); memcpy(buffer[0].data(), p->bufL, bufs);
memcpy(buffer[1].data(), p->bufR, bufs); memcpy(buffer[1].data(), p->bufR, bufs);
} }

View File

@ -12,6 +12,8 @@
#include <QSemaphore> #include <QSemaphore>
#include <QWaitCondition> #include <QWaitCondition>
#include "audio/audio.h"
class QThread; class QThread;
namespace Xybrid::Data { namespace Xybrid::Data {
class Project; class Project;
@ -57,11 +59,12 @@ namespace Xybrid::Audio {
int sampleRate = 48000; int sampleRate = 48000;
int bufferMs = 64; int bufferMs = 64;
std::vector<float> buffer[2]; std::vector<bufferType> buffer[2];
size_t bufPos = 0; size_t bufPos = 0;
//std::vector<char> outBuf; //std::vector<char> outBuf;
static const constexpr size_t tickBufSize = (1024*1024*5); // 5mb should be enough // 32MiB really isn't much to take up for being a far higher ceiling than we should ever need
static const constexpr size_t tickBufSize = (1024*1024*32);
std::unique_ptr<size_t[]> tickBuf; std::unique_ptr<size_t[]> tickBuf;
std::atomic<size_t*> tickBufPtr; std::atomic<size_t*> tickBufPtr;
size_t* tickBufEnd; size_t* tickBufEnd;

View File

@ -14,7 +14,7 @@ void AudioPort::pull() {
size_t ts = audioEngine->curTickSize(); size_t ts = audioEngine->curTickSize();
size = ts; size = ts;
size_t s = sizeof(float) * ts; size_t s = sizeof(bufferType) * ts;
if (type == Input) { if (type == Input) {
if (connections.size() == 1) { if (connections.size() == 1) {
@ -26,7 +26,7 @@ void AudioPort::pull() {
goto done;//return; goto done;//return;
} }
} }
bufL = static_cast<float*>(audioEngine->tickAlloc(s*2)); bufL = static_cast<bufferType*>(audioEngine->tickAlloc(s*2));
bufR = &bufL[ts]; // for some reason just adding the size wonks out bufR = &bufL[ts]; // for some reason just adding the size wonks out
memset(bufL, 0, s*2); // clear buffers memset(bufL, 0, s*2); // clear buffers
@ -45,7 +45,7 @@ void AudioPort::pull() {
bufL = pt->bufL; bufL = pt->bufL;
bufR = pt->bufR; bufR = pt->bufR;
} else { // output without valid passthrough, just clear and prepare a blank buffer } else { // output without valid passthrough, just clear and prepare a blank buffer
bufL = static_cast<float*>(audioEngine->tickAlloc(s*2)); bufL = static_cast<bufferType*>(audioEngine->tickAlloc(s*2));
bufR = &bufL[ts]; bufR = &bufL[ts];
memset(bufL, 0, s*2); // clear buffers memset(bufL, 0, s*2); // clear buffers
} }

View File

@ -2,6 +2,7 @@
#include "data/node.h" #include "data/node.h"
#include "data/audioframe.h" #include "data/audioframe.h"
#include "audio/audio.h"
namespace Xybrid::Data { namespace Xybrid::Data {
class AudioPort : public Port { class AudioPort : public Port {
@ -13,21 +14,21 @@ namespace Xybrid::Data {
FrameRef(AudioPort* port, size_t at) : port(port), at(at) { } FrameRef(AudioPort* port, size_t at) : port(port), at(at) { }
public: public:
FrameRef& operator=(AudioFrame f) { FrameRef& operator=(AudioFrame f) {
port->bufL[at] = static_cast<float>(f.l); port->bufL[at] = static_cast<Audio::bufferType>(f.l);
port->bufR[at] = static_cast<float>(f.r); port->bufR[at] = static_cast<Audio::bufferType>(f.r);
return *this; return *this;
} }
FrameRef& operator+=(AudioFrame f) { FrameRef& operator+=(AudioFrame f) {
port->bufL[at] += static_cast<float>(f.l); port->bufL[at] += static_cast<Audio::bufferType>(f.l);
port->bufR[at] += static_cast<float>(f.r); port->bufR[at] += static_cast<Audio::bufferType>(f.r);
return *this; return *this;
} }
operator AudioFrame() const { return { port->bufL[at], port->bufR[at] }; } operator AudioFrame() const { return { port->bufL[at], port->bufR[at] }; }
AudioFrame operator*(AudioFrame o) const { return static_cast<AudioFrame>(*this) * o; } AudioFrame operator*(AudioFrame o) const { return static_cast<AudioFrame>(*this) * o; }
}; };
float* bufL; Audio::bufferType* bufL;
float* bufR; Audio::bufferType* bufR;
size_t size; size_t size;
AudioPort() = default; AudioPort() = default;