summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2018-05-24 20:44:33 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2018-05-24 20:44:33 +0200
commitcb896a4fa1acd9167d3e7ee9f6336a63309eebde (patch)
tree650337e053b670ba1f67d8b2f6da03d43fb0cda0
parent5f3f9fabf5ad2e1cda638612c3cf863045765a3b (diff)
Add save/load of selections/regions in instruments.
-rw-r--r--src/canvastoolthreshold.cc12
-rw-r--r--src/canvastoolthreshold.h6
-rw-r--r--src/instrumentwidget.cc56
-rw-r--r--src/instrumentwidget.h2
-rw-r--r--src/project.cc121
-rw-r--r--src/project.h37
-rw-r--r--src/projectserialiser.cc56
-rw-r--r--src/samplesorter.cc3
-rw-r--r--src/samplesorter.h7
-rw-r--r--src/selection.cc12
-rw-r--r--src/selection.h4
-rw-r--r--src/selectioneditor.cc9
-rw-r--r--src/selectioneditor.h6
13 files changed, 311 insertions, 20 deletions
diff --git a/src/canvastoolthreshold.cc b/src/canvastoolthreshold.cc
index bafee70..a905766 100644
--- a/src/canvastoolthreshold.cc
+++ b/src/canvastoolthreshold.cc
@@ -28,15 +28,19 @@
#include <math.h>
+#include "project.h"
+
#define mapX(x) canvas->mapX(x)
#define mapY(x) canvas->mapY(x)
#define unmapX(x) canvas->unmapX(x)
#define unmapY(x) canvas->unmapY(x)
-CanvasToolThreshold::CanvasToolThreshold(Canvas* c)
+CanvasToolThreshold::CanvasToolThreshold(Canvas* c, Instrument& instrument)
+ : instrument(instrument)
{
canvas = c;
- threshold = 0.5;
+ threshold = instrument.getThreshold();
+
threshold_is_moving = false;
colThreshold = QColor(255, 127, 127);
@@ -72,7 +76,7 @@ bool CanvasToolThreshold::mouseMoveEvent(QMouseEvent* event)
canvas->update();
emit thresholdChanging(threshold);
-
+ instrument.setThreshold(threshold);
return true;
}
@@ -117,7 +121,7 @@ bool CanvasToolThreshold::mouseReleaseEvent(QMouseEvent* event)
canvas->update();
emit thresholdChanged(threshold);
-
+ instrument.setThreshold(threshold);
return true;
}
}
diff --git a/src/canvastoolthreshold.h b/src/canvastoolthreshold.h
index ddb1a85..936bf68 100644
--- a/src/canvastoolthreshold.h
+++ b/src/canvastoolthreshold.h
@@ -32,12 +32,14 @@
#include "canvas.h"
+class Instrument;
+
class CanvasToolThreshold
: public CanvasTool
{
Q_OBJECT
public:
- CanvasToolThreshold(Canvas* canvas);
+ CanvasToolThreshold(Canvas* canvas, Instrument& instrument);
QString name() { return tr("Threshold"); }
bool mouseMoveEvent(QMouseEvent* event);
@@ -57,4 +59,6 @@ private:
QColor colThreshold;
QColor colThresholdMoving;
+
+ Instrument& instrument;
};
diff --git a/src/instrumentwidget.cc b/src/instrumentwidget.cc
index 641f690..f8b4046 100644
--- a/src/instrumentwidget.cc
+++ b/src/instrumentwidget.cc
@@ -92,7 +92,7 @@ InstrumentWidget::InstrumentWidget(Settings& settings, Instrument& instrument)
QToolBar* toolbar = addToolBar(tr("Tools"));
listen = new CanvasToolListen(canvaswidget->canvas, player);
addTool(toolbar, canvaswidget->canvas, listen);
- threshold = new CanvasToolThreshold(canvaswidget->canvas);
+ threshold = new CanvasToolThreshold(canvaswidget->canvas, instrument);
canvaswidget->canvas->tools.push_back(threshold);
tool_selections = new CanvasToolSelections(canvaswidget->canvas, selections,
selections_preview);
@@ -106,7 +106,7 @@ InstrumentWidget::InstrumentWidget(Settings& settings, Instrument& instrument)
canvaswidget->canvas, SLOT(update()));
addTool(toolbar, canvaswidget->canvas, tool_selections);
- sorter = new SampleSorter(selections, selections_preview);
+ sorter = new SampleSorter(selections, selections_preview, instrument);
connect(&selections, SIGNAL(added(sel_id_t)),
sorter, SLOT(addSelection(sel_id_t)));
connect(&selections_preview, SIGNAL(added(sel_id_t)),
@@ -142,6 +142,7 @@ InstrumentWidget::InstrumentWidget(Settings& settings, Instrument& instrument)
dockWidget->widget()->setLayout(new QVBoxLayout());
tabs = new QTabWidget(this);
+ tabs->setMinimumWidth(350);
tabs->addTab(createFilesTab(), tr("Files"));
generateTabId = tabs->addTab(createGenerateTab(), tr("Generate"));
tabs->addTab(createEditTab(), tr("Edit"));
@@ -166,6 +167,9 @@ InstrumentWidget::InstrumentWidget(Settings& settings, Instrument& instrument)
canvaswidget->yoffset->setValue(MAXVAL/2);
canvaswidget->xscale->setValue(0);
canvaswidget->xoffset->setValue(0);
+
+ // Update selections according to threshold
+ tool_selections->thresholdChanged(instrument.getThreshold());
}
InstrumentWidget::~InstrumentWidget()
@@ -203,12 +207,18 @@ QWidget* InstrumentWidget::createFilesTab()
extractor, SLOT(changeName(QString, QString)));
l->addWidget(filelist);
+ if(!instrument.getMasterFile().isEmpty())
+ {
+ loadFile(instrument.getMasterFile());
+ }
+
return w;
}
QWidget* InstrumentWidget::createEditTab()
{
- SelectionEditor* se = new SelectionEditor(selections);
+ selections = instrument.getSelections();
+ SelectionEditor* se = new SelectionEditor(selections, instrument);
connect(&selections, SIGNAL(added(sel_id_t)), se, SLOT(added(sel_id_t)));
connect(&selections, SIGNAL(updated(sel_id_t)), se, SLOT(updated(sel_id_t)));
@@ -216,9 +226,19 @@ QWidget* InstrumentWidget::createEditTab()
connect(&selections, SIGNAL(activeChanged(sel_id_t)),
se, SLOT(activeChanged(sel_id_t)));
+ connect(&selections, SIGNAL(added(sel_id_t)), this, SLOT(selectionChanged()));
+ connect(&selections, SIGNAL(updated(sel_id_t)), this, SLOT(selectionChanged()));
+ connect(&selections, SIGNAL(removed(sel_id_t)), this, SLOT(selectionChanged()));
+ connect(&selections, SIGNAL(activeChanged(sel_id_t)), this, SLOT(selectionChanged()));
+
return se;
}
+void InstrumentWidget::selectionChanged()
+{
+ instrument.setSelections(selections);
+}
+
static QSlider* createAttribute(QWidget* parent, QString name,
int range_from, int range_to)
{
@@ -281,41 +301,61 @@ QWidget* InstrumentWidget::createGenerateTab()
sorter, SLOT(setAttackLength(int)));
connect(slider_attacklength, SIGNAL(valueChanged(int)),
tool_selections, SLOT(autoCreateSelectionsPreview()));
- slider_attacklength->setValue(300);
+ slider_attacklength->setValue(instrument.getAttackLength());
+ connect(slider_attacklength, SIGNAL(valueChanged(int)),
+ this, SLOT(generateSlidersChanged()));
slider_spread = createAttribute(w, tr("Power spread:"), 1, 2000);
connect(slider_spread, SIGNAL(valueChanged(int)),
sorter, SLOT(setSpreadFactor(int)));
connect(slider_spread, SIGNAL(valueChanged(int)),
tool_selections, SLOT(autoCreateSelectionsPreview()));
- slider_spread->setValue(1000);
+ slider_spread->setValue(instrument.getPowerSpread());
+ connect(slider_spread, SIGNAL(valueChanged(int)),
+ this, SLOT(generateSlidersChanged()));
slider_hold = createAttribute(w, tr("Minimum size (samples):"), 0, 200000);
connect(slider_hold, SIGNAL(valueChanged(int)),
tool_selections, SLOT(holdChanged(int)));
connect(slider_hold, SIGNAL(valueChanged(int)),
tool_selections, SLOT(autoCreateSelectionsPreview()));
- slider_hold->setValue(100);
+ slider_hold->setValue(instrument.getMinimumSize());
+ connect(slider_hold, SIGNAL(valueChanged(int)),
+ this, SLOT(generateSlidersChanged()));
slider_falloff = createAttribute(w, tr("Falloff:"), 10, 5000);
connect(slider_falloff, SIGNAL(valueChanged(int)),
tool_selections, SLOT(noiseFloorChanged(int)));
connect(slider_falloff, SIGNAL(valueChanged(int)),
tool_selections, SLOT(autoCreateSelectionsPreview()));
- slider_falloff->setValue(300);
+ slider_falloff->setValue(instrument.getFalloff());
+ connect(slider_falloff, SIGNAL(valueChanged(int)),
+ this, SLOT(generateSlidersChanged()));
slider_fadelength = createAttribute(w, tr("Fadelength:"), 0, 2000);
connect(slider_fadelength, SIGNAL(valueChanged(int)),
tool_selections, SLOT(fadeoutChanged(int)));
connect(slider_fadelength, SIGNAL(valueChanged(int)),
tool_selections, SLOT(autoCreateSelectionsPreview()));
- slider_fadelength->setValue(666);
+ slider_fadelength->setValue(instrument.getFadeLength());
+ connect(slider_fadelength, SIGNAL(valueChanged(int)),
+ this, SLOT(generateSlidersChanged()));
l->addStretch();
return w;
}
+void InstrumentWidget::generateSlidersChanged()
+{
+ Project::RAIIBulkUpdate bulkUpdate(instrument.getProject());
+ instrument.setAttackLength(slider_attacklength->value());
+ instrument.setPowerSpread(slider_spread->value());
+ instrument.setMinimumSize(slider_hold->value());
+ instrument.setFalloff(slider_falloff->value());
+ instrument.setFadeLength(slider_fadelength->value());
+}
+
QWidget* InstrumentWidget::createExportTab()
{
QWidget* w = new QWidget();
diff --git a/src/instrumentwidget.h b/src/instrumentwidget.h
index 7a2b40d..2a5b3c5 100644
--- a/src/instrumentwidget.h
+++ b/src/instrumentwidget.h
@@ -73,6 +73,8 @@ public slots:
void playSamples();
void browse();
void tabChanged(int tabid);
+ void generateSlidersChanged();
+ void selectionChanged();
private:
QWidget* createFilesTab();
diff --git a/src/project.cc b/src/project.cc
index 8a1338c..5c45973 100644
--- a/src/project.cc
+++ b/src/project.cc
@@ -95,6 +95,127 @@ void Instrument::setFileList(const AudioFileList& file_list)
}
}
+std::size_t Instrument::getAttackLength() const
+{
+ return attack_length;
+}
+
+void Instrument::setAttackLength(std::size_t attack_length)
+{
+ if(this->attack_length == attack_length)
+ {
+ return;
+ }
+
+ {
+ Project::RAIIBulkUpdate bulkUpdate(project);
+ this->attack_length = attack_length;
+ }
+}
+
+std::size_t Instrument::getPowerSpread() const
+{
+ return power_spread;
+}
+
+void Instrument::setPowerSpread(std::size_t power_spread)
+{
+ if(this->power_spread == power_spread)
+ {
+ return;
+ }
+
+ {
+ Project::RAIIBulkUpdate bulkUpdate(project);
+ this->power_spread = power_spread;
+ }
+}
+
+std::size_t Instrument::getMinimumSize() const
+{
+ return minimum_size;
+}
+
+void Instrument::setMinimumSize(std::size_t minimum_size)
+{
+ if(this->minimum_size == minimum_size)
+ {
+ return;
+ }
+
+ {
+ Project::RAIIBulkUpdate bulkUpdate(project);
+ this->minimum_size = minimum_size;
+ }
+}
+
+std::size_t Instrument::getFalloff() const
+{
+ return falloff;
+}
+
+void Instrument::setFalloff(std::size_t falloff)
+{
+ if(this->falloff == falloff)
+ {
+ return;
+ }
+
+ {
+ Project::RAIIBulkUpdate bulkUpdate(project);
+ this->falloff = falloff;
+ }
+}
+
+std::size_t Instrument::getFadeLength() const
+{
+ return fade_length;
+}
+
+void Instrument::setFadeLength(std::size_t fade_length)
+{
+ if(this->fade_length == fade_length)
+ {
+ return;
+ }
+
+ {
+ Project::RAIIBulkUpdate bulkUpdate(project);
+ this->fade_length = fade_length;
+ }
+}
+
+float Instrument::getThreshold() const
+{
+ return threshold;
+}
+
+void Instrument::setThreshold(float threshold)
+{
+ if(this->threshold == threshold)
+ {
+ return;
+ }
+
+ {
+ Project::RAIIBulkUpdate bulkUpdate(project);
+ this->threshold = threshold;
+ }
+}
+
+Selections Instrument::getSelections() const
+{
+ return selections;
+}
+
+void Instrument::setSelections(const Selections& selections)
+{
+ {
+ Project::RAIIBulkUpdate bulkUpdate(project);
+ this->selections = selections;
+ }
+}
+
Project& Instrument::getProject()
{
return project;
diff --git a/src/project.h b/src/project.h
index 2b172ea..725e936 100644
--- a/src/project.h
+++ b/src/project.h
@@ -32,6 +32,7 @@
#include <QString>
#include "audioextractor.h"
+#include "selection.h"
class Project;
@@ -51,6 +52,27 @@ public:
AudioFileList getFileList() const;
void setFileList(const AudioFileList& file_list);
+ std::size_t getAttackLength() const;
+ void setAttackLength(std::size_t attack_length);
+
+ std::size_t getPowerSpread() const;
+ void setPowerSpread(std::size_t power_spread);
+
+ std::size_t getMinimumSize() const;
+ void setMinimumSize(std::size_t minimum_size);
+
+ std::size_t getFalloff() const;
+ void setFalloff(std::size_t falloff);
+
+ std::size_t getFadeLength() const;
+ void setFadeLength(std::size_t fade_length);
+
+ float getThreshold() const;
+ void setThreshold(float threshold);
+
+ Selections getSelections() const;
+ void setSelections(const Selections& selectios);
+
Project& getProject();
private:
@@ -58,9 +80,24 @@ private:
int id;
QString instrument_name;
+
+ // Files tab
QString master_file;
AudioFileList file_list;
+ // Generate tab
+ std::size_t attack_length{300};
+ std::size_t power_spread{1000};
+ std::size_t minimum_size{100};
+ std::size_t falloff{300};
+ std::size_t fade_length{666};
+
+ // Canvas
+ float threshold{0.5f};
+
+ // Edit tab
+ Selections selections;
+
Project& project;
};
diff --git a/src/projectserialiser.cc b/src/projectserialiser.cc
index 44f9ff7..f70e6dd 100644
--- a/src/projectserialiser.cc
+++ b/src/projectserialiser.cc
@@ -128,6 +128,15 @@ QString ProjectSerialiser::serialise(const Project& project)
for(const auto& i : project.instruments)
{
auto instrument = doc.createElement("instrument");
+
+ instrument.setAttribute("attack_length", (int)i.getAttackLength());
+ instrument.setAttribute("power_spread", (int)i.getPowerSpread());
+ instrument.setAttribute("minimum_size", (int)i.getMinimumSize());
+ instrument.setAttribute("falloff", (int)i.getFalloff());
+ instrument.setAttribute("fade_length", (int)i.getFadeLength());
+
+ instrument.setAttribute("threshold", i.getThreshold());
+
instruments.appendChild(instrument);
auto instrument_name = doc.createElement("instrument_name");
@@ -145,6 +154,24 @@ QString ProjectSerialiser::serialise(const Project& project)
file.setAttribute("master", i.master_file == f.first);
file_list.appendChild(file);
}
+
+ auto regions = doc.createElement("regions");
+ regions.setAttribute("nextid", i.selections.nextid);
+ regions.setAttribute("act", i.selections.act);
+ instrument.appendChild(regions);
+
+ for(auto r = i.selections.sels.begin(); r != i.selections.sels.end(); ++r)
+ {
+ auto region = doc.createElement("region");
+ region.setAttribute("id", (int)r.key());
+ region.setAttribute("from", (int)r.value().from);
+ region.setAttribute("to", (int)r.value().to);
+ region.setAttribute("fadein", (int)r.value().fadein);
+ region.setAttribute("fadeout", (int)r.value().fadeout);
+ region.setAttribute("energy", r.value().energy);
+ region.setAttribute("name", r.value().name);
+ regions.appendChild(region);
+ }
}
return doc.toString();
@@ -192,8 +219,33 @@ bool ProjectSerialiser::deserialise(const QString& data, Project& project)
}
file_list.push_back(qMakePair(file.text(), file["name"]));
}
- project.instruments.back().file_list = file_list;
- project.instruments.back().master_file = master_file;
+
+ instr.file_list = file_list;
+ instr.master_file = master_file;
+
+ instr.attack_length = instrument["attack_length"].toInt();
+ instr.power_spread = instrument["power_spread"].toInt();;
+ instr.minimum_size = instrument["minimum_size"].toInt();
+ instr.falloff = instrument["falloff"].toInt();
+ instr.fade_length = instrument["fade_length"].toInt();
+
+ instr.threshold = instrument["threshold"].toFloat();
+
+ auto selections = instrument("regions");
+ instr.selections.nextid = selections["nextid"].toInt();
+ instr.selections.act = selections["act"].toInt();
+
+ for(auto& selection : selections.children())
+ {
+ Selection s;
+ s.from = selection["from"].toInt();
+ s.to = selection["to"].toInt();
+ s.fadein = selection["fadein"].toInt();
+ s.fadeout = selection["fadeout"].toInt();
+ s.energy = selection["energy"].toFloat();
+ s.name = selection["name"];
+ instr.selections.sels[selection["id"].toInt()] = s;
+ }
}
return true;
diff --git a/src/samplesorter.cc b/src/samplesorter.cc
index 6158bfa..91bc6b4 100644
--- a/src/samplesorter.cc
+++ b/src/samplesorter.cc
@@ -36,9 +36,10 @@
#define MAXFLOAT (3.40282347e+38F)
#endif
-SampleSorter::SampleSorter(Selections& s, Selections& p)
+SampleSorter::SampleSorter(Selections& s, Selections& p, Instrument& instrument)
: selections(s)
, selections_preview(p)
+ , instrument(instrument)
{
setMouseTracking(true);
diff --git a/src/samplesorter.h b/src/samplesorter.h
index fa53a3f..496274d 100644
--- a/src/samplesorter.h
+++ b/src/samplesorter.h
@@ -30,12 +30,15 @@
#include <QVector>
#include "selection.h"
+class Instrument;
+
class SampleSorter
: public QWidget
{
Q_OBJECT
public:
- SampleSorter(Selections& selections, Selections& selections_preview);
+ SampleSorter(Selections& selections, Selections& selections_preview,
+ Instrument& instrument);
public slots:
void setWavData(const float* data, size_t size);
@@ -78,4 +81,6 @@ private:
sel_id_t sel_moving;
double spread;
+
+ Instrument& instrument;
};
diff --git a/src/selection.cc b/src/selection.cc
index 0b93fa2..e18e485 100644
--- a/src/selection.cc
+++ b/src/selection.cc
@@ -33,6 +33,18 @@ Selections::Selections()
act = SEL_NONE;
}
+Selections::Selections(const Selections& other)
+{
+ *this = other;
+}
+
+void Selections::operator=(const Selections& other)
+{
+ sels = other.sels;
+ nextid = other.nextid;
+ act = other.act;
+}
+
sel_id_t Selections::add(Selection selection)
{
sel_id_t id = nextid++;
diff --git a/src/selection.h b/src/selection.h
index 7d4d677..338b381 100644
--- a/src/selection.h
+++ b/src/selection.h
@@ -60,6 +60,9 @@ class Selections
Q_OBJECT
public:
Selections();
+ Selections(const Selections&);
+
+ void operator=(const Selections& other);
//! Add a new selection object. The new id is returned.
//! Adding a new selections will emit an added signal with the new id.
@@ -105,6 +108,7 @@ signals:
void activeChanged(sel_id_t id);
private:
+ friend class ProjectSerialiser;
QMap<sel_id_t, Selection> sels;
sel_id_t nextid;
sel_id_t act;
diff --git a/src/selectioneditor.cc b/src/selectioneditor.cc
index 98c6161..417059d 100644
--- a/src/selectioneditor.cc
+++ b/src/selectioneditor.cc
@@ -26,11 +26,13 @@
*/
#include "selectioneditor.h"
+#include "project.h"
+
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
-QLineEdit *createWidget(QString name, QWidget* parent)
+static QLineEdit *createWidget(QString name, QWidget* parent)
{
QHBoxLayout* l = new QHBoxLayout();
@@ -47,8 +49,9 @@ QLineEdit *createWidget(QString name, QWidget* parent)
return edt;
}
-SelectionEditor::SelectionEditor(Selections &s)
+SelectionEditor::SelectionEditor(Selections &s, Instrument& instrument)
: selections(s)
+ , instrument(instrument)
{
cur = SEL_NONE;
@@ -76,6 +79,8 @@ void SelectionEditor::updateSelection()
sel.name = name->text();
selections.update(cur, sel);
+
+ instrument.setSelections(selections);
}
void SelectionEditor::update()
diff --git a/src/selectioneditor.h b/src/selectioneditor.h
index feb9200..cdbf2de 100644
--- a/src/selectioneditor.h
+++ b/src/selectioneditor.h
@@ -31,12 +31,14 @@
#include <QLineEdit>
#include "selection.h"
+class Instrument;
+
class SelectionEditor
: public QWidget
{
Q_OBJECT
public:
- SelectionEditor(Selections& selections);
+ SelectionEditor(Selections& selections, Instrument& instrument);
public slots:
void added(sel_id_t id);
@@ -59,4 +61,6 @@ private:
QLineEdit* fadeout;
QLineEdit* energy;
QLineEdit* name;
+
+ Instrument& instrument;
};