diff options
| author | Bent Bisballe Nyeng <deva@aasimon.org> | 2014-04-15 09:55:45 +0200 | 
|---|---|---|
| committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2014-04-15 09:55:45 +0200 | 
| commit | 0fcacc1c3329e905228ceb80903f69561a7db732 (patch) | |
| tree | 0d1d636d5e0b95b1d4554ad112aa63bfaa79e7e0 /dgedit | |
| parent | a0bff571893f9afd5e4eb84ac52755f851398601 (diff) | |
New selections model.
Diffstat (limited to 'dgedit')
| -rw-r--r-- | dgedit/Makefile.am | 3 | ||||
| -rw-r--r-- | dgedit/audioextractor.cc | 69 | ||||
| -rw-r--r-- | dgedit/audioextractor.h | 6 | ||||
| -rw-r--r-- | dgedit/canvastoolselections.cc | 115 | ||||
| -rw-r--r-- | dgedit/canvastoolselections.h | 13 | ||||
| -rw-r--r-- | dgedit/mainwindow.cc | 57 | ||||
| -rw-r--r-- | dgedit/mainwindow.h | 5 | ||||
| -rw-r--r-- | dgedit/samplesorter.cc | 247 | ||||
| -rw-r--r-- | dgedit/samplesorter.h | 36 | ||||
| -rw-r--r-- | dgedit/selection.cc | 106 | ||||
| -rw-r--r-- | dgedit/selection.h | 85 | 
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__*/ | 
