summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2014-04-15 09:55:45 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2014-04-15 09:55:45 +0200
commit0fcacc1c3329e905228ceb80903f69561a7db732 (patch)
tree0d1d636d5e0b95b1d4554ad112aa63bfaa79e7e0
parenta0bff571893f9afd5e4eb84ac52755f851398601 (diff)
New selections model.
-rw-r--r--dgedit/Makefile.am3
-rw-r--r--dgedit/audioextractor.cc69
-rw-r--r--dgedit/audioextractor.h6
-rw-r--r--dgedit/canvastoolselections.cc115
-rw-r--r--dgedit/canvastoolselections.h13
-rw-r--r--dgedit/mainwindow.cc57
-rw-r--r--dgedit/mainwindow.h5
-rw-r--r--dgedit/samplesorter.cc247
-rw-r--r--dgedit/samplesorter.h36
-rw-r--r--dgedit/selection.cc106
-rw-r--r--dgedit/selection.h85
11 files changed, 388 insertions, 354 deletions
diff --git a/dgedit/Makefile.am b/dgedit/Makefile.am
index 2925f74..d79df6c 100644
--- a/dgedit/Makefile.am
+++ b/dgedit/Makefile.am
@@ -23,7 +23,8 @@ dgedit_SOURCES = \
itemeditor.cc \
mainwindow.cc \
mipmap.cc \
- samplesorter.cc
+ samplesorter.cc \
+ selection.cc
EXTRA_DIST = \
audioextractor.h \
diff --git a/dgedit/audioextractor.cc b/dgedit/audioextractor.cc
index 8395b7f..5e37312 100644
--- a/dgedit/audioextractor.cc
+++ b/dgedit/audioextractor.cc
@@ -37,13 +37,12 @@ typedef struct {
float *data;
} audiodata_t;
-AudioExtractor::AudioExtractor(QObject *parent)
- : QObject(parent)
+AudioExtractor::AudioExtractor(Selections &s, QObject *parent)
+ : QObject(parent), selections(s)
{
}
-void AudioExtractor::exportSelections(Selections selections,
- Levels levels)
+void AudioExtractor::exportSelections()
{
// Open all input audio files:
audiodata_t audiodata[audiofiles.size()];
@@ -67,9 +66,10 @@ void AudioExtractor::exportSelections(Selections selections,
}
idx = 0;
- QMap<int, Selection>::iterator si = selections.begin();
- while(si != selections.end()) {
- Selection &sel = *si;
+ QVector<sel_id_t> sels = selections.ids();
+ QVector<sel_id_t>::iterator si = sels.begin();
+ while(si != sels.end()) {
+ Selection sel = selections.get(*si);
size_t offset = sel.from;
size_t size = sel.to - sel.from;
size_t fadein = sel.fadein;
@@ -161,19 +161,23 @@ void AudioExtractor::exportSelections(Selections selections,
QDomElement samples = doc.createElement("samples");
instrument.appendChild(samples);
+ {
// Do the adding to the xml file one sample at the time.
int index = 0;
- QMap<int, Selection>::iterator i = selections.begin();
- while(i != selections.end()) {
+ QVector<sel_id_t>::iterator si = sels.begin();
+ while(si != sels.end()) {
index++;
- i->name = prefix + "-" + QString::number(index);
+ Selection i = selections.get(*si);
+ i.name = prefix + "-" + QString::number(index);
QDomElement sample = doc.createElement("sample");
- sample.setAttribute("name", i->name);
- sample.setAttribute("power", QString::number(i->energy));
+ sample.setAttribute("name", i.name);
+ sample.setAttribute("power", QString::number(i.energy));
samples.appendChild(sample);
+ selections.update(*si, i);
+
int channelnum = 1; // Filechannel numbers are 1-based.
AudioFileList::iterator j = audiofiles.begin();
while(j != audiofiles.end()) {
@@ -191,47 +195,10 @@ void AudioExtractor::exportSelections(Selections selections,
j++;
}
- i++;
+ si++;
}
-
- QDomElement velocities = doc.createElement("velocities");
- instrument.appendChild(velocities);
-
- Levels::iterator k = levels.begin();
- while(k != levels.end()) {
-
- Levels::iterator nxt = k;
- nxt++;
- float next;
- if(nxt == levels.end()) next = 1.0;
- else next = nxt->velocity;
-
-
- QDomElement velocity = doc.createElement("velocity");
- velocity.setAttribute("lower", k->velocity);
- velocity.setAttribute("upper", next);
- velocities.appendChild(velocity);
-
- QMap<float, Selection>::iterator i = k->selections.begin();
- while(i != k->selections.end()) {
-
- QMap<int, Selection>::iterator j = selections.begin();
- while(j != selections.end()) {
- if(i->from == j->from && i->to == j->to) {
- QDomElement sampleref = doc.createElement("sampleref");
- sampleref.setAttribute("name", j->name);
- sampleref.setAttribute("probability",
- 1.0 / (double)k->selections.size());
- velocity.appendChild(sampleref);
- }
- j++;
- }
- i++;
- }
-
- k++;
}
-
+
QFile xmlfile(exportpath + "/" + prefix + "/" + prefix + ".xml");
xmlfile.open(QIODevice::WriteOnly);
xmlfile.write(doc.toByteArray());
diff --git a/dgedit/audioextractor.h b/dgedit/audioextractor.h
index f18860b..a91fe6c 100644
--- a/dgedit/audioextractor.h
+++ b/dgedit/audioextractor.h
@@ -41,17 +41,19 @@ typedef QLinkedList< QPair<QString, QString> > AudioFileList;
class AudioExtractor : public QObject {
Q_OBJECT
public:
- AudioExtractor(QObject *parent);
+ AudioExtractor(Selections &selections, QObject *parent);
public slots:
void addFile(QString file, QString name);
void changeName(QString file, QString name);
void removeFile(QString file, QString name);
- void exportSelections(Selections selections, Levels levels);
+
+ void exportSelections();
void setExportPath(const QString &path);
void setOutputPrefix(const QString &prefix);
private:
+ Selections &selections;
AudioFileList audiofiles;
QString exportpath;
QString prefix;
diff --git a/dgedit/canvastoolselections.cc b/dgedit/canvastoolselections.cc
index 5868b1f..30f8970 100644
--- a/dgedit/canvastoolselections.cc
+++ b/dgedit/canvastoolselections.cc
@@ -34,17 +34,15 @@
#define unmapX(x) canvas->unmapX(x)
#define unmapY(x) canvas->unmapY(x)
-CanvasToolSelections::CanvasToolSelections(Canvas *c)
+CanvasToolSelections::CanvasToolSelections(Canvas *c, Selections &s)
+ : selections(s)
{
threshold = 0.5; // Default from CanvasToolThreshold
canvas = c;
- // data = canvas->data;
- // size = canvas->size;
selection_is_moving_left = false;
selection_is_moving_right = false;
- active_selection = NULL;
colSelBg = QColor(255, 0, 0, 60);
colSel = QColor(255, 0, 0, 160);
@@ -53,45 +51,37 @@ CanvasToolSelections::CanvasToolSelections(Canvas *c)
}
-void CanvasToolSelections::setActiveSelection(Selection s)
-{
- QMap<int, Selection>::iterator i = _selections.begin();
- while(i != _selections.end()) {
- if(s.from == i.value().from &&
- s.to == i.value().to) active_selection = &i.value();
- i++;
- }
-
- canvas->update();
- emit activeSelectionChanged(s);
-}
-
bool CanvasToolSelections::mouseMoveEvent(QMouseEvent *event)
{
+ sel_id_t active_selection = selections.active();
+ Selection act_sel = selections.get(active_selection);
+
if(selection_is_moving_left) {
float val = unmapX(event->x());
- if(val > active_selection->to) val = active_selection->to - 1;
- active_selection->from = val;
+ if(val > act_sel.to) val = act_sel.to - 1;
+ act_sel.from = val;
+ selections.update(active_selection, act_sel);
canvas->update();
- emit selectionsChanged(_selections);
return true;
}
if(selection_is_moving_right) {
float val = unmapX(event->x());
- if(val < active_selection->from) val = active_selection->from + 1;
- active_selection->to = val;
+ if(val < act_sel.from) val = act_sel.from + 1;
+ act_sel.to = val;
+ selections.update(active_selection, act_sel);
canvas->update();
- emit selectionsChanged(_selections);
return true;
}
if(event->button() != Qt::LeftButton) {
// Check if a selection is being dragged.
- QMap<int, Selection>::iterator i = _selections.begin();
- while(i != _selections.end()) {
- if(abs(event->x() - mapX(i.value().from)) < 2
- || abs(event->x() - mapX(i.value().to)) < 2) {
+ QVector<sel_id_t> ids = selections.ids();
+ QVector<sel_id_t>::iterator i = ids.begin();
+ while(i != ids.end()) {
+ Selection sel = selections.get(*i);
+ if(abs(event->x() - mapX(sel.from)) < 2
+ || abs(event->x() - mapX(sel.to)) < 2) {
canvas->setCursor(Qt::SplitHCursor);
return true;
}
@@ -106,19 +96,19 @@ bool CanvasToolSelections::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton) {
// Check if a selection is being dragged.
- QMap<int, Selection>::iterator i = _selections.begin();
- while(i != _selections.end()) {
- if(abs(event->x() - mapX(i.value().from)) < 2) {
- active_selection = &i.value();
+ QVector<sel_id_t> ids = selections.ids();
+ QVector<sel_id_t>::iterator i = ids.begin();
+ while(i != ids.end()) {
+ Selection sel = selections.get(*i);
+ if(abs(event->x() - mapX(sel.from)) < 2) {
+ selections.setActive(*i);
selection_is_moving_left = true;
- emit activeSelectionChanged(i.value());
return true;
}
- if(abs(event->x() - mapX(i.value().to)) < 2) {
- active_selection = &i.value();
+ if(abs(event->x() - mapX(sel.to)) < 2) {
+ selections.setActive(*i);
selection_is_moving_right = true;
- emit activeSelectionChanged(i.value());
return true;
}
@@ -126,13 +116,13 @@ bool CanvasToolSelections::mousePressEvent(QMouseEvent *event)
}
// Check if a selection is being selected.
- i = _selections.begin();
- while(i != _selections.end()) {
- if(event->x() > mapX(i.value().from) &&
- event->x() < mapX(i.value().to)) {
- active_selection = &i.value();
+ i = ids.begin();
+ while(i != ids.end()) {
+ Selection sel = selections.get(*i);
+ if(event->x() > mapX(sel.from) &&
+ event->x() < mapX(sel.to)) {
+ selections.setActive(*i);
canvas->update();
- emit activeSelectionChanged(i.value());
return true;
}
@@ -141,8 +131,9 @@ bool CanvasToolSelections::mousePressEvent(QMouseEvent *event)
// Make new selection
int from = unmapX(event->x());
- _selections[from] = Selection(from, from);
- active_selection = &_selections[from];
+ Selection new_selection(from, from);
+ sel_id_t id = selections.add(new_selection);
+ selections.setActive(id);
selection_is_moving_right = true;
canvas->update();
return true;
@@ -170,21 +161,25 @@ void CanvasToolSelections::paintEvent(QPaintEvent *event, QPainter &painter)
{
int pos = unmapX(event->rect().x());
int width = unmapX(event->rect().width());
- QMap<int, Selection>::iterator i = _selections.begin();
- while(i != _selections.end()) {
- int from = i.value().from;
- int to = i.value().to;
- int fadein = i.value().fadein;
- int fadeout = i.value().fadeout;
+
+ QVector<sel_id_t> ids = selections.ids();
+ QVector<sel_id_t>::iterator i = ids.begin();
+ while(i != ids.end()) {
+ Selection sel = selections.get(*i);
+ int from = sel.from;
+ int to = sel.to;
+ int fadein = sel.fadein;
+ int fadeout = sel.fadeout;
if(from > pos + width || to + width < pos) { i++; continue; }
- if(active_selection == &i.value()) {
+ if(selections.active() == *i) {
painter.setBrush(colActiveSelBg);
painter.setPen(colActiveSel);
} else {
painter.setBrush(colSelBg);
painter.setPen(colSel);
}
- painter.drawRect(mapX(from), mapY(-1.0), mapX(to) - mapX(from), mapY(1.0) - mapY(-1.0));
+ painter.drawRect(mapX(from), mapY(-1.0),
+ mapX(to) - mapX(from), mapY(1.0) - mapY(-1.0));
painter.drawLine(mapX(from), mapY(0.0), mapX(from + fadein), mapY(-1.0));
painter.drawLine(mapX(from), mapY(0.0), mapX(from + fadein), mapY(1.0));
painter.drawLine(mapX(to - fadeout), mapY(-1.0), mapX(to), mapY(0.0));
@@ -195,9 +190,8 @@ void CanvasToolSelections::paintEvent(QPaintEvent *event, QPainter &painter)
void CanvasToolSelections::keyReleaseEvent(QKeyEvent *event)
{
- if(active_selection && event->key() == Qt::Key_Delete) {
- _selections.remove(active_selection->from);
- emit selectionsChanged(_selections);
+ if(selections.active() != SEL_NONE && event->key() == Qt::Key_Delete) {
+ selections.remove(selections.active());
canvas->update();
}
}
@@ -251,26 +245,21 @@ void CanvasToolSelections::autoCreateSelections()
runavg = runavg * p + fabs(data[to]) * (1 - p);
to++;
}
- _selections[from] = Selection(from, to, 2, ((to - from) / 3) * fadeout);
+
+ Selection s(from, to, 2, ((to - from) / 3) * fadeout);
+ selections.add(s);
i = to+1;
}
}
canvas->update();
- emit selectionsChanged(_selections);
}
void CanvasToolSelections::clearSelections()
{
- _selections.clear();
+ selections.clear();
selection_is_moving_left = false;
selection_is_moving_right = false;
canvas->setCursor(Qt::ArrowCursor);
canvas->update();
- emit selectionsChanged(_selections);
-}
-
-Selections CanvasToolSelections::selections()
-{
- return _selections;
}
diff --git a/dgedit/canvastoolselections.h b/dgedit/canvastoolselections.h
index 64c52b8..8b877de 100644
--- a/dgedit/canvastoolselections.h
+++ b/dgedit/canvastoolselections.h
@@ -38,7 +38,7 @@
class CanvasToolSelections : public CanvasTool {
Q_OBJECT
public:
- CanvasToolSelections(Canvas *canvas);
+ CanvasToolSelections(Canvas *canvas, Selections &selections);
QString name() { return "Selections"; }
bool mouseMoveEvent(QMouseEvent *event);
@@ -47,11 +47,11 @@ public:
void paintEvent(QPaintEvent *event, QPainter &painter);
void keyReleaseEvent(QKeyEvent *event);
- Selections selections();
+ //Selections selections();
signals:
- void selectionsChanged(Selections selections);
- void activeSelectionChanged(Selection selection);
+ //void selectionsChanged(Selections selections);
+ //void activeSelectionChanged(sel_id_t id);
public slots:
void autoCreateSelections();
@@ -59,13 +59,10 @@ public slots:
void thresholdChanged(double threshold);
void noiseFloorChanged(int t);
void fadeoutChanged(int t);
- void setActiveSelection(Selection s);
private:
bool selection_is_moving_left;
bool selection_is_moving_right;
- Selection *active_selection;
- Selections _selections;
Canvas *canvas;
@@ -77,6 +74,8 @@ private:
QColor colSel;
QColor colActiveSelBg;
QColor colActiveSel;
+
+ Selections &selections;
};
#endif/*__DRUMGIZMO_CANVASTOOLSELECTIONS_H__*/
diff --git a/dgedit/mainwindow.cc b/dgedit/mainwindow.cc
index 2b1638c..412cd32 100644
--- a/dgedit/mainwindow.cc
+++ b/dgedit/mainwindow.cc
@@ -70,7 +70,7 @@ MainWindow::MainWindow()
central->setLayout(lv);
setCentralWidget(central);
- extractor = new AudioExtractor(this);
+ extractor = new AudioExtractor(session, this);
canvas = new Canvas(this);
QToolBar *toolbar = addToolBar("Tools");
@@ -79,9 +79,11 @@ MainWindow::MainWindow()
addTool(toolbar, canvas, listen);
CanvasTool *threshold = new CanvasToolThreshold(canvas);
addTool(toolbar, canvas, threshold);
- selections = new CanvasToolSelections(canvas);
+ selections = new CanvasToolSelections(canvas, session);
connect(threshold, SIGNAL(thresholdChanged(double)),
selections, SLOT(thresholdChanged(double)));
+ connect(&session, SIGNAL(activeChanged(sel_id_t)),
+ canvas, SLOT(update()));
addTool(toolbar, canvas, selections);
QMenu *fileMenu = menuBar()->addMenu("&File");
@@ -114,14 +116,12 @@ MainWindow::MainWindow()
xoffset->setSingleStep(SINGLESTEP);
connect(xoffset, SIGNAL(valueChanged(int)), this, SLOT(setXOffset(int)));
- sorter = new SampleSorter();
- connect(selections, SIGNAL(selectionsChanged(Selections)),
- sorter, SLOT(setSelections(Selections)));
- connect(selections, SIGNAL(activeSelectionChanged(Selection)),
- sorter, SLOT(setActiveSelection(Selection)));
-
- connect(sorter, SIGNAL(activeSelectionChanged(Selection)),
- selections, SLOT(setActiveSelection(Selection)));
+ sorter = new SampleSorter(session);
+ connect(&session, SIGNAL(added(sel_id_t)),
+ sorter, SLOT(addSelection(sel_id_t)));
+ connect(&session, SIGNAL(updated(sel_id_t)), sorter, SLOT(relayout()));
+ connect(&session, SIGNAL(removed(sel_id_t)), sorter, SLOT(relayout()));
+ connect(&session, SIGNAL(activeChanged(sel_id_t)), sorter, SLOT(relayout()));
QPushButton *btn_playsamples = new QPushButton("Play samples");
connect(btn_playsamples, SIGNAL(clicked()), this, SLOT(playSamples()));
@@ -321,21 +321,40 @@ void MainWindow::setVolumeLineEd(int value)
void MainWindow::playSamples()
{
- // unsigned int length = 44100 / 4; // 0.25 seconds in 44k1Hz
+ //unsigned int length = 44100 / 4; // 0.25 seconds in 44k1Hz
+
+ QVector<sel_id_t> ids = session.ids();
+ for(int v1 = 0; v1 < ids.size(); v1++) {
+ for(int v2 = 0; v2 < ids.size(); v2++) {
+
+ Selection sel1 = session.get(ids[v1]);
+ Selection sel2 = session.get(ids[v2]);
+
+ if(sel1.energy < sel2.energy) {
+ sel_id_t vtmp = ids[v1];
+ ids[v1] = ids[v2];
+ ids[v2] = vtmp;
+ }
+ }
+ }
+
+ QVector<sel_id_t>::iterator i = ids.begin();
+ while(i != ids.end()) {
+ Selection sel = session.get(*i);
- Selections sels = sorter->selections();
- Selections::iterator i = sels.begin();
- while(i != sels.end()) {
unsigned int length = sb_playsamples->value() * 44100 / 1000;
- unsigned int sample_length = i->to - i->from;
+ unsigned int sample_length = sel.to - sel.from;
- unsigned int to = i->to;
+ unsigned int to = sel.to;
unsigned int sleep = 0;
- if(sample_length > length) to = i->from + length;
+ if(sample_length > length) to = sel.from + length;
else sleep = length - sample_length;
- g_listen->playRange(i->from, to);
+
+ session.setActive(*i);
+
+ g_listen->playRange(sel.from, to);
usleep(1000000 * sleep / 44100);
i++;
}
@@ -402,7 +421,7 @@ void MainWindow::setYOffset(int of)
void MainWindow::doExport()
{
- extractor->exportSelections(sorter->selections(), sorter->levels());
+ extractor->exportSelections();
}
void MainWindow::loadFile(QString filename)
diff --git a/dgedit/mainwindow.h b/dgedit/mainwindow.h
index 5fbf0ec..6758779 100644
--- a/dgedit/mainwindow.h
+++ b/dgedit/mainwindow.h
@@ -39,6 +39,7 @@
#include "samplesorter.h"
#include "filelist.h"
#include "canvastoolselections.h"
+#include "selection.h"
class Preset {
public:
@@ -93,12 +94,14 @@ private:
QLineEdit *prefix;
QLineEdit *lineed_exportp;
+ // Session state information:
+ Selections session;
+
private slots:
void setAttackLengthLineEd(int);
void setFalloffLineEd(int);
void setFadeLengthLineEd(int);
void setVolumeLineEd(int);
-
};
#endif/*__DRUMGIZMO_MAINWINDOW_H__*/
diff --git a/dgedit/samplesorter.cc b/dgedit/samplesorter.cc
index 299a552..4048b49 100644
--- a/dgedit/samplesorter.cc
+++ b/dgedit/samplesorter.cc
@@ -36,7 +36,8 @@
#define MAXFLOAT (3.40282347e+38F)
#endif
-SampleSorter::SampleSorter()
+SampleSorter::SampleSorter(Selections &s)
+ : selections(s)
{
setMouseTracking(true);
@@ -44,22 +45,14 @@ SampleSorter::SampleSorter()
size = 0;
attlen = 666; // Magical constants needs biblical proportions...
- cur_thr = -1;
- threshold.push_back(0.8);
- threshold_is_moving = false;
+ sel_moving = SEL_NONE;
}
void SampleSorter::setWavData(const float *data, size_t size)
{
this->data = data;
this->size = size;
- resort();
-}
-
-void SampleSorter::setSelections(Selections s)
-{
- _selections = s;
- resort();
+ relayout();
}
int SampleSorter::attackLength()
@@ -70,9 +63,9 @@ int SampleSorter::attackLength()
void SampleSorter::setAttackLength(int len)
{
attlen = len;
- resort();
+ relayout();
}
-
+/* // TODO
Selections SampleSorter::selections()
{
Selections s;
@@ -86,78 +79,38 @@ Selections SampleSorter::selections()
return s;
}
+*/
-Levels SampleSorter::levels()
+void SampleSorter::addSelection(sel_id_t id)
{
- Levels lvls;
-
- // Sort the segmentation lines:
- for(int i = 0; i < threshold.size(); i++) {
- for(int j = 0; j < threshold.size(); j++) {
- if(threshold[i] < threshold[j]) {
- float tmp = threshold[i];
- threshold[i] = threshold[j];
- threshold[j] = tmp;
- }
- }
+ Selection s = selections.get(id);
+
+ double energy = 0.0;
+ for(size_t idx = s.from;
+ (idx < (size_t)s.from + (size_t)attackLength()) &&
+ (idx < (size_t)s.to) && (idx < size);
+ idx++) {
+ energy += data[idx] * data[idx];
}
-
- //
- for(int i = -1; i < threshold.size(); i++) {
- Level lvl;
-
- if(i == -1) lvl.velocity = 0;
- else lvl.velocity = threshold[i] * threshold[i];
- float next;
- if(i == threshold.size() - 1) next = 1.0;
- else next = threshold[i+1] * threshold[i+1];
-
- QMap<float, Selection>::iterator si = sorted.begin();
- while(si != sorted.end()) {
- float val = (si.key()/max);
- if(val >= lvl.velocity && val <= next) {
- lvl.selections[si.key()] = si.value();
- }
- si++;
- }
-
- lvls.push_back(lvl);
- }
+ s.energy = energy;
+ selections.update(id, s);
- return lvls;
+ relayout();
}
-
-void SampleSorter::resort()
+void SampleSorter::relayout()
{
- sorted.clear();
-
min = MAXFLOAT;
max = 0.0;
- QMap<int, Selection>::iterator i = _selections.begin();
- while(i != _selections.end()) {
- float energy = 0.0;
- Selection &s = i.value();
-
- for(size_t idx = s.from;
- (idx < (size_t)s.from + (size_t)attackLength()) &&
- (idx < (size_t)s.to) && (idx < size);
- idx++) {
- energy += data[idx] * data[idx];
- }
-
- while(sorted.find(energy) != sorted.end()) {
- energy += 1; // Make sure that the key is unique.
- }
+ QVector<sel_id_t> ids = selections.ids();
+ QVector<sel_id_t>::iterator i = ids.begin();
+ while(i != ids.end()) {
+ Selection sel = selections.get(*i);
- s.energy = energy;
-
- sorted[energy] = i.value();
-
- if(energy < min) min = energy;
- if(energy > max) max = energy;
+ if(sel.energy < min) min = sel.energy;
+ if(sel.energy > max) max = sel.energy;
i++;
}
@@ -165,12 +118,6 @@ void SampleSorter::resort()
update();
}
-void SampleSorter::setActiveSelection(Selection s)
-{
- sel = s;
- update();
-}
-
#define MAP(p) (height()-(int)(p*((float)height()/(float)width())))
#define unmapX(x) ((double)x/(double)(width()-1))
@@ -192,7 +139,6 @@ void SampleSorter::paintEvent(QPaintEvent *event)
QColor colFg = QColor(160, 180, 160);
QColor colPt = QColor(255, 100, 100);
QColor colPtSel = QColor(255, 255, 100);
- QColor colVel = QColor(0, 0, 0);
painter.setPen(colBg);
painter.setBrush(colBg);
@@ -201,24 +147,13 @@ void SampleSorter::paintEvent(QPaintEvent *event)
painter.setPen(colFg);
painter.drawLine(0,height(),width(),0);
- for(int i = 0; i < threshold.size(); i++) {
- if(cur_thr == i) painter.setPen(colPtSel);
- else painter.setPen(colPt);
- painter.drawLine(mapX(threshold[i]), 0, mapX(threshold[i]), height());
- char valstr[32];
- sprintf(valstr, "%.3f", threshold[i] * threshold[i]);
- painter.setPen(colVel);
- painter.drawText(mapX(threshold[i]), height(), valstr);
- }
-
- if(sorted.isEmpty()) return;
-
- QMap<float, Selection>::iterator i = sorted.begin();
- while(i != sorted.end()) {
- if(sel.to == i.value().to && sel.from == i.value().from)
- painter.setPen(colPtSel);
+ QVector<sel_id_t> ids = selections.ids();
+ QVector<sel_id_t>::iterator i = ids.begin();
+ while(i != ids.end()) {
+ Selection sel = selections.get(*i);
+ if(*i == selections.active()) painter.setPen(colPtSel);
else painter.setPen(colPt);
- float x = (i.key()/max);
+ float x = sel.energy / max;
x = sqrt(x);
x *= (float)width();
drawCircle(painter, x, MAP(x));
@@ -226,68 +161,48 @@ void SampleSorter::paintEvent(QPaintEvent *event)
}
}
-Selection *SampleSorter::getSelectionByCoordinate(int px, int py)
+sel_id_t SampleSorter::getSelectionByCoordinate(int px, int py)
{
- py -= C_RADIUS;
-
- QMap<float, Selection>::iterator i = sorted.begin();
- while(i != sorted.end()) {
- float x = (i.key()/max);
+ // Hit radius is slithly larger than the circles themselves.
+ int hit_r = C_RADIUS + 1;
+
+ QVector<sel_id_t> ids = selections.ids();
+ QVector<sel_id_t>::iterator i = ids.begin();
+ while(i != ids.end()) {
+ Selection sel = selections.get(*i);
+ float x = (sel.energy/max);
x = sqrt(x);
x *= (float)width();
- if(px < (x + C_RADIUS) && px > (x - C_RADIUS) &&
- py < (MAP(x) + C_RADIUS) && py > (MAP(x) - C_RADIUS)) {
- return &i.value();
+ if(px < (x + hit_r) && px > (x - hit_r) &&
+ py < (MAP(x) + hit_r) && py > (MAP(x) - hit_r)) {
+ return *i;
}
i++;
}
- return NULL;
+ return SEL_NONE;
}
-
void SampleSorter::mouseMoveEvent(QMouseEvent *event)
{
- if(sel_moving) {
- QMap<float, Selection>::iterator i = sorted.begin();
- while(i != sorted.end()) {
- Selection &sel = i.value();
- if(sel_moving == &sel) {
- float power = unmapX(event->x());
- power *= power;
- power *= max;
- printf("power: %f => %f\n", i.key(), power);
- sorted.erase(i);
- while(sorted.find(power) != sorted.end()) power += 0.000001;
- sorted[power] = sel;
- emit activeSelectionChanged(sorted[power]);
- sel_moving = &sorted[power];
- printf("Found it!\n");
- break;
- }
- i++;
+ if(sel_moving != SEL_NONE) {
+ Selection sel = selections.get(sel_moving);
+ if(sel_moving != SEL_NONE) {
+ double power = unmapX(event->x());
+ power *= power;
+ power *= max;
+ sel.energy = power;
+ selections.update(sel_moving, sel);
}
- update();
- return;
- }
-
- if(cur_thr != -1 && cur_thr < threshold.size()) {
- float val = unmapX(event->x());
- if(val < 0.0) val = 0.0;
- if(val > 1.0) val = 1.0;
- threshold[cur_thr] = fabs(val);
update();
return;
- }
-
- if(event->button() != Qt::LeftButton) {
- setCursor(Qt::ArrowCursor);
- for(size_t i = 0; i < (size_t)threshold.size(); i++) {
- if(abs(event->x() - mapX(threshold[i])) < 2 ||
- abs(event->x() - mapX(-threshold[i])) < 2 ) {
- setCursor(Qt::SplitHCursor);
- }
+ } else {
+ sel_id_t psel = getSelectionByCoordinate(event->x(), event->y());
+ if(psel != SEL_NONE) {
+ setCursor(Qt::UpArrowCursor);
+ } else {
+ setCursor(Qt::ArrowCursor);
}
}
}
@@ -295,49 +210,19 @@ void SampleSorter::mouseMoveEvent(QMouseEvent *event)
void SampleSorter::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton) {
-
- Selection *psel = getSelectionByCoordinate(event->x(), event->y());
- if(psel) {
- emit activeSelectionChanged(*psel);
- sel_moving = psel;
- return;
- }
-
- // Check if threshold is being dragged.
- for(size_t i = 0; i < (size_t)threshold.size(); i++) {
- if(abs(event->x() - mapX(threshold[i])) < 2 ||
- abs(event->x() - mapX(-threshold[i])) < 2 ) {
- cur_thr = i;
- threshold_is_moving = true;
- update();
- return;
- }
+ sel_id_t psel = getSelectionByCoordinate(event->x(), event->y());
+ sel_moving = psel;
+ selections.setActive(psel);
+ if(psel != SEL_NONE) {
+ setCursor(Qt::UpArrowCursor);
}
-
- // Make new selection
- float from = unmapX(event->x());
- threshold.push_back(from);
- cur_thr = threshold.size() - 1;
- threshold_is_moving = true;
- update();
- return;
}
}
void SampleSorter::mouseReleaseEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton) {
- sel_moving = NULL;
-
- if(threshold_is_moving) {
- if(threshold[cur_thr] == 0.0 || threshold[cur_thr] == 1.0) {
- threshold.remove(cur_thr);
- }
- threshold_is_moving = false;
- cur_thr = -1;
- setCursor(Qt::ArrowCursor);
- update();
- return;
- }
+ sel_moving = SEL_NONE;
+ setCursor(Qt::ArrowCursor);
}
}
diff --git a/dgedit/samplesorter.h b/dgedit/samplesorter.h
index 4ffaf2a..f35622a 100644
--- a/dgedit/samplesorter.h
+++ b/dgedit/samplesorter.h
@@ -31,29 +31,18 @@
#include <QVector>
#include "selection.h"
-class Level {
-public:
- float velocity;
- QMap<float, Selection> selections;
-};
-
-typedef QVector<Level> Levels;
-
class SampleSorter : public QWidget {
Q_OBJECT
public:
- SampleSorter();
-
- Selections selections();
- Levels levels();
+ SampleSorter(Selections &selections);
public slots:
- void setSelections(Selections selections);
void setWavData(const float *data, size_t size);
- void resort();
void setAttackLength(int len);
int attackLength();
- void setActiveSelection(Selection s);
+
+ void addSelection(sel_id_t id);
+ void relayout();
protected:
void paintEvent(QPaintEvent *event);
@@ -61,14 +50,11 @@ protected:
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
-signals:
- void activeSelectionChanged(Selection selection);
-
private:
- Selection *getSelectionByCoordinate(int x, int y);
+ sel_id_t getSelectionByCoordinate(int x, int y);
+
+ Selections &selections;
- Selections _selections;
- QMap<float, Selection> sorted;
float min;
float max;
int attlen;
@@ -79,13 +65,7 @@ private:
Selection sel;
- QVector<double> threshold;
- bool threshold_is_moving;
- bool selection_is_moving_left;
- bool selection_is_moving_right;
- int cur_thr;
-
- Selection *sel_moving;
+ sel_id_t sel_moving;
};
#endif/*__DRUMGIZMO_SAMPLESORTER_H__*/
diff --git a/dgedit/selection.cc b/dgedit/selection.cc
new file mode 100644
index 0000000..c0300a4
--- /dev/null
+++ b/dgedit/selection.cc
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * selection.cc
+ *
+ * Mon Apr 14 10:13:21 CEST 2014
+ * Copyright 2014 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "selection.h"
+
+Selections::Selections()
+ : QObject(NULL)
+{
+ nextid = 0;
+ act = SEL_NONE;
+}
+
+sel_id_t Selections::add(Selection selection)
+{
+ sel_id_t id = nextid++;
+ sels[id] = selection;
+ added(id);
+ return id;
+}
+
+Selection Selections::get(sel_id_t id)
+{
+ if(sels.find(id) == sels.end()) {
+ Selection s(0,0,0,0);
+ return s;
+ }
+ return sels[id];
+}
+
+QVector<sel_id_t> Selections::ids()
+{
+ QVector<sel_id_t> v;
+
+ QMap<sel_id_t, Selection>::iterator i = sels.begin();
+ while(i != sels.end()) {
+ v.push_back(i.key());
+ i++;
+ }
+
+ return v;
+}
+
+void Selections::update(sel_id_t id, Selection selection)
+{
+ if(sels.find(id) != sels.end()) {
+ sels[id] = selection;
+ emit updated(id);
+ }
+}
+
+void Selections::remove(sel_id_t id)
+{
+ if(sels.find(id) != sels.end()) {
+ sels.erase(sels.find(id));
+ if(id == act) setActive(SEL_NONE);
+ emit removed(id);
+ }
+}
+
+void Selections::clear()
+{
+ QVector<sel_id_t> _ids = ids();
+ QVector<sel_id_t>::iterator i = _ids.begin();
+ while(i != _ids.end()) {
+ remove(*i);
+ i++;
+ }
+}
+
+void Selections::setActive(sel_id_t id)
+{
+ if(sels.find(id) != sels.end()) {
+ act = id;
+ } else {
+ act = SEL_NONE;
+ }
+ emit activeChanged(act);
+}
+
+sel_id_t Selections::active()
+{
+ return act;
+}
diff --git a/dgedit/selection.h b/dgedit/selection.h
index 64e6d98..08b897b 100644
--- a/dgedit/selection.h
+++ b/dgedit/selection.h
@@ -27,7 +27,10 @@
#ifndef __DRUMGIZMO_SELECTION_H__
#define __DRUMGIZMO_SELECTION_H__
+#include <QObject>
+
#include <QMap>
+#include <QVector>
class Selection {
public:
@@ -47,6 +50,86 @@ public:
QString name;
};
-typedef QMap<int, Selection> Selections;
+typedef int sel_id_t;
+#define SEL_NONE -1
+
+class Selections : public QObject {
+Q_OBJECT
+public:
+ Selections();
+
+ /**
+ * Add a new selection object. The new id is returned.
+ * Adding a new selections will emit an added signal with the new id.
+ */
+ sel_id_t add(Selection selection);
+
+ /**
+ * Get a stack copy of a specific selection object, by id.
+ * NOTE: If id does not exist an empty selection (from = to = 0) is
+ * returned.
+ */
+ Selection get(sel_id_t id);
+
+ /**
+ * Return vector (unsorted) of all ids in the object.
+ */
+ QVector<sel_id_t> ids();
+
+ /**
+ * Set active selection (to be rendered yellow)
+ */
+ void setActive(sel_id_t id);
+
+ /**
+ * Get active selection id.
+ */
+ sel_id_t active();
+
+public slots:
+ /**
+ * Update a selection by id.
+ * Updating a selection will emit a updated signal.
+ */
+ void update(sel_id_t id, Selection selection);
+
+ /**
+ * Delete a selection by id.
+ * Deleting a selection will emit a deleted signal.
+ */
+ void remove(sel_id_t id);
+
+ /**
+ * Delete all selections
+ */
+ void clear();
+
+signals:
+ /**
+ * This signal is emitted when a new selection has been added.
+ */
+ void added(sel_id_t id);
+
+ /**
+ * This signal is emitted when an existing selection has been updated.
+ */
+ void updated(sel_id_t id);
+
+ /**
+ * This signal is emitted when a selection has been removed.
+ */
+ void removed(sel_id_t id);
+
+ /**
+ * The active selection changed.
+ */
+ void activeChanged(sel_id_t id);
+
+private:
+ QMap<sel_id_t, Selection> sels;
+ sel_id_t nextid;
+ sel_id_t act;
+};
+
#endif/*__DRUMGIZMO_SELECTION_H__*/