summaryrefslogtreecommitdiff
path: root/dgedit
diff options
context:
space:
mode:
authordeva <deva>2011-07-15 13:02:33 +0000
committerdeva <deva>2011-07-15 13:02:33 +0000
commitcd0e36773992e26985bdec1f7a5341f83fa3e521 (patch)
tree4710fb3f2465f4b464f5f6176261a67cfde2e46e /dgedit
parente190d38057892b69246391841b234a368bc2b4ad (diff)
New input/output plugin architecture. New LV2 plugin.
Diffstat (limited to 'dgedit')
-rw-r--r--dgedit/.cvsignore3
-rw-r--r--dgedit/Makefile.am4
-rw-r--r--dgedit/audioextractor.cc65
-rw-r--r--dgedit/audioextractor.h3
-rw-r--r--dgedit/canvas.cc128
-rw-r--r--dgedit/canvas.h8
-rw-r--r--dgedit/mainwindow.cc11
-rw-r--r--dgedit/mipmap.cc99
-rw-r--r--dgedit/mipmap.h62
-rw-r--r--dgedit/samplesorter.cc139
-rw-r--r--dgedit/samplesorter.h21
-rw-r--r--dgedit/selection.h2
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;