zetaPRIME 2020-02-20 03:58:36 -05:00
commit ac2e81ab10
9 changed files with 324 additions and 11 deletions

24
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,24 @@
pipeline {
agent any
stages {
stage('Clean Up') {
steps {
sh '''cd xybrid
make clean || true
rm Makefile || true'''
}
}
stage('qmake') {
steps {
sh '''cd xybrid
qmake'''
}
}
stage('Make') {
steps {
sh '''cd xybrid
make -j 17'''
}
}
}
}

View File

@ -19,6 +19,12 @@ using namespace Xybrid::Data;
#include <QTimer>
#include <QProcess>
#ifdef Q_OS_MAC
#define FFMPEG "/usr/local/bin/ffmpeg"
#else
#define FFMPEG "ffmpeg"
#endif
// zero-initialize
AudioEngine* Xybrid::Audio::audioEngine = nullptr;
@ -239,7 +245,7 @@ void AudioEngine::render(std::shared_ptr<Project> p, QString filename) {
param << "-f" << "mp3" << "-codec:a" << "libmp3lame"<< "-q:a" << "0"; // specify mp3, vbr v0
param << filename;
enc.start("ffmpeg", param);
enc.start(FFMPEG, param);
enc.waitForStarted();
std::vector<char> dat;

View File

@ -17,6 +17,22 @@ namespace Xybrid::Data {
l += o.l;
r += o.r;
}
inline AudioFrame operator+(double m) const { return {l+m, r+m}; }
inline void operator+=(double m) {
l += m;
r += m;
}
inline AudioFrame operator-(AudioFrame o) const { return {l-o.l, r-o.r}; }
inline void operator-=(AudioFrame o) {
l -= o.l;
r -= o.r;
}
inline AudioFrame operator-(double m) const { return {l-m, r-m}; }
inline void operator-=(double m) {
l -= m;
r -= m;
}
inline AudioFrame operator*(AudioFrame o) const { return {l*o.l, r*o.r}; }
inline void operator*=(AudioFrame o) {

View File

@ -22,8 +22,15 @@ using namespace Xybrid::Data;
#include <QDataStream>
#include <QEventLoop>
#include<QDebug>
#define qs QStringLiteral
#ifdef Q_OS_MAC
#define FFMPEG "/usr/local/bin/ffmpeg"
#else
#define FFMPEG "ffmpeg"
#endif
std::array<float, 2> Sample::plotBetween(size_t ch, size_t start, size_t end) const {
if (end < start) end = start;
@ -171,10 +178,18 @@ std::shared_ptr<Sample> Sample::fromFile(QString fileName) {
QStringList param;
param << "-v" << "quiet" << "-show_streams" << "-select_streams" << "a" << "-of" << "json";
param << fileName;
probe.start("ffprobe", param);
probe.waitForFinished();
auto doc = QJsonDocument::fromJson(probe.readAllStandardOutput());
#ifdef Q_OS_MAC
#define FFPROBE "/usr/local/bin/ffprobe"
#else
#define FFPROBE "ffprobe"
#endif
probe.start(FFPROBE, param);
if (!probe.waitForFinished()) {
qCritical() << (probe.errorString());
}
auto mystdout = probe.readAllStandardOutput();
auto mystderr = probe.readAllStandardError();
auto doc = QJsonDocument::fromJson(mystdout);
info = doc.object()["streams"].toArray().first().toObject();
}
if (!info.contains("sample_rate") || !info.contains("channels")) return nullptr; // no/invalid audio streams
@ -190,8 +205,9 @@ std::shared_ptr<Sample> Sample::fromFile(QString fileName) {
{
QProcess dec;
QStringList param;
param << "-i" << fileName << "-f" << "f32le" << "-acodec" << "pcm_f32le" << "-";
dec.start("ffmpeg", param);
dec.start(FFMPEG, param);
dec.waitForFinished();
raw = dec.readAllStandardOutput();
}

180
xybrid/nodes/effect/svf.cpp Normal file
View File

@ -0,0 +1,180 @@
/*
* Filename: svf.cpp
*
* Description: State Variable Filter
*
*
* Version:
* Created: Fri Nov 1 23:36:50 2019
* Revision: None
* Author: Rachel Fae Fox (foxiepaws),fox@foxiepa.ws
*
*/
#include "svf.h"
using Xybrid::Effects::SVF;
using namespace Xybrid::Data;
#include "nodelib/basics.h"
using namespace Xybrid::NodeLib;
#include "data/audioframe.h"
#include "data/porttypes.h"
#include "config/pluginregistry.h"
using namespace Xybrid::Config;
#include "audio/audioengine.h"
using namespace Xybrid::Audio;
#include "ui/patchboard/nodeobject.h"
#include "ui/gadgets/layoutgadget.h"
#include "ui/gadgets/togglegadget.h"
#include "ui/gadgets/knobgadget.h"
using namespace Xybrid::UI;
#include <cmath>
#include <QCborMap>
#define qs QStringLiteral
#define MIN(a,b) (a<b?a:b)
namespace {
bool _ = PluginRegistry::enqueueRegistration([] {
auto i = std::make_shared<PluginInfo>();
i->id = "gadget:svf";
i->displayName = "Filter";
i->category = "Effect";
i->createInstance = []{ return std::make_shared<SVF>(); };
PluginRegistry::registerPlugin(i);
});
}
SVF::SVF() { }
void SVF::init() {
auto sr = audioEngine->curSampleRate();
this->max_freq = ((float)sr / 4.0);
this->frequency = 12000;
this->resonance = 65;
addPort(Port::Input, Port::Audio, 0);
addPort(Port::Output, Port::Audio, 0);
}
void SVF::reset() {
release();
auto sr = audioEngine->curSampleRate();
}
void SVF::release() {
}
void SVF::process() {
auto in = std::static_pointer_cast<AudioPort>(port(Port::Input, Port::Audio, 0));
auto out = std::static_pointer_cast<AudioPort>(port(Port::Output, Port::Audio, 0));
in->pull();
out->pull();
if (this->fm != _off)
if (this->frequency > 0) { this->frequency-=0.1; }
size_t ts = audioEngine->curTickSize();
for (size_t f = 0; f < ts; f++) {
AudioFrame fCurrent = (*in)[f];
AudioFrame fOut;
if (this->fm == _off) {
(*out)[f] = fCurrent;
continue;
}
double res = this->resonance;
//double damp = MIN(2.0*(1.0 - pow(res, 0.25)), MIN(2.0, 2.0/freq - freq*0.5));
double q = sqrt(1.0 - atan(sqrt(res)) * 2.0 / PI);
double damp = sqrt(q);
//double freq = 2.0*sin(M_PI * MIN(0.25, this->frequency/audioEngine->curSampleRate()));
double freq = this->frequency / (audioEngine->curSampleRate() * 2 );
double in_l, in_r;
double low_l, low_r;
double band_l, band_r;
double high_l, high_r;
double notch_l, notch_r;
in_l = fCurrent.l;
in_r = fCurrent.r;
low_l=low.l;
low_r=low.r;
band_l=band.l;
band_r=band.r;
high_l=high.l;
high_r=high.r;
notch_l=notch.l;
notch_r=notch.r;
low_l = low_l + freq * band_l;
high_l = damp * in_l - low_l - q * band_l;
band_l = freq * high_l + band_l;
notch_l = high_l + low_l;
low_r = low_r + freq * band_r;
high_r = damp * in_r - low_r - q * band_r;
band_r = freq * high_r + band_r;
notch_r = high_r + low_r;
low_l = low_l + freq * band_l;
high_l = damp * in_l - low_l - q * band_l;
band_l = freq * high_l + band_l;
notch_l = high_l + low_l;
low_r = low_r + freq * band_r;
high_r = damp * in_r - low_r - q * band_r;
band_r = freq * high_r + band_r;
notch_r = high_r + low_r;
low = {low_l, low_r};
band = {band_l, band_r};
high = {high_l, high_r};
notch = {notch_l, notch_r};
switch (fm) {
case _low:
(*out)[f] = this->low;
break;
case _band:
(*out)[f] = this->band;
break;
case _high:
(*out)[f] = this->high;
break;
case _notch:
(*out)[f] = this->notch;
break;
}
}
}
void SVF::saveData(QCborMap& m) const {
//m[qs("frequency")] = QCborValue(frequency);
//m[qs("resonance")] = QCborValue(resonance);
}
void SVF::loadData(const QCborMap& m) {
//frequency = m.value("frequency").toDouble(frequency);
//resonance = m.value("resonance").toDouble(resonance);
}
void SVF::onGadgetCreated() {
if (!obj) return;
auto l = new LayoutGadget(obj);
//(new KnobGadget(l))->bind(freq)->setLabel(qs("Frequency Step"))->setRange(0.0, 10, 0.5)->setDefault(1.0);
(new KnobGadget(l))->bind(frequency)->setLabel(qs("Frequency"))->setRange(0.0, this->max_freq, 10.0)->setDefault(6440.0);
l->addSpacer();
(new KnobGadget(l))->bind(resonance)->setLabel(qs("Resonance"))->setRange(0.0, 100.0, 0.1)->setDefault(0.0);
l->addSpacer();
(new KnobGadget(l))->bind(fm)->setLabel(qs("Filter Mode"))->setRange(0,4,1)->setDefault(0);
}

60
xybrid/nodes/effect/svf.h Normal file
View File

@ -0,0 +1,60 @@
/*
* Filename: svf.h
*
* Description:
*
*
* Version:
* Created: Fri Nov 1 23:34:34 2019
* Revision: None
* Author: Rachel Fae Fox (foxiepaws),fox@foxiepa.ws
*
*/
#pragma once
#include <QContiguousCache>
#include "data/node.h"
#include "data/audioframe.h"
namespace Xybrid::Effects {
class SVF : public Data::Node {
enum FilterMode {_off, _low, _band, _high, _notch };
double frequency= 0.5;
double resonance = 0.0;
Xybrid::Data::AudioFrame low = 0.0;
Xybrid::Data::AudioFrame band = 0.0;
Xybrid::Data::AudioFrame high = 0.0;
Xybrid::Data::AudioFrame notch = 0.0;
FilterMode fm = _off;
// solve these in cons.
double max_freq;
double freq;
double q;
public:
SVF();
~SVF() override = default;
void init() override;
void reset() override;
void release() override;
void process() override;
//void onRename() override;
void saveData(QCborMap&) const override;
void loadData(const QCborMap&) override;
//void onUnparent(std::shared_ptr<Data::Graph>) override;
//void onParent(std::shared_ptr<Data::Graph>) override;
void onGadgetCreated() override;
//void drawCustomChrome(QPainter*, const QStyleOptionGraphicsItem*) override;
};
}

View File

@ -101,13 +101,14 @@ namespace {
#pragma GCC diagnostic pop
// for clang on freebsd (and possibly other non-apple llvm sources) it seems we need to specify more.
// wave function list(s)
const constexpr std::array waveFunc = {
const constexpr std::array<double(*)(double,double,double),3> waveFunc = {
&oscSaw,
&oscSine,
&oscPulse,
};
const std::array waveName = {
const std::array<QString,3> waveName = {
qs("saw"),
qs("sine"),
qs("pulse"),

View File

@ -22,9 +22,9 @@ using namespace Xybrid::Editing;
#include <QMenu>
#include <QMessageBox>
#include "mainwindow.h"
SampleListModel::SampleListModel(QObject* parent, MainWindow* window) : QAbstractItemModel (parent) {
this->window = window;
root = std::make_shared<DirectoryNode>();
@ -223,6 +223,7 @@ bool SampleListModel::canDropMimeData(const QMimeData *data, Qt::DropAction acti
return data->hasUrls() || data->hasFormat("xybrid-internal/x-sample-entry-move");
}
bool SampleListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row [[maybe_unused]], int column [[maybe_unused]], const QModelIndex &parent [[maybe_unused]]) {
if (data->hasUrls()) {
if (action == Qt::IgnoreAction) return true; // can accept type
@ -232,6 +233,7 @@ bool SampleListModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
if (!tdn->isDirectory()) tdn = tdn->parent;
QString p = tdn->path();
QList<QUrl> urls = data->urls();
bool success = false;
for (auto u : urls) {

View File

@ -37,17 +37,25 @@ HEADERS += $$files(*.h, true) \
FORMS += $$files(*.ui, true)
RESOURCES += res/resources.qrc
unix:!macx {
freebsd-clang {
DEFINES += WITH_BOOST
LIBS += -lboost_math_tr1
}
macx: {
DEFINES += WITH_BOOST
LIBS += -L/usr/local/Cellar/boost/1.70.0/lib/ -lboost_math_tr1
LIBS += -framework OpenGL
QMAKE_CXXFLAGS += -I/usr/local/Cellar/boost/1.70.0/include/
LIBS += -framework Foundation
SOURCES +=
HEADERS +=
QMAKE_CXXFLAGS += -g -I/usr/local/Cellar/boost/1.70.0/include/
}
# TODO: make this work.
CONFIG (boost) {
DEFINES += WITH_BOOST