xybrid/xybrid/data/porttypes.cpp

120 lines
4.0 KiB
C++

#include "porttypes.h"
using namespace Xybrid::Data;
#include "audio/audioengine.h"
using namespace Xybrid::Audio;
#include <QDebug>
void AudioPort::pull() {
auto t = audioEngine->curTickId();
if (tickUpdatedOn == t) return;
lock.lock();
if (tickUpdatedOn == t) { lock.unlock(); return; } // someone else got here before us
size_t ts = audioEngine->curTickSize();
size = ts;
size_t s = sizeof(bufferType) * ts;
if (type == Input) {
if (connections.size() == 1) {
// if this is a single connection, just repoint to source audio
if (auto p = std::static_pointer_cast<AudioPort>(connections[0].lock()); p && p->dataType() == Audio) {
p->pull();
bufL = p->bufL;
bufR = p->bufR;
goto done;//return;
}
}
bufL = static_cast<bufferType*>(audioEngine->tickAlloc(s*2));
bufR = &bufL[ts]; // for some reason just adding the size wonks out
memset(bufL, 0, s*2); // clear buffers
for (auto& c : connections) { // mix
if (auto p = std::static_pointer_cast<AudioPort>(c.lock()); p && p->dataType() == Audio) {
p->pull();
for (size_t i = 0; i < ts; i++) {
bufL[i] += p->bufL[i];
bufR[i] += p->bufR[i];
}
}
}
} else if (auto pt = std::static_pointer_cast<AudioPort>(passthroughTo.lock()); pt && pt->dataType() == Audio) {
// passthrough; ports abound
pt->pull();
bufL = pt->bufL;
bufR = pt->bufR;
} else { // output without valid passthrough, just clear and prepare a blank buffer
bufL = static_cast<bufferType*>(audioEngine->tickAlloc(s*2));
bufR = &bufL[ts];
memset(bufL, 0, s*2); // clear buffers
}
done:
tickUpdatedOn = t;
lock.unlock();
}
void CommandPort::pull() {
auto t = audioEngine->curTickId();
if (tickUpdatedOn == t) return;
lock.lock();
if (tickUpdatedOn == t) { lock.unlock(); return; } // someone else got here before us
size = 0;
if (type == Input) {
for (auto& c : connections) {
if (auto p = std::static_pointer_cast<CommandPort>(c.lock()); p && p->dataType() == Command) {
p->pull();
data = p->data; // just repoint to input's buffer
size = p->size;
break;
}
}
} else if (auto pt = std::static_pointer_cast<CommandPort>(passthroughTo.lock()); pt && pt->dataType() == Command) {
// valid passthrough
pt->pull();
data = pt->data; // again, just repoint
size = pt->size;
} // don't need an else case, size is already zero
tickUpdatedOn = t;
lock.unlock();
}
void CommandPort::push(std::vector<uint8_t> v) {
tickUpdatedOn = audioEngine->curTickId();
size = v.size();
data = static_cast<uint8_t*>(audioEngine->tickAlloc(size));
memcpy(data, v.data(), size);
}
void ParameterPort::pull() {
auto t = audioEngine->curTickId();
if (tickUpdatedOn == t) return;
lock.lock();
if (tickUpdatedOn == t) { lock.unlock(); return; } // someone else got here before us
data = nullptr;
if (type == Input) {
if (isConnected()) {
if (auto p = std::static_pointer_cast<ParameterPort>(connections[0].lock()); p) {
p->pull();
data = p->data;
size = p->size;
}
}
} else if (auto pt = std::static_pointer_cast<ParameterPort>(passthroughTo.lock()); pt && pt->dataType() == Parameter) {
pt->pull();
data = pt->data;
size = pt->size;
}
if (!data) { // no buffer pulled from input or passthrough; create a new one
size = audioEngine->curTickSize();
data = static_cast<double*>(audioEngine->tickAlloc(size * sizeof(double)));
std::fill_n(data, size, std::numeric_limits<double>::quiet_NaN());
}
tickUpdatedOn = t;
lock.unlock();
}