diff options
| author | deva <deva> | 2011-07-15 13:02:33 +0000 | 
|---|---|---|
| committer | deva <deva> | 2011-07-15 13:02:33 +0000 | 
| commit | cd0e36773992e26985bdec1f7a5341f83fa3e521 (patch) | |
| tree | 4710fb3f2465f4b464f5f6176261a67cfde2e46e /dgedit | |
| parent | e190d38057892b69246391841b234a368bc2b4ad (diff) | |
New input/output plugin architecture. New LV2 plugin.
Diffstat (limited to 'dgedit')
| -rw-r--r-- | dgedit/.cvsignore | 3 | ||||
| -rw-r--r-- | dgedit/Makefile.am | 4 | ||||
| -rw-r--r-- | dgedit/audioextractor.cc | 65 | ||||
| -rw-r--r-- | dgedit/audioextractor.h | 3 | ||||
| -rw-r--r-- | dgedit/canvas.cc | 128 | ||||
| -rw-r--r-- | dgedit/canvas.h | 8 | ||||
| -rw-r--r-- | dgedit/mainwindow.cc | 11 | ||||
| -rw-r--r-- | dgedit/mipmap.cc | 99 | ||||
| -rw-r--r-- | dgedit/mipmap.h | 62 | ||||
| -rw-r--r-- | dgedit/samplesorter.cc | 139 | ||||
| -rw-r--r-- | dgedit/samplesorter.h | 21 | ||||
| -rw-r--r-- | dgedit/selection.h | 2 | 
12 files changed, 407 insertions, 138 deletions
| diff --git a/dgedit/.cvsignore b/dgedit/.cvsignore new file mode 100644 index 0000000..e995588 --- /dev/null +++ b/dgedit/.cvsignore @@ -0,0 +1,3 @@ +.deps +Makefile +Makefile.in diff --git a/dgedit/Makefile.am b/dgedit/Makefile.am index dad5437..1aa940a 100644 --- a/dgedit/Makefile.am +++ b/dgedit/Makefile.am @@ -3,7 +3,7 @@ bin_PROGRAMS = dgedit  dgedit_LDADD = $(SNDFILE_LIBS) $(QT_LIBS) $(shell ../tools/MocList o )  dgedit_CXXFLAGS = $(SNDFILE_CXXFLAGS) $(QT_CFLAGS) -CXXFLAGS += $(QT_CFLAGS) +AM_CXXFLAGS = $(QT_CFLAGS)  dgedit_SOURCES = $(shell ../tools/MocList cc ) \  	dgedit.cc \ @@ -12,6 +12,7 @@ dgedit_SOURCES = $(shell ../tools/MocList cc ) \  	filelist.cc \  	itemeditor.cc \  	mainwindow.cc \ +	mipmap.cc \  	samplesorter.cc \  	dgedit.qrc \  	dgedit_qrc.cpp @@ -22,6 +23,7 @@ EXTRA_DIST = \  	filelist.h \  	itemeditor.h \  	mainwindow.h \ +	mipmap.h \  	samplesorter.h  dgedit_MOC = $(shell ../tools/MocList cc ) diff --git a/dgedit/audioextractor.cc b/dgedit/audioextractor.cc index 63273d1..015d323 100644 --- a/dgedit/audioextractor.cc +++ b/dgedit/audioextractor.cc @@ -28,6 +28,7 @@  #include <QDomDocument>  #include <QFile> +#include <QDir>  #include <sndfile.h> @@ -48,10 +49,10 @@ float *AudioExtractor::load(QString file, size_t *size)      return NULL;    } -	*size = sf_seek(fh, 0, SEEK_END); +  *size = sf_info.frames; +    data = new float[*size]; -	sf_seek(fh, 0, SEEK_SET);  	sf_read_float(fh, data, *size);   	sf_close(fh); @@ -67,7 +68,11 @@ void AudioExtractor::exportSelection(QString filename,    printf("Writing: %s (sz: %d, from %d to %d)\n",           filename.toStdString().c_str(), size, sel.from, sel.to); -  if(sel.from > (int)size || sel.to > (int)size || sel.to < 0 || sel.from < 0 || sel.to < sel.from) { +  if(sel.from > (int)size || +     sel.to > (int)size || +     sel.to < 0 || +     sel.from < 0 || +     sel.to < sel.from) {      printf("Out of bounds\n");      return;    } @@ -98,7 +103,8 @@ void AudioExtractor::exportSelection(QString filename,    sf_close(fh);  } -void AudioExtractor::exportSelections(Selections selections, QVector<int> levels) +void AudioExtractor::exportSelections(Selections selections, +                                      Levels levels)  {    // Do the actual exporting one file at the time.    AudioFileList::iterator j = audiofiles.begin(); @@ -117,8 +123,12 @@ void AudioExtractor::exportSelections(Selections selections, QVector<int> levels      while(i != selections.end()) {        index++; -      QString file = exportpath + "/" + prefix + "/samples/" + -        prefix + "-" + name + "-" + QString::number(index) + ".wav"; +      QString path = exportpath + "/" + prefix + "/samples"; +      QString file = path + "/" + QString::number(index) + +        "-" + prefix + "-" + name + ".wav"; + +      QDir d; +      d.mkpath(path);        exportSelection(file, index, data, size, i.value());        i++; @@ -147,8 +157,10 @@ void AudioExtractor::exportSelections(Selections selections, QVector<int> levels    while(i != selections.end()) {      index++; +    i->name = prefix + "-" + QString::number(index); +      QDomElement sample = doc.createElement("sample"); -    sample.setAttribute("name", prefix + "-" + QString::number(index)); +    sample.setAttribute("name", i->name);      samples.appendChild(sample);      AudioFileList::iterator j = audiofiles.begin(); @@ -158,8 +170,9 @@ void AudioExtractor::exportSelections(Selections selections, QVector<int> levels        QString name = j->second;        QDomElement audiofile = doc.createElement("audiofile"); -      audiofile.setAttribute("file", "samples/" + prefix + "-" + name + "-" -                             + QString::number(index) + ".wav"); +      audiofile.setAttribute("file", "samples/" +  +                             QString::number(index) + "-" + prefix + +                             "-" + name + ".wav");        audiofile.setAttribute("channel", name);        sample.appendChild(audiofile); @@ -172,17 +185,37 @@ void AudioExtractor::exportSelections(Selections selections, QVector<int> levels    QDomElement velocities = doc.createElement("velocities");    instrument.appendChild(velocities); -  QVector<int>::iterator k = levels.begin(); +  Levels::iterator k = levels.begin();    while(k != levels.end()) { + +    Levels::iterator nxt = k; +    nxt++; +    int next; +    if(nxt == levels.end()) next = 127; +    else next = nxt->velocity - 1; +     +      QDomElement velocity = doc.createElement("velocity"); -    velocity.setAttribute("lower", "0"); -    velocity.setAttribute("upper", "127"); +    velocity.setAttribute("lower", k->velocity); +    velocity.setAttribute("upper", next);      velocities.appendChild(velocity); -    QDomElement sampleref = doc.createElement("sampleref"); -    sampleref.setAttribute("name", "bleh"); -    sampleref.setAttribute("probability", "0.1"); -    velocity.appendChild(sampleref); +    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++;    } diff --git a/dgedit/audioextractor.h b/dgedit/audioextractor.h index 2f4ce98..33ccf71 100644 --- a/dgedit/audioextractor.h +++ b/dgedit/audioextractor.h @@ -34,6 +34,7 @@  #include <QVector>  #include "selection.h" +#include "samplesorter.h"  typedef QLinkedList< QPair<QString, QString> > AudioFileList; @@ -46,7 +47,7 @@ public slots:    void addFile(QString file, QString name);    void changeName(QString file, QString name);    void removeFile(QString file, QString name); -  void exportSelections(Selections selections, QVector<int> levels); +  void exportSelections(Selections selections, Levels levels);    void setExportPath(const QString &path);    void setOutputPrefix(const QString &prefix); diff --git a/dgedit/canvas.cc b/dgedit/canvas.cc index 4c63e5e..5fc1f1f 100644 --- a/dgedit/canvas.cc +++ b/dgedit/canvas.cc @@ -35,7 +35,6 @@  #include <math.h>  #define DEFYSCALE 200 -#define MIPMAPS 65536  Canvas::Canvas(QWidget *parent)    : QWidget(parent) @@ -43,8 +42,12 @@ Canvas::Canvas(QWidget *parent)    setAttribute(Qt::WA_StaticContents);    setMouseTracking(true);    setFocusPolicy(Qt::ClickFocus); + +  mipmap = NULL; +    data = NULL;    size = 0; +    xscale = 1.0;    yscale = 1.0;    xoffset = 0.0; @@ -77,31 +80,7 @@ Canvas::Canvas(QWidget *parent)  Canvas::~Canvas()  {    if(data) delete[] data; -} - -#define VALL(x) (x*4) -#define VALU(x) (x*4+1) -#define POWL(x) (x*4+2) -#define POWU(x) (x*4+3) - -static void genmipmap(float *in, size_t insz, float *out, size_t outsz) -{ -  float *lookup = out; - -  for(size_t i = 0; i < outsz; i++) { -    lookup[VALL(i)] = 0.0; -    lookup[VALU(i)] = 0.0; -    lookup[POWL(i)] = 0.0; -    lookup[POWU(i)] = 0.0; - -    for(size_t j = i * (insz / outsz); j < (i+1)*(insz / outsz); j++) { -      if(in[VALU(j)] > lookup[VALU(i)]) lookup[VALU(i)] = in[VALU(j)]; -      if(in[VALL(j)] < lookup[VALL(i)]) lookup[VALL(i)] = in[VALL(j)]; -      if(in[POWU(j)] > 0) lookup[POWU(i)] += in[POWU(j)]; -      if(in[POWL(j)] < 0) lookup[POWL(i)] += in[POWL(j)]; -    } - -  } +  if(mipmap) delete mipmap;  }  void Canvas::load(QString file) @@ -110,55 +89,30 @@ void Canvas::load(QString file)      delete[] data;      data = NULL;      size = 0; +  } -    QMap<int, float*>::iterator i = mipmaps.begin(); -    while(i != mipmaps.end()) { -      delete[] i.value(); -      i++; -    } - +  if(mipmap) { +    delete mipmap; +    mipmap = NULL;    }    SF_INFO sf_info;  	SNDFILE *fh = sf_open(file.toStdString().c_str(), SFM_READ, &sf_info);    if(!fh) {      printf("Load error...\n"); +    return;    } -	size = sf_seek(fh, 0, SEEK_END); +  size = sf_info.frames; + +  printf("Size: %u\n", (unsigned int)sf_info.frames);    data = new float[size]; -	sf_seek(fh, 0, SEEK_SET);  	sf_read_float(fh, data, size);   	sf_close(fh); -  size_t lastsz = 0; -  for(size_t dev = 2; dev <= MIPMAPS; dev*=2) { -    size_t mipmapsize = size/dev; - -    float *lookup = new float[mipmapsize * 4]; - -    if(dev == 2) { -      for(size_t i = 0; i < mipmapsize; i++) { -        lookup[VALL(i)] = 0.0; -        lookup[VALU(i)] = 0.0; -        lookup[POWL(i)] = 0.0; -        lookup[POWU(i)] = 0.0; -        for(size_t j = i * dev; j < (i + 1) * dev; j++) { -          if(data[j] > lookup[VALU(i)]) lookup[VALU(i)] = data[j]; -          if(data[j] < lookup[VALL(i)]) lookup[VALL(i)] = data[j]; -          if(data[j] > 0) lookup[POWU(i)] += data[j]; -          if(data[j] < 0) lookup[POWL(i)] += data[j]; -        } -      } -    } else { -      genmipmap(mipmaps[dev/2], lastsz, lookup, mipmapsize); -    } - -    lastsz = mipmapsize; -    mipmaps[dev] = lookup; -  } +  mipmap = new MipMap(data, size);    updateWav();    update(); @@ -323,42 +277,17 @@ void Canvas::resizeEvent(QResizeEvent *)    update();  } -void Canvas::getWavValues(int last, int lx, float *vu, float *vl, float *avgu, float *avgl) +void Canvas::getWavValues(int last, int lx, float *vu, float *vl, +                          float *avgu, float *avgl)  { -  float *lookup = data; -  int dev = 1; - -  int i = 2; -  while(i < (lx - last) && mipmaps.find(i) != mipmaps.end()) { -    lookup = mipmaps[i]; -    dev = i; -    i *= 2; -  } +  if(mipmap == NULL) return; -  *vu = *vl = *avgu = *avgl = 0; -  for(int i = last / dev; i < lx / dev; i++) { -    float lval; -    float uval; -    float lpow; -    float upow; -    if(dev > 1) { -      lval = -lookup[VALL(i)]; -      uval = -lookup[VALU(i)]; -      upow = -lookup[POWL(i)]; -      lpow = -lookup[POWU(i)]; -    } else { -      lpow = upow = lval = uval = -lookup[i]; -    } -    if(lpow < 0.0) *avgl += lpow; -    if(upow > 0.0) *avgu += upow; -    if(lval > *vl) *vl = lval; -    if(uval < *vu) *vu = uval; -  } -   -  if((lx - last) != 0) { -    *avgu /= (float)(lx - last); -    *avgl /= (float)(lx - last); -  } +  MipMapValue val = mipmap->lookup(last, lx); + +  *vu = val.max; +  *vl = val.min; +  *avgu = val.uavg; +  *avgl = val.lavg;  }  void Canvas::updateWav() @@ -514,10 +443,15 @@ void Canvas::autoCreateSelections()          }        } +      int minsize = 100; // attack. +      float minval = 0.0001; // noise floor        int to = i; -      float runavg = fabs(data[to]); -      while(runavg > 0.001 && to < (int)size) { -        runavg = runavg * 0.99999 + fabs(data[to]) * 0.00001; +      float runavg = fabs(data[from]); +      while((runavg > minval || +             to < from + minsize) && +            to < (int)size) { +        double p = 0.9; +        runavg = runavg * p + fabs(data[to]) * (1 - p);          to++;        }        _selections[from] = Selection(from, to, 2, (to - from) / 3); diff --git a/dgedit/canvas.h b/dgedit/canvas.h index 2a06d03..b881d01 100644 --- a/dgedit/canvas.h +++ b/dgedit/canvas.h @@ -32,6 +32,7 @@  #include <QImage>  #include "selection.h" +#include "mipmap.h"  class Canvas : public QWidget {  Q_OBJECT @@ -64,8 +65,11 @@ protected:    void keyReleaseEvent(QKeyEvent *event);  private: +  MipMap *mipmap; +    void updateWav(); -  void getWavValues(int last, int lx, float *vu, float *vl, float *avgu, float *avgl); +  void getWavValues(int last, int lx, float *vu, float *vl, +                    float *avgu, float *avgl);    float mapX(float x);    float unmapX(float x);    float mapY(float y); @@ -77,8 +81,6 @@ public:    float *data;    size_t size;  private: -  QMap<int, float *> mipmaps; -    float xscale;    float yscale;    float xoffset; diff --git a/dgedit/mainwindow.cc b/dgedit/mainwindow.cc index f9b0147..9454a97 100644 --- a/dgedit/mainwindow.cc +++ b/dgedit/mainwindow.cc @@ -78,8 +78,10 @@ MainWindow::MainWindow()    connect(xoffset, SIGNAL(valueChanged(int)), this, SLOT(setXOffset(int)));    sorter = new SampleSorter(); -  connect(canvas, SIGNAL(selectionsChanged(Selections)), sorter, SLOT(setSelections(Selections))); -  connect(canvas, SIGNAL(activeSelectionChanged(Selection)), sorter, SLOT(setActiveSelection(Selection))); +  connect(canvas, SIGNAL(selectionsChanged(Selections)), +          sorter, SLOT(setSelections(Selections))); +  connect(canvas, SIGNAL(activeSelectionChanged(Selection)), +          sorter, SLOT(setActiveSelection(Selection)));    lh->addWidget(canvas);    lh->addWidget(yscale); @@ -117,7 +119,7 @@ MainWindow::MainWindow()    QLineEdit *prefix = new QLineEdit();    connect(prefix, SIGNAL(textChanged(const QString &)),            extractor, SLOT(setOutputPrefix(const QString &))); -  prefix->setText("china"); +  prefix->setText("kick-r");    configs->addWidget(prefix);    configs->addWidget(new QLabel("Export path:")); @@ -133,7 +135,8 @@ MainWindow::MainWindow()    configs->addWidget(new QLabel("Files: (double-click to set as master)"));    filelist = new FileList(); -  connect(filelist, SIGNAL(masterFileChanged(QString)), this, SLOT(loadFile(QString))); +  connect(filelist, SIGNAL(masterFileChanged(QString)), +          this, SLOT(loadFile(QString)));    connect(loadbtn, SIGNAL(clicked()), filelist, SLOT(addFiles()));    connect(filelist, SIGNAL(fileAdded(QString, QString)),            extractor, SLOT(addFile(QString, QString))); diff --git a/dgedit/mipmap.cc b/dgedit/mipmap.cc new file mode 100644 index 0000000..09b15b6 --- /dev/null +++ b/dgedit/mipmap.cc @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            mipmap.cc + * + *  Fri Sep  3 16:39:46 CEST 2010 + *  Copyright 2010 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 "mipmap.h" + +MipMap::MipMap(float *data, size_t size) +{ +  this->data = data; +  this->size = size; +  this->zoom = 1; +} + +MipMapValue MipMap::data_lookup(size_t begin, size_t end) +{ +  MipMapValue val; + +  size_t numlavg = 0; +  size_t numuavg = 0; +  for(size_t i = begin; i <= end; i++) { +    if(i > size || i < 0) break; +    if(data[i] > val.max) val.max = data[i]; +    if(data[i] < val.min) val.min = data[i]; +     +    if(data[i] > 0) { val.uavg += data[i]; numuavg++; } +    if(data[i] < 0) { val.lavg += data[i]; numlavg++; } +  } +   +  if(numlavg) val.lavg /= (float) numlavg; +  if(numuavg) val.uavg /= (float) numuavg; + +  return val; +} + +MipMapValue MipMap::mipmap_lookup(size_t begin, size_t end) +{ +  MipMapValue val; + +  size_t numlavg = 0; +  size_t numuavg = 0; +  for(size_t i = begin; i <= end; i++) { +    if(i > size || i < 0) break; +    if(data[i] > val.max) val.max = data[i]; +    if(data[i] < val.min) val.min = data[i]; +     +    if(data[i] > 0) { val.uavg += data[i]; numuavg++; } +    if(data[i] < 0) { val.lavg += data[i]; numlavg++; } +  } +   +  if(numlavg) val.lavg /= (float) numlavg; +  if(numuavg) val.uavg /= (float) numuavg; + +  return val; +} + +#define ABS(x) (x>0?x:-x) + +MipMapValue MipMap::lookup(size_t begin, size_t end) +{ +  return data_lookup(begin, end); +  /* + +  size_t zoom_factor = ABS(end - begin); + +  if(zoom_factor < zoom / 2) { +    if(zoom == 1) { // Lookup in original data. +      return data_lookup(begin, end); +    } + +    return mipmap_lookup(begin, end); +  } + +  if(lowerlevel) return lowerlevel->lookup(begin,end); + +  return MipMapValue(); +  */ +} diff --git a/dgedit/mipmap.h b/dgedit/mipmap.h new file mode 100644 index 0000000..550d6ae --- /dev/null +++ b/dgedit/mipmap.h @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            mipmap.h + * + *  Fri Sep  3 16:39:45 CEST 2010 + *  Copyright 2010 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. + */ +#ifndef __DRUMGIZMO_MIPMAP_H__ +#define __DRUMGIZMO_MIPMAP_H__ + +#include <QMap> +#include <stddef.h> + +class MipMapValue { +public: +  MipMapValue() { max = min = uavg = lavg = 0.0; } +  float max; +  float min; +  float uavg; +  float lavg; +}; + +class MipMap { +public: +  MipMap(float *data, size_t size); + +  MipMapValue lookup(size_t begin, size_t end); + +private: +  float *data; +  size_t size; + +  MipMapValue *values; + +  size_t zoom; + +  MipMapValue data_lookup(size_t begin, size_t end); +  MipMapValue mipmap_lookup(size_t begin, size_t end); + +  MipMap *lowerlevel; +}; + +#endif/*__DRUMGIZMO_MIPMAP_H__*/ diff --git a/dgedit/samplesorter.cc b/dgedit/samplesorter.cc index e93754c..545c7cd 100644 --- a/dgedit/samplesorter.cc +++ b/dgedit/samplesorter.cc @@ -29,18 +29,24 @@  #include <QPainter>  #include <QPaintEvent> +#include <stdio.h> +  #include <math.h>  #ifndef MAXFLOAT  #define MAXFLOAT (3.40282347e+38F)  #endif -#define NUM_LEVELS 6 -  SampleSorter::SampleSorter()  { +  setMouseTracking(true); +    data = NULL;    size = 0;    attlen = 666; // Magical constants needs biblical proportions... + +  cur_thr = -1; +  threshold.push_back(100); +  threshold_is_moving = false;  }  void SampleSorter::setWavData(const float *data, size_t size) @@ -81,20 +87,41 @@ Selections SampleSorter::selections()    return s;  } -QVector<int> SampleSorter::levels() +Levels SampleSorter::levels()  { -  QVector<int> lvls; -  int idx = 0; -  float next = min; +  Levels lvls; + +  for(int i = 0; i < threshold.size(); i++) { +    for(int j = 0; j < threshold.size(); j++) { +      if(threshold[i] < threshold[j]) { +        int tmp = threshold[i]; +        threshold[i] = threshold[j]; +        threshold[j] = tmp; +      } +    } +  } +   -  QMap<float, Selection>::iterator i = sorted.begin(); -  while(i != sorted.end()) { -    if(i.key() >= next) { -      lvls.push_back(idx); -      next += (max - min) / NUM_LEVELS; +  for(int i = -1; i < threshold.size(); i++) { +    Level lvl; +     +    if(i == -1) lvl.velocity = 0; +    else lvl.velocity = threshold[i]; +     +    int next; +    if(i == threshold.size() - 1) next = 127; +    else next = threshold[i+1]; + +    QMap<float, Selection>::iterator i = sorted.begin(); +    while(i != sorted.end()) { +      float val = (i.key()/max)*127.0; +      if(val >= lvl.velocity && val <= next) { +        lvl.selections[i.key()] = i.value(); +      } +      i++;      } -    i++; -    idx++; + +    lvls.push_back(lvl);    }    return lvls; @@ -114,7 +141,8 @@ void SampleSorter::resort()      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 < (size_t)s.from + (size_t)attackLength()) && +          (idx < (size_t)s.to) && (idx < size);          idx++) {        energy += data[idx] * data[idx];      } @@ -142,6 +170,12 @@ void SampleSorter::setActiveSelection(Selection s)  #define MAP(p) (height()-(int)(p*((float)height()/(float)width()))) +#define unmapX(x) ((double)x/(double)(width()-1)*127.0) +#define unmapY(x) x +#define mapX(x) (((double)x/127.0)*(width()-1)) +#define mapY(x) x + +  static void drawCircle(QPainter &p, int x, int y)  {    p.drawEllipse(x-2, y-2, 4, 4); @@ -155,6 +189,7 @@ 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); @@ -167,10 +202,84 @@ void SampleSorter::paintEvent(QPaintEvent *event)    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); +    if(sel.to == i.value().to && sel.from == i.value().from) +      painter.setPen(colPtSel);      else painter.setPen(colPt);      float x = (i.key()/max)*(float)width();      drawCircle(painter, x, MAP(x));      i++;    } + +  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, "%d", (int)threshold[i]); +    painter.setPen(colVel); +    painter.drawText(mapX(threshold[i]), height(), valstr); +  } +} + +void SampleSorter::mouseMoveEvent(QMouseEvent *event) +{ +  if(cur_thr != -1 && cur_thr < threshold.size()) { +    float val = unmapX(event->x()); +    if(val < 0) val = 0; +    if(val > 127) val = 127; +    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); +      } +    } +  } +} + +void SampleSorter::mousePressEvent(QMouseEvent *event) +{ +  if(event->button() == Qt::LeftButton) { + +    // 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; +      } +    } + +    // Make new selection +    int 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) { +    if(threshold_is_moving) { +      if(threshold[cur_thr] == 0 || threshold[cur_thr] == 127) { +        threshold.remove(cur_thr); +      } +      threshold_is_moving = false; +      cur_thr = -1; +      setCursor(Qt::ArrowCursor); +      update(); +      return; +    } +  }  } diff --git a/dgedit/samplesorter.h b/dgedit/samplesorter.h index a7c356d..ff45f3e 100644 --- a/dgedit/samplesorter.h +++ b/dgedit/samplesorter.h @@ -28,15 +28,24 @@  #define __DRUMGIZMO_SAMPLESORTER_H__  #include <QWidget> +#include <QVector>  #include "selection.h" +class Level { +public: +  int velocity; +  QMap<float, Selection> selections; +}; + +typedef QVector<Level> Levels; +  class SampleSorter : public QWidget {  Q_OBJECT  public:    SampleSorter();    Selections selections(); -  QVector<int> levels(); +  Levels levels();  public slots:    void setSelections(Selections selections); @@ -48,6 +57,9 @@ public slots:  protected:    void paintEvent(QPaintEvent *event); +  void mouseMoveEvent(QMouseEvent *event); +  void mousePressEvent(QMouseEvent *event); +  void mouseReleaseEvent(QMouseEvent *event);  private:    Selections _selections; @@ -61,6 +73,13 @@ private:    size_t size;    Selection sel; + +  QVector<int> threshold; +  bool threshold_is_moving; +  bool selection_is_moving_left; +  bool selection_is_moving_right; +  int cur_thr; +  };  #endif/*__DRUMGIZMO_SAMPLESORTER_H__*/ diff --git a/dgedit/selection.h b/dgedit/selection.h index 02d5163..283b642 100644 --- a/dgedit/selection.h +++ b/dgedit/selection.h @@ -41,6 +41,8 @@ public:    int to;    int fadein;    int fadeout; + +  QString name;  };  typedef QMap<int, Selection> Selections; | 
