Merge branch 'master' of https://git.foxiepa.ws/foxiepaws/xybrid
commit
ac2e81ab10
|
@ -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'''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -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"),
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue