From cd0e36773992e26985bdec1f7a5341f83fa3e521 Mon Sep 17 00:00:00 2001 From: deva Date: Fri, 15 Jul 2011 13:02:33 +0000 Subject: New input/output plugin architecture. New LV2 plugin. --- dgedit/.cvsignore | 3 + dgedit/Makefile.am | 4 +- dgedit/audioextractor.cc | 65 ++++++++++++++++------ dgedit/audioextractor.h | 3 +- dgedit/canvas.cc | 128 +++++++++++-------------------------------- dgedit/canvas.h | 8 ++- dgedit/mainwindow.cc | 11 ++-- dgedit/mipmap.cc | 99 +++++++++++++++++++++++++++++++++ dgedit/mipmap.h | 62 +++++++++++++++++++++ dgedit/samplesorter.cc | 139 ++++++++++++++++++++++++++++++++++++++++++----- dgedit/samplesorter.h | 21 ++++++- dgedit/selection.h | 2 + 12 files changed, 407 insertions(+), 138 deletions(-) create mode 100644 dgedit/.cvsignore create mode 100644 dgedit/mipmap.cc create mode 100644 dgedit/mipmap.h (limited to 'dgedit') 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 #include +#include #include @@ -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 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 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 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 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 levels QDomElement velocities = doc.createElement("velocities"); instrument.appendChild(velocities); - QVector::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::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++; } 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 #include "selection.h" +#include "samplesorter.h" typedef QLinkedList< QPair > 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 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 #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::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 #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 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 +#include + +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 #include +#include + #include #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 SampleSorter::levels() +Levels SampleSorter::levels() { - QVector 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::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::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::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 +#include #include "selection.h" +class Level { +public: + int velocity; + QMap selections; +}; + +typedef QVector Levels; + class SampleSorter : public QWidget { Q_OBJECT public: SampleSorter(); Selections selections(); - QVector 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 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 Selections; -- cgit v1.2.3