From 0fcacc1c3329e905228ceb80903f69561a7db732 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Tue, 15 Apr 2014 09:55:45 +0200 Subject: New selections model. --- dgedit/Makefile.am | 3 +- dgedit/audioextractor.cc | 69 +++--------- dgedit/audioextractor.h | 6 +- dgedit/canvastoolselections.cc | 115 +++++++++---------- dgedit/canvastoolselections.h | 13 +-- dgedit/mainwindow.cc | 57 ++++++---- dgedit/mainwindow.h | 5 +- dgedit/samplesorter.cc | 247 +++++++++++------------------------------ dgedit/samplesorter.h | 36 ++---- dgedit/selection.cc | 106 ++++++++++++++++++ dgedit/selection.h | 85 +++++++++++++- 11 files changed, 388 insertions(+), 354 deletions(-) create mode 100644 dgedit/selection.cc 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::iterator si = selections.begin(); - while(si != selections.end()) { - Selection &sel = *si; + QVector sels = selections.ids(); + QVector::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::iterator i = selections.begin(); - while(i != selections.end()) { + QVector::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::iterator i = k->selections.begin(); - while(i != k->selections.end()) { - - QMap::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 > 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::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::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 ids = selections.ids(); + QVector::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::iterator i = _selections.begin(); - while(i != _selections.end()) { - if(abs(event->x() - mapX(i.value().from)) < 2) { - active_selection = &i.value(); + QVector ids = selections.ids(); + QVector::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::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 ids = selections.ids(); + QVector::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 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::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::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::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 ids = selections.ids(); + QVector::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::iterator i = sorted.begin(); - while(i != sorted.end()) { - if(sel.to == i.value().to && sel.from == i.value().from) - painter.setPen(colPtSel); + QVector ids = selections.ids(); + QVector::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::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 ids = selections.ids(); + QVector::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::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 #include "selection.h" -class Level { -public: - float velocity; - QMap selections; -}; - -typedef QVector 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 sorted; float min; float max; int attlen; @@ -79,13 +65,7 @@ private: Selection sel; - QVector 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 Selections::ids() +{ + QVector v; + + QMap::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 _ids = ids(); + QVector::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 + #include +#include class Selection { public: @@ -47,6 +50,86 @@ public: QString name; }; -typedef QMap 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 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 sels; + sel_id_t nextid; + sel_id_t act; +}; + #endif/*__DRUMGIZMO_SELECTION_H__*/ -- cgit v1.2.3