From 7776aa97fc1c69a8f28ba4bab7387fb96be9a6e4 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Mon, 8 Sep 2014 20:48:38 +0200 Subject: Import dgedit from drumgizmo repository (split into its own project). --- src/Makefile.am | 73 ++++++ src/audioextractor.cc | 283 ++++++++++++++++++++++ src/audioextractor.h | 66 ++++++ src/canvas.cc | 285 +++++++++++++++++++++++ src/canvas.h | 95 ++++++++ src/canvastool.cc | 78 +++++++ src/canvastool.h | 62 +++++ src/canvastoollisten.cc | 81 +++++++ src/canvastoollisten.h | 61 +++++ src/canvastoolselections.cc | 319 +++++++++++++++++++++++++ src/canvastoolselections.h | 93 ++++++++ src/canvastoolthreshold.cc | 120 ++++++++++ src/canvastoolthreshold.h | 61 +++++ src/canvaswidget.cc | 93 ++++++++ src/canvaswidget.h | 57 +++++ src/dgedit.cc | 39 ++++ src/dgedit.qrc | 7 + src/filelist.cc | 186 +++++++++++++++ src/filelist.h | 78 +++++++ src/itemeditor.cc | 40 ++++ src/itemeditor.h | 49 ++++ src/mainwindow.cc | 555 ++++++++++++++++++++++++++++++++++++++++++++ src/mainwindow.h | 124 ++++++++++ src/mipmap.cc | 99 ++++++++ src/mipmap.h | 62 +++++ src/player.cc | 190 +++++++++++++++ src/player.h | 131 +++++++++++ src/samplesorter.cc | 271 +++++++++++++++++++++ src/samplesorter.h | 78 +++++++ src/selection.cc | 106 +++++++++ src/selection.h | 135 +++++++++++ src/selectioneditor.cc | 114 +++++++++ src/selectioneditor.h | 63 +++++ src/sleep.h | 57 +++++ src/volumefader.cc | 97 ++++++++ src/volumefader.h | 65 ++++++ src/zoomslider.cc | 108 +++++++++ src/zoomslider.h | 73 ++++++ 38 files changed, 4554 insertions(+) create mode 100644 src/Makefile.am create mode 100644 src/audioextractor.cc create mode 100644 src/audioextractor.h create mode 100644 src/canvas.cc create mode 100644 src/canvas.h create mode 100644 src/canvastool.cc create mode 100644 src/canvastool.h create mode 100644 src/canvastoollisten.cc create mode 100644 src/canvastoollisten.h create mode 100644 src/canvastoolselections.cc create mode 100644 src/canvastoolselections.h create mode 100644 src/canvastoolthreshold.cc create mode 100644 src/canvastoolthreshold.h create mode 100644 src/canvaswidget.cc create mode 100644 src/canvaswidget.h create mode 100644 src/dgedit.cc create mode 100644 src/dgedit.qrc create mode 100644 src/filelist.cc create mode 100644 src/filelist.h create mode 100644 src/itemeditor.cc create mode 100644 src/itemeditor.h create mode 100644 src/mainwindow.cc create mode 100644 src/mainwindow.h create mode 100644 src/mipmap.cc create mode 100644 src/mipmap.h create mode 100644 src/player.cc create mode 100644 src/player.h create mode 100644 src/samplesorter.cc create mode 100644 src/samplesorter.h create mode 100644 src/selection.cc create mode 100644 src/selection.h create mode 100644 src/selectioneditor.cc create mode 100644 src/selectioneditor.h create mode 100644 src/sleep.h create mode 100644 src/volumefader.cc create mode 100644 src/volumefader.h create mode 100644 src/zoomslider.cc create mode 100644 src/zoomslider.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..734152c --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,73 @@ +bin_PROGRAMS = dgedit + +dgedit_LDADD = $(SNDFILE_LIBS) $(QT_LIBS) $(AO_LIBS) \ + $(shell ../tools/MocList o ) qrc_dgedit.o + +dgedit_CXXFLAGS = $(SNDFILE_CXXFLAGS) $(QT_CFLAGS) $(AO_CFLAGS) +AM_CXXFLAGS = $(QT_CFLAGS) + +dgedit_SOURCES = \ + dgedit.cc \ + audioextractor.cc \ + canvas.cc \ + canvastool.cc \ + canvastoollisten.cc \ + canvastoolselections.cc \ + canvastoolthreshold.cc \ + canvaswidget.cc \ + filelist.cc \ + itemeditor.cc \ + mainwindow.cc \ + mipmap.cc \ + player.cc \ + samplesorter.cc \ + selection.cc \ + selectioneditor.cc \ + volumefader.cc \ + zoomslider.cc + +EXTRA_DIST = \ + audioextractor.h \ + canvas.h \ + canvastool.h \ + canvastoollisten.h \ + canvastoolselections.h \ + canvastoolthreshold.h \ + canvaswidget.h \ + filelist.h \ + itemeditor.h \ + mainwindow.h \ + mipmap.h \ + player.h \ + samplesorter.h \ + selection.h \ + selectioneditor.h \ + sleep.h \ + volumefader.h \ + zoomslider.h \ + dgedit.qrc + +dgedit_MOC = $(shell ../tools/MocList cc ) + +BUILT_SOURCES = $(dgedit_MOC) qrc_dgedit.cc + +CLEANFILES = $(BUILT_SOURCES) + +qrc_%.cc: %.qrc + rcc $< > $@ + +%.moc.cc: %.h + $(QT_MOC) -o $@ $< + +# +# ui files not used in this project... +#%.h: %.ui +# $(QT_UIC) -o $@ $< +# +#%.cc: %.ui +# $(QT_UIC) -o $@ -impl $*.h $< + +# command for creating .res file from .rc on Win32 +%.res: %.rc + rc $< + diff --git a/src/audioextractor.cc b/src/audioextractor.cc new file mode 100644 index 0000000..71e0b2a --- /dev/null +++ b/src/audioextractor.cc @@ -0,0 +1,283 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * audioextractor.cc + * + * Sat Nov 21 13:09:35 CET 2009 + * Copyright 2009 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 "audioextractor.h" + +#include +#include +#include +#include + +#include + +#define INSTRUMENT_VERSION "2.0" + +typedef struct { + SNDFILE *fh; + float *data; +} audiodata_t; + +AudioExtractor::AudioExtractor(Selections &s, QObject *parent) + : QObject(parent), selections(s) +{ +} + +void AudioExtractor::exportSelections() +{ + emit setMaximumProgress(selections.ids().size() + 1/* for xml writing*/); + int progress = 0; + emit progressUpdate(progress++); + qApp->processEvents(); + + // Open all input audio files: + audiodata_t audiodata[audiofiles.size()]; + + int idx = 0; + AudioFileList::iterator j = audiofiles.begin(); + while(j != audiofiles.end()) { + QString file = j->first; + + SF_INFO sf_info; + audiodata[idx].fh = sf_open(file.toStdString().c_str(), SFM_READ, &sf_info); + if(!audiodata[idx].fh) { + printf("Load error '%s'\n", file.toStdString().c_str()); + return; + } + + audiodata[idx].data = NULL; + + j++; + idx++; + } + + idx = 1; + QVector sels = selections.ids(); + + // Sort selections by velocity + for(int v1 = 0; v1 < sels.size(); v1++) { + for(int v2 = 0; v2 < sels.size(); v2++) { + + Selection sel1 = selections.get(sels[v1]); + Selection sel2 = selections.get(sels[v2]); + + if(sel1.energy < sel2.energy) { + sel_id_t vtmp = sels[v1]; + sels[v1] = sels[v2]; + sels[v2] = vtmp; + } + } + } + + // Iterate and write audio files + QVector::iterator si = sels.begin(); + while(si != sels.end()) { + Selection sel = selections.get(*si); + size_t offset = sel.from; + size_t size = sel.to - sel.from; + size_t fadein = sel.fadein; + size_t fadeout = sel.fadeout; + + + // Read all input audio file chunks: + for(int i = 0; i < audiofiles.size(); i++) { + + // Clear out old buffer (if one exists) + if(audiodata[i].data) { + delete audiodata[i].data; + audiodata[i].data = NULL; + } + + SNDFILE *fh = audiodata[i].fh; + + sf_seek(fh, offset, SEEK_SET); + + float *data = new float[size]; + sf_read_float(fh, data, size); + + // Apply linear fadein + for(size_t fi = 0; fi < fadein; fi++) { + float val = ((float)fi / (float)fadein); + if(fi < size) data[fi] *= val; + } + + // Apply fadeout + for(size_t fo = 0; fo < fadeout; fo++) { + float val = 1.0 - ((float)fo / (float)fadeout); + if( (((size - fadeout) + fo) < size) && + (((size - fadeout) + fo) >= 0) ) { + data[(size - fadeout) + fo] *= val; + } + } + + audiodata[i].data = data; + } + + // Create output path: + QString path = exportpath + "/" + prefix + "/samples"; + QDir d; + d.mkpath(path); + + // Write all sample chunks to single output file: + QString file = path + "/" + QString::number(idx) + "-" + prefix + ".wav"; + + SF_INFO sf_info; + sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; + sf_info.samplerate = 44100; + sf_info.channels = audiofiles.size(); + + SNDFILE *ofh = sf_open(file.toStdString().c_str(), SFM_WRITE, &sf_info); + if(!ofh) { + printf("Open for write error...\n"); + return; + } + + for(size_t ob = 0; ob < size; ob++) { + float obuf[audiofiles.size()]; + for(int ai = 0; ai < audiofiles.size(); ai++) { + obuf[ai] = audiodata[ai].data[ob]; + } + sf_write_float(ofh, obuf, audiofiles.size()); + } + sf_close(ofh); + + idx++; + si++; + + emit progressUpdate(progress++); + qApp->processEvents(); + } + + // Close all input audio files: + for(int i = 0; i < audiofiles.size(); i++) { + if(audiodata[i].data) { + delete audiodata[i].data; + audiodata[i].data = NULL; + } + + sf_close(audiodata[i].fh); + } + + QDomDocument doc; + QDomProcessingInstruction header = + doc.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); + doc.appendChild(header); + + QDomElement instrument = doc.createElement("instrument"); + instrument.setAttribute("version", INSTRUMENT_VERSION); + instrument.setAttribute("name", prefix); + doc.appendChild(instrument); + + QDomElement samples = doc.createElement("samples"); + instrument.appendChild(samples); + + { + // Do the adding to the xml file one sample at the time. + int index = 0; + QVector::iterator si = sels.begin(); + while(si != sels.end()) { + 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)); + samples.appendChild(sample); + + selections.update(*si, i); + + int channelnum = 1; // Filechannel numbers are 1-based. + AudioFileList::iterator j = audiofiles.begin(); + while(j != audiofiles.end()) { + + QString file = j->first; + QString name = j->second; + + QDomElement audiofile = doc.createElement("audiofile"); + audiofile.setAttribute("file", "samples/" + + QString::number(index) + "-" + prefix + ".wav"); + audiofile.setAttribute("channel", name); + audiofile.setAttribute("filechannel", QString::number(channelnum)); + sample.appendChild(audiofile); + channelnum++; + j++; + } + + si++; + } + } + + QFile xmlfile(exportpath + "/" + prefix + "/" + prefix + ".xml"); + xmlfile.open(QIODevice::WriteOnly); + xmlfile.write(doc.toByteArray()); + xmlfile.close(); + + emit progressUpdate(progress++); + qApp->processEvents(); +} + +void AudioExtractor::addFile(QString file, QString name) +{ + QPair pair; + pair.first = file; + pair.second = name; + audiofiles.push_back(pair); +} + +void AudioExtractor::removeFile(QString file, QString name) +{ + AudioFileList::iterator j = audiofiles.begin(); + while(j != audiofiles.end()) { + if(file == j->first/* && name == j->second*/) { + audiofiles.erase(j); + return; + } + j++; + } +} + +void AudioExtractor::setOutputPrefix(const QString &p) +{ + prefix = p; +} + +void AudioExtractor::setExportPath(const QString &path) +{ + exportpath = path; +} + +void AudioExtractor::changeName(QString file, QString name) +{ + AudioFileList::iterator j = audiofiles.begin(); + while(j != audiofiles.end()) { + if(file == j->first) { + j->second = name; + return; + } + j++; + } +} diff --git a/src/audioextractor.h b/src/audioextractor.h new file mode 100644 index 0000000..ae50d17 --- /dev/null +++ b/src/audioextractor.h @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * audioextractor.h + * + * Sat Nov 21 13:09:35 CET 2009 + * Copyright 2009 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_AUDIOEXTRACTOR_H__ +#define __DRUMGIZMO_AUDIOEXTRACTOR_H__ + +#include +#include +#include +#include +#include + +#include "selection.h" +#include "samplesorter.h" + +typedef QLinkedList< QPair > AudioFileList; + +class AudioExtractor : public QObject { +Q_OBJECT +public: + 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(); + void setExportPath(const QString &path); + void setOutputPrefix(const QString &prefix); + +signals: + void progressUpdate(int value); + void setMaximumProgress(int value); + +private: + Selections &selections; + AudioFileList audiofiles; + QString exportpath; + QString prefix; +}; + +#endif/*__DRUMGIZMO_AUDIOEXTRACTOR_H__*/ diff --git a/src/canvas.cc b/src/canvas.cc new file mode 100644 index 0000000..7007b0b --- /dev/null +++ b/src/canvas.cc @@ -0,0 +1,285 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvas.cc + * + * Tue Nov 10 08:37:37 CET 2009 + * Copyright 2009 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 "canvas.h" + +#include +#include +#include +#include +#include + +#include + +#define DEFYSCALE 200 + +Canvas::Canvas(QWidget *parent) + : 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; + yoffset = 0.5; + + colBg = QColor(180, 200, 180); + colSec = QColor(160, 180, 160); + colWavMax = QColor(100, 100, 100); + colWavAvg = QColor(0, 0, 0); + colMax = QColor(127, 127, 255); + colHalf = QColor(180, 180, 255); + + setCursor(Qt::ArrowCursor); + + wav = QImage(width(), height(), QImage::Format_RGB32); +} + +Canvas::~Canvas() +{ + if(data) delete[] data; + if(mipmap) delete mipmap; +} + +void Canvas::load(QString file) +{ + if(data) { + delete[] data; + data = NULL; + size = 0; + } + + 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_info.frames; + + printf("Size: %u\n", (unsigned int)sf_info.frames); + data = new float[size]; + + sf_read_float(fh, data, size); + + sf_close(fh); + + mipmap = new MipMap(data, size); + + updateWav(); + update(); +} + + +#define SCALEX ((xscale * (float)size/(float)width()) + 0.1) +#define OFFSETX (xoffset * (float)size) +float Canvas::mapX(float x) +{ + float val = (x - OFFSETX) / SCALEX; + return val; +} + +float Canvas::unmapX(float x) +{ + float val = x * SCALEX + OFFSETX; + return val; +} + +#define SCALEY (yscale * height()) +#define OFFSETY (((float)height() / 2.0) + ((yoffset * 2.0 - 1.0) * SCALEY)) +float Canvas::mapY(float y) +{ + float val = OFFSETY + (y * SCALEY); + return val; +} + +float Canvas::unmapY(float y) +{ + float val = (y - OFFSETY) / SCALEY; + return val; +} + +void Canvas::mouseMoveEvent(QMouseEvent *event) +{ + for(int i = 0; i < tools.size(); i++) { + if(tools[i]->mouseMoveEvent(event)) return; + } + + setCursor(Qt::ArrowCursor); +} + +void Canvas::mousePressEvent(QMouseEvent *event) +{ + for(int i = 0; i < tools.size(); i++) { + if(tools[i]->mousePressEvent(event)) return; + } +} + +void Canvas::mouseReleaseEvent(QMouseEvent *event) +{ + for(int i = 0; i < tools.size(); i++) { + if(tools[i]->mouseReleaseEvent(event)) return; + } +} + +void Canvas::resizeEvent(QResizeEvent *event) +{ + for(int i = 0; i < tools.size(); i++) { + tools[i]->resizeEvent(event); + } + + wav = QImage(width(), height(), QImage::Format_RGB32); + updateWav(); + update(); +} + +void Canvas::getWavValues(int last, int lx, float *vu, float *vl, + float *avgu, float *avgl) +{ + if(mipmap == NULL) return; + + MipMapValue val = mipmap->lookup(last, lx); + + *vu = val.max; + *vl = val.min; + *avgu = val.uavg; + *avgl = val.lavg; +} + +void Canvas::updateWav() +{ + QPainter painter(&wav); + + painter.setPen(colBg); + painter.setBrush(colBg); + painter.drawRect(0, 0, wav.width(), wav.height()); + + painter.setPen(colSec); + int step = 44100; + for(size_t i = 0; i < size; i += step) { + painter.drawLine(mapX(i), mapY(1.0), mapX(i), mapY(-1.0)); + } + + painter.setPen(colMax); + painter.drawLine(0, mapY(1.0), wav.width(), mapY(1.0)); + painter.drawLine(0, mapY(-1.0), wav.width(), mapY(-1.0)); + + painter.setPen(colHalf); + painter.drawLine(0, mapY(0.5), wav.width(), mapY(0.5)); + painter.drawLine(0, mapY(-0.5), wav.width(), mapY(-0.5)); + + if(data) { + int last = unmapX(0); + for(int x = 0; x < wav.width(); x++) { + int lx = unmapX(x); + if(lx > (int)size || lx < 0) break; + float vu = 0; + float vl = 0; + float avgu = 0; + float avgl = 0; + + getWavValues(last, lx, &vu, &vl, &avgu, &avgl); + + int c = mapY(0.0); + + painter.setPen(colWavMax); + painter.drawLine(x, c, x, mapY(vu)); + painter.drawLine(x, c, x, mapY(vl)); + + painter.setPen(colWavAvg); + painter.drawLine(x, c, x, mapY(avgu)); + painter.drawLine(x, c, x, mapY(avgl)); + + last = lx; + } + } +} + +void Canvas::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + + painter.drawImage(event->rect(),wav,event->rect()); + + for(int i = 0; i < tools.size(); i++) { + tools[i]->paintEvent(event, painter); + } +} + +void Canvas::keyReleaseEvent(QKeyEvent *event) +{ + for(int i = 0; i < tools.size(); i++) { + tools[i]->keyReleaseEvent(event); + } +} + +void Canvas::setXScale(float scale) +{ + scale = (pow(100.0,scale) / 100.0) - (pow(100.0, 0.0)/ 100.0); + if(scale < 0.0) scale = 0.0; + if(scale > 1.0) scale = 1.0; + xscale = scale; + updateWav(); + update(); +} + +void Canvas::setYScale(float scale) +{ + yscale = scale; + updateWav(); + update(); +} + +void Canvas::setXOffset(float offset) +{ + if(offset < 0.0) offset = 0.0; + if(offset > 1.0) offset = 1.0; + xoffset = offset; + updateWav(); + update(); +} + +void Canvas::setYOffset(float offset) +{ + if(offset < 0.0) offset = 0.0; + if(offset > 1.0) offset = 1.0; + yoffset = offset; + updateWav(); + update(); +} diff --git a/src/canvas.h b/src/canvas.h new file mode 100644 index 0000000..c83a726 --- /dev/null +++ b/src/canvas.h @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvas.h + * + * Tue Nov 10 08:37:37 CET 2009 + * Copyright 2009 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_CANVAS_H__ +#define __DRUMGIZMO_CANVAS_H__ + +#include +#include +#include + +#include "mipmap.h" +#include "canvastool.h" + +class Canvas : public QWidget { +Q_OBJECT +public: + Canvas(QWidget *parent); + ~Canvas(); + + void load(QString file); + + void addTool(CanvasTool *tool); + + float mapX(float x); + float unmapX(float x); + float mapY(float y); + float unmapY(float y); + +public slots: + void setXScale(float scale); + void setYScale(float scale); + void setXOffset(float scroll); + void setYOffset(float scroll); + +protected: + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void resizeEvent(QResizeEvent *event); + void paintEvent(QPaintEvent *event); + void keyReleaseEvent(QKeyEvent *event); + +private: + MipMap *mipmap; + + void updateWav(); + void getWavValues(int last, int lx, float *vu, float *vl, + float *avgu, float *avgl); + + QImage wav; + +public: + float *data; + size_t size; + + QVector tools; + +private: + float xscale; + float yscale; + float xoffset; + float yoffset; + + QColor colBg; + QColor colSec; + QColor colMax; + QColor colHalf; + QColor colWavMax; + QColor colWavAvg; +}; + +#endif/*__DRUMGIZMO_CANVAS_H__*/ diff --git a/src/canvastool.cc b/src/canvastool.cc new file mode 100644 index 0000000..9d23d97 --- /dev/null +++ b/src/canvastool.cc @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastool.cc + * + * Thu Jul 28 23:01:36 CEST 2011 + * Copyright 2011 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 "canvastool.h" + +#include + +bool CanvasTool::mouseMoveEvent(QMouseEvent *) +{ + return false; +} + +bool CanvasTool::mousePressEvent(QMouseEvent *) +{ + return false; +} + +bool CanvasTool::mouseReleaseEvent(QMouseEvent *) +{ + return false; +} + +void CanvasTool::resizeEvent(QResizeEvent *) +{ +} + +void CanvasTool::paintEvent(QPaintEvent *, QPainter &) +{ +} + +void CanvasTool::keyReleaseEvent(QKeyEvent *) +{ +} + +void CanvasTool::setActive(bool active) +{ + printf("setActive(%d)\n", active); + _active = active; + emit activateChanged(active); +} + +void CanvasTool::activate() +{ + setActive(true); +} + +void CanvasTool::disactivate() +{ + setActive(false); +} + +bool CanvasTool::isActive() +{ + return _active; +} diff --git a/src/canvastool.h b/src/canvastool.h new file mode 100644 index 0000000..56cfa84 --- /dev/null +++ b/src/canvastool.h @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastool.h + * + * Thu Jul 28 20:12:25 CEST 2011 + * Copyright 2011 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_CANVASTOOL_H__ +#define __DRUMGIZMO_CANVASTOOL_H__ + +#include +#include +#include +#include +#include +#include + +class CanvasTool : public QObject { +Q_OBJECT +public: + virtual QString name() = 0; + virtual bool mouseMoveEvent(QMouseEvent *event); + virtual bool mousePressEvent(QMouseEvent *event); + virtual bool mouseReleaseEvent(QMouseEvent *event); + virtual void resizeEvent(QResizeEvent *event); + virtual void paintEvent(QPaintEvent *event, QPainter &painter); + virtual void keyReleaseEvent(QKeyEvent *event); + + bool isActive(); + +signals: + void activateChanged(bool activestate); + +public slots: + void setActive(bool active); + void activate(); + void disactivate(); + +private: + bool _active; +}; + +#endif/*__DRUMGIZMO_CANVASTOOL_H__*/ diff --git a/src/canvastoollisten.cc b/src/canvastoollisten.cc new file mode 100644 index 0000000..847c32d --- /dev/null +++ b/src/canvastoollisten.cc @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoollisten.cc + * + * Fri Jul 29 16:57:48 CEST 2011 + * Copyright 2011 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 "canvastoollisten.h" + +#include + +CanvasToolListen::CanvasToolListen(Canvas *c, Player &p) + : player(p) +{ + lastpos = pos = 0; + canvas = c ; +} + +bool CanvasToolListen::mousePressEvent(QMouseEvent *event) +{ + if(!isActive()) return false; + player.setPosition(canvas->unmapX(event->x())); + canvas->update(); + connect(&player, SIGNAL(positionUpdate(size_t)), this, SLOT(update(size_t))); + return true; +} + +bool CanvasToolListen::mouseReleaseEvent(QMouseEvent *event) +{ + if(!isActive()) return false; + player.stop(); + disconnect(&player, SIGNAL(positionUpdate(size_t)), + this, SLOT(update(size_t))); + lastpos = 0; + canvas->update(); + return true; +} + +void CanvasToolListen::paintEvent(QPaintEvent *event, QPainter &painter) +{ + if(!isActive()) return; + + if(player.pos < player.end) { + painter.setPen(QColor(0, 127, 127)); + painter.drawLine(canvas->mapX(pos), + event->rect().y(), + canvas->mapX(pos), + event->rect().y() + event->rect().height()); + } +} + +void CanvasToolListen::update(size_t pos) +{ + this->pos = pos; + size_t last = canvas->mapX(lastpos); + size_t x = canvas->mapX(player.pos); + QRect r(last, 0, + x - last + 2, canvas->height()); + + canvas->update(r); + lastpos = pos; +} diff --git a/src/canvastoollisten.h b/src/canvastoollisten.h new file mode 100644 index 0000000..bfb2d41 --- /dev/null +++ b/src/canvastoollisten.h @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoollisten.h + * + * Fri Jul 29 16:57:48 CEST 2011 + * Copyright 2011 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_CANVASTOOLLISTEN_H__ +#define __DRUMGIZMO_CANVASTOOLLISTEN_H__ + +#include "canvastool.h" + +//#include + +#include "canvas.h" +#include "player.h" + +class CanvasToolListen : public CanvasTool { +Q_OBJECT +public: + CanvasToolListen(Canvas *canvas, Player &player); + + QString name() { return "Listen"; } + bool mousePressEvent(QMouseEvent *event); + bool mouseReleaseEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event, QPainter &painter); + + void playRange(unsigned int from, unsigned int to); + +public slots: + void update(size_t position); + +private: + Canvas *canvas; + + Player &player; + + size_t lastpos; + size_t pos; +}; + +#endif/*__DRUMGIZMO_CANVASTOOLLISTEN_H__*/ diff --git a/src/canvastoolselections.cc b/src/canvastoolselections.cc new file mode 100644 index 0000000..ad5e193 --- /dev/null +++ b/src/canvastoolselections.cc @@ -0,0 +1,319 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoolselections.cc + * + * Thu Jul 28 20:16:59 CEST 2011 + * Copyright 2011 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 "canvastoolselections.h" + +#include +#include + +#define mapX(x) canvas->mapX(x) +#define mapY(x) canvas->mapY(x) +#define unmapX(x) canvas->unmapX(x) +#define unmapY(x) canvas->unmapY(x) + +CanvasToolSelections::CanvasToolSelections(Canvas *c, Selections &s, + Selections &p) + : selections(s), selections_preview(p) +{ + threshold = 0.5; // Default from CanvasToolThreshold + hold = 100; + + canvas = c; + + selection_is_moving_left = false; + selection_is_moving_right = false; + + colSelBg = QColor(255, 0, 0, 60); + colSel = QColor(255, 0, 0, 160); + colActiveSelBg = QColor(255, 255, 0, 60); + colActiveSel = QColor(255, 255, 0, 160); + colPreviewSelBg = QColor(0, 0, 255, 60); + colPreviewSel = QColor(0, 0, 255, 160); +} + +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 > act_sel.to) val = act_sel.to - 1; + act_sel.from = val; + selections.update(active_selection, act_sel); + canvas->update(); + return true; + } + + if(selection_is_moving_right) { + float val = unmapX(event->x()); + if(val < act_sel.from) val = act_sel.from + 1; + act_sel.to = val; + selections.update(active_selection, act_sel); + canvas->update(); + return true; + } + + if(event->button() != Qt::LeftButton) { + // Check if a selection is being dragged. + QVector ids = selections.ids(); + QVector::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections.get(*i); + if(abs(event->x() - mapX(sel.from)) < 2 + || abs(event->x() - mapX(sel.to)) < 2) { + canvas->setCursor(Qt::SplitHCursor); + return true; + } + i++; + } + } + + return false; +} + +bool CanvasToolSelections::mousePressEvent(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) { + // Check if a selection is being dragged. + QVector ids = selections.ids(); + QVector::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections.get(*i); + if(abs(event->x() - mapX(sel.from)) < 2) { + selections.setActive(*i); + selection_is_moving_left = true; + return true; + } + + if(abs(event->x() - mapX(sel.to)) < 2) { + selections.setActive(*i); + selection_is_moving_right = true; + return true; + } + + i++; + } + + // Check if a selection is being selected. + 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(); + return true; + } + + i++; + } + + // Make new selection + int from = unmapX(event->x()); + 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; + } + + return false; +} + +bool CanvasToolSelections::mouseReleaseEvent(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) { + if(selection_is_moving_left || selection_is_moving_right) { + selection_is_moving_left = false; + selection_is_moving_right = false; + canvas->setCursor(Qt::ArrowCursor); + canvas->update(); + return true; + } + } + + return false; +} + +void CanvasToolSelections::paintEvent(QPaintEvent *event, QPainter &painter) +{ + int pos = unmapX(event->rect().x()); + int width = unmapX(event->rect().width()); + + { + QVector ids = selections.ids(); + QVector::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections.get(*i); + int from = sel.from; + int to = sel.to; + int fadein = sel.fadein; + int fadeout = sel.fadeout; + if(from > pos + width || to + width < pos) { i++; continue; } + if(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.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)); + painter.drawLine(mapX(to - fadeout), mapY(1.0), mapX(to), mapY(0.0)); + i++; + } + } + + if(show_preview) { + QVector ids = selections_preview.ids(); + QVector::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections_preview.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; } + painter.setBrush(colPreviewSelBg); + painter.setPen(colPreviewSel); + + 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)); + painter.drawLine(mapX(to - fadeout), mapY(1.0), mapX(to), mapY(0.0)); + i++; + } + } +} + +void CanvasToolSelections::keyReleaseEvent(QKeyEvent *event) +{ + if(selections.active() != SEL_NONE && event->key() == Qt::Key_Delete) { + selections.remove(selections.active()); + canvas->update(); + } +} + +void CanvasToolSelections::thresholdChanged(double t) +{ + threshold = t; +} + +void CanvasToolSelections::holdChanged(int h) +{ + hold = h; +} + +void CanvasToolSelections::noiseFloorChanged(int t) +{ + double div = 666.0 / 0.00003; + noise_floor = (double)t/div; +} + +void CanvasToolSelections::fadeoutChanged(int t) +{ + fadeout = (double)t/1000.0; +} + +void CanvasToolSelections::autoCreateSelections() +{ + doAutoCreateSelections(false); +} + +void CanvasToolSelections::autoCreateSelectionsPreview() +{ + doAutoCreateSelections(true); +} + +void CanvasToolSelections::doAutoCreateSelections(bool preview) +{ + float *data = canvas->data; + size_t size = canvas->size; + + if(preview) selections_preview.clear(); + + for(size_t i = 0; i < size; i++) { + if(fabs(data[i]) > fabs(threshold)) { + int from = i; + + if(data[from] > 0.0) { + while(data[from] > data[from-1] // Falling + && data[from-1] > 0.0 // Not crossing zero + ) { + from--; + } + } else if(data[from] < 0.0) { + while(data[from] < data[from-1] // Rising + && data[from-1] < 0.0 // Not crossing zero + ) { + from--; + } + } + + int to = i; + float runavg = fabs(data[from]); + while((runavg > noise_floor || + to < from + hold) && + to < (int)size) { + double p = 0.9; + runavg = runavg * p + fabs(data[to]) * (1 - p); + to++; + } + + Selection s(from, to, 2, ((to - from) / 3) * fadeout); + if(preview) { + selections_preview.add(s); + } else { + selections.add(s); + } + + i = to+1; + } + } + canvas->update(); +} + +void CanvasToolSelections::clearSelections() +{ + selections.clear(); + selection_is_moving_left = false; + selection_is_moving_right = false; + canvas->setCursor(Qt::ArrowCursor); + canvas->update(); +} + +void CanvasToolSelections::setShowPreview(bool s) +{ + show_preview = s; + canvas->update(); +} diff --git a/src/canvastoolselections.h b/src/canvastoolselections.h new file mode 100644 index 0000000..0557520 --- /dev/null +++ b/src/canvastoolselections.h @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoolselections.h + * + * Thu Jul 28 20:16:59 CEST 2011 + * Copyright 2011 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_CANVASTOOLSELECTIONS_H__ +#define __DRUMGIZMO_CANVASTOOLSELECTIONS_H__ + +#include "canvastool.h" + +#include + +#include "canvas.h" + +#include "selection.h" + +class CanvasToolSelections : public CanvasTool { +Q_OBJECT +public: + CanvasToolSelections(Canvas *canvas, Selections &selections, + Selections &selections_preview); + + QString name() { return "Selections"; } + bool mouseMoveEvent(QMouseEvent *event); + bool mousePressEvent(QMouseEvent *event); + bool mouseReleaseEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event, QPainter &painter); + void keyReleaseEvent(QKeyEvent *event); + + //Selections selections(); + +signals: + //void selectionsChanged(Selections selections); + //void activeSelectionChanged(sel_id_t id); + +public slots: + void autoCreateSelections(); + void autoCreateSelectionsPreview(); + void clearSelections(); + void thresholdChanged(double threshold); + void noiseFloorChanged(int t); + void holdChanged(int h); + void fadeoutChanged(int f); + void setShowPreview(bool show_preview); + +private: + void doAutoCreateSelections(bool preview); + + bool selection_is_moving_left; + bool selection_is_moving_right; + + Canvas *canvas; + + double threshold; + double noise_floor; + double fadeout; + int hold; + + QColor colSelBg; + QColor colSel; + QColor colActiveSelBg; + QColor colActiveSel; + QColor colPreviewSelBg; + QColor colPreviewSel; + + Selections &selections; + Selections &selections_preview; + + bool show_preview; +}; + +#endif/*__DRUMGIZMO_CANVASTOOLSELECTIONS_H__*/ diff --git a/src/canvastoolthreshold.cc b/src/canvastoolthreshold.cc new file mode 100644 index 0000000..a321ff2 --- /dev/null +++ b/src/canvastoolthreshold.cc @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoolthreshold.cc + * + * Fri Jul 29 16:27:00 CEST 2011 + * Copyright 2011 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 "canvastoolthreshold.h" + +#include + +#define mapX(x) canvas->mapX(x) +#define mapY(x) canvas->mapY(x) +#define unmapX(x) canvas->unmapX(x) +#define unmapY(x) canvas->unmapY(x) + +CanvasToolThreshold::CanvasToolThreshold(Canvas *c) +{ + canvas = c; + threshold = 0.5; + threshold_is_moving = false; + + colThreshold = QColor(255, 127, 127); + colThresholdMoving = QColor(180, 0, 0); +} + +bool CanvasToolThreshold::mouseMoveEvent(QMouseEvent *event) +{ + if(!isActive()) return false; + + if(event->button() != Qt::LeftButton) { + if(abs(event->y() - mapY(threshold)) < 2 || + abs(event->y() - mapY(-threshold)) < 2 ) { + canvas->setCursor(Qt::SplitVCursor); + return true; + } + } + + if(threshold_is_moving) { + float val = unmapY(event->y()); + if(fabs(val) > 1.0) val = 1.0; + threshold = fabs(val); + canvas->update(); + + emit thresholdChanging(threshold); + + return true; + } + + return false; +} + +bool CanvasToolThreshold::mousePressEvent(QMouseEvent *event) +{ + if(!isActive()) return false; + + if(event->button() == Qt::LeftButton) { + + // Check if threshold is being dragged. + if(abs(event->y() - mapY(threshold)) < 2 || + abs(event->y() - mapY(-threshold)) < 2 ) { + threshold_is_moving = true; + canvas->update(); + return true; + } + } + + return false; +} + +bool CanvasToolThreshold::mouseReleaseEvent(QMouseEvent *event) +{ + if(!isActive()) return false; + + if(event->button() == Qt::LeftButton) { + if(threshold_is_moving) { + threshold_is_moving = false; + canvas->setCursor(Qt::ArrowCursor); + canvas->update(); + + emit thresholdChanged(threshold); + + return true; + } + } + + return false; +} + +void CanvasToolThreshold::paintEvent(QPaintEvent *event, QPainter &painter) +{ + if(!isActive()) return; + + if(threshold_is_moving) painter.setPen(colThresholdMoving); + else painter.setPen(colThreshold); + painter.drawLine(event->rect().x(), mapY(threshold), + event->rect().x() + event->rect().width(), mapY(threshold)); + painter.drawLine(event->rect().x(), mapY(-threshold), + event->rect().x() + event->rect().width(), mapY(-threshold)); +} + diff --git a/src/canvastoolthreshold.h b/src/canvastoolthreshold.h new file mode 100644 index 0000000..907e312 --- /dev/null +++ b/src/canvastoolthreshold.h @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoolthreshold.h + * + * Fri Jul 29 16:27:00 CEST 2011 + * Copyright 2011 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_CANVASTOOLTHRESHOLD_H__ +#define __DRUMGIZMO_CANVASTOOLTHRESHOLD_H__ + +#include "canvastool.h" + +#include + +#include "canvas.h" + +class CanvasToolThreshold : public CanvasTool { +Q_OBJECT +public: + CanvasToolThreshold(Canvas *canvas); + + QString name() { return "Threshold"; } + bool mouseMoveEvent(QMouseEvent *event); + bool mousePressEvent(QMouseEvent *event); + bool mouseReleaseEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event, QPainter &painter); + +signals: + void thresholdChanged(double threshold); + void thresholdChanging(double threshold); + +private: + float threshold; + bool threshold_is_moving; + + Canvas *canvas; + + QColor colThreshold; + QColor colThresholdMoving; +}; + +#endif/*__DRUMGIZMO_CANVASTOOLTHRESHOLD_H__*/ diff --git a/src/canvaswidget.cc b/src/canvaswidget.cc new file mode 100644 index 0000000..35b3684 --- /dev/null +++ b/src/canvaswidget.cc @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvaswidget.cc + * + * Fri Aug 1 19:31:32 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 "canvaswidget.h" + +#include + +#define MAXVAL 10000000L +#define SINGLESTEP MAXVAL/100000 +#define PAGESTEP MAXVAL/10000 + +CanvasWidget::CanvasWidget(QWidget *parent) +{ + QGridLayout *g = new QGridLayout(this); + + canvas = new Canvas(this); + g->addWidget(canvas, 0, 0); + + yoffset = new QScrollBar(Qt::Vertical); + yoffset->setRange(0, MAXVAL); + yoffset->setPageStep(PAGESTEP); + yoffset->setSingleStep(SINGLESTEP); + connect(yoffset, SIGNAL(valueChanged(int)), this, SLOT(setYOffset(int))); + g->addWidget(yoffset, 0, 1); + + yscale = new ZoomSlider(Qt::Vertical); + yscale->setRange(0.9, 30); + yscale->setTickWidth(0.1); + connect(yscale, SIGNAL(valueChanged(float)), this, SLOT(setYScale(float))); + g->addWidget(yscale, 0, 2); + + xoffset = new QScrollBar(Qt::Horizontal); + xoffset->setRange(0, MAXVAL); + xoffset->setPageStep(PAGESTEP); + xoffset->setSingleStep(SINGLESTEP); + connect(xoffset, SIGNAL(valueChanged(int)), this, SLOT(setXOffset(int))); + g->addWidget(xoffset, 1, 0); + + xscale = new ZoomSlider(Qt::Horizontal); + xscale->setRange(1, 0.0001); + xscale->setTickWidth(0.0001); + connect(xscale, SIGNAL(valueChanged(float)), this, SLOT(setXScale(float))); + g->addWidget(xscale, 2, 0); + + setLayout(g); +} + +void CanvasWidget::setXScale(float val) +{ + canvas->setXScale(val); +} + +void CanvasWidget::setYScale(float val) +{ + canvas->setYScale(val); +} + +void CanvasWidget::setXOffset(int of) +{ + // range 0.0 - 1.0 + float val = (float)of/(float)MAXVAL; + canvas->setXOffset(val); +} + +void CanvasWidget::setYOffset(int of) +{ + // range 0.0 - 1.0 + float val = (float)(of * -1 + MAXVAL)/(float)MAXVAL; + canvas->setYOffset(val); +} diff --git a/src/canvaswidget.h b/src/canvaswidget.h new file mode 100644 index 0000000..1ae73da --- /dev/null +++ b/src/canvaswidget.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvaswidget.h + * + * Fri Aug 1 19:31:31 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. + */ +#ifndef __DRUMGIZMO_CANVASWIDGET_H__ +#define __DRUMGIZMO_CANVASWIDGET_H__ + +#include + +#include + +#include "canvas.h" +#include "zoomslider.h" + +class CanvasWidget : public QWidget { +Q_OBJECT +public: + CanvasWidget(QWidget *parent); + + Canvas *canvas; + + QScrollBar *yoffset; + ZoomSlider *yscale; + ZoomSlider *xscale; + QScrollBar *xoffset; + +public slots: + void setXScale(float); + void setYScale(float); + void setXOffset(int); + void setYOffset(int); + +}; + +#endif/*__DRUMGIZMO_CANVASWIDGET_H__*/ diff --git a/src/dgedit.cc b/src/dgedit.cc new file mode 100644 index 0000000..0417876 --- /dev/null +++ b/src/dgedit.cc @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * editor.cc + * + * Tue Nov 10 08:37:43 CET 2009 + * Copyright 2009 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 + +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + MainWindow wnd; + wnd.show(); + + return app.exec(); +} diff --git a/src/dgedit.qrc b/src/dgedit.qrc new file mode 100644 index 0000000..d71c0a0 --- /dev/null +++ b/src/dgedit.qrc @@ -0,0 +1,7 @@ + + + + icons/master.png + icons/file.png + + diff --git a/src/filelist.cc b/src/filelist.cc new file mode 100644 index 0000000..c4e5c4b --- /dev/null +++ b/src/filelist.cc @@ -0,0 +1,186 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * filelist.cc + * + * Mon Nov 30 15:35:52 CET 2009 + * Copyright 2009 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 "filelist.h" + +#include +#include +#include + +#include "itemeditor.h" + +FileList::FileList() +{ + setContextMenuPolicy(Qt::CustomContextMenu); + + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(popupMenu(const QPoint &))); + + connect(this, SIGNAL(itemDoubleClicked(QListWidgetItem *)), + this, SLOT(selectionChanged(QListWidgetItem *))); + + createMenus(); +} + +void FileList::addFiles() +{ + QStringList files = QFileDialog::getOpenFileNames(this, tr("Open file"), + path, tr("Audio Files (*.wav)")); + QStringList::Iterator i = files.begin(); + while(i != files.end()) { + QString file = *i; + QFileInfo fi(file); + QString name = fi.baseName(); + path = fi.absolutePath(); + + QListWidgetItem *item = new QListWidgetItem(); + setItemFile(item, file); + setItemName(item, name); + setItemMaster(item, false); + addItem(item); + + emit fileAdded(file, name); + + i++; + } +} + +void FileList::setMasterFile(QListWidgetItem *i) +{ + QString filename = itemFile(i); + + for(int idx = 0; idx < count(); idx++) { + setItemMaster(item(idx), false); + } + + setItemMaster(i, true); + emit masterFileChanged(filename); +} + +void FileList::selectionChanged(QListWidgetItem *i) +{ + setMasterFile(i); +} + + +void FileList::createMenus() +{ + menu = new QMenu(); + + setMasterAction = new QAction("Set as Master (dbl-click)", this); + connect(setMasterAction, SIGNAL(triggered()), this, SLOT(setMaster())); + + editAction = new QAction("Edit name", this); + connect(editAction, SIGNAL(triggered()), this, SLOT(editName())); + + removeAction = new QAction("Remove", this); + connect(removeAction, SIGNAL(triggered()), this, SLOT(removeFile())); + + removeAllAction = new QAction("Remove all", this); + connect(removeAllAction, SIGNAL(triggered()), this, SLOT(removeAllFiles())); + + menu->addAction(setMasterAction); + menu->addAction(editAction); + menu->addAction(removeAction); + menu->addSeparator(); + menu->addAction(removeAllAction); + +} + +void FileList::popupMenu(const QPoint & pos) +{ + activeItem = itemAt(pos); + if(!activeItem) return; + menu->popup(mapToGlobal(pos)); +} + +void FileList::setMaster() +{ + setMasterFile(activeItem); +} + +void FileList::removeFile() +{ + QString file = itemFile(activeItem); + QString name = itemName(activeItem); + + printf("Removing: %s\n", file.toStdString().c_str()); + delete activeItem;//takeItem(row(activeItem)); + activeItem = NULL; + setCurrentRow(-1); + + emit fileRemoved(file, name); +} + +void FileList::removeAllFiles() +{ + activeItem = NULL; + + clear(); + + emit allFilesRemoved(); +} + +void FileList::editName() +{ + ItemEditor *e = new ItemEditor(activeItem, itemName(activeItem)); + connect(e, SIGNAL(updateItem(QListWidgetItem *, QString)), + this, SLOT(setItemName(QListWidgetItem *, QString))); +} + + +// Item utility functions. +QString FileList::itemFile(QListWidgetItem *i) +{ + return i->data(Qt::ToolTipRole).toString(); +} + +void FileList::setItemFile(QListWidgetItem *i, QString file) +{ + i->setData(Qt::ToolTipRole, file); + i->setData(Qt::DisplayRole, itemName(i) + "\t" + file); +} + +QString FileList::itemName(QListWidgetItem *i) +{ + return i->data(Qt::UserRole).toString(); +} + +void FileList::setItemName(QListWidgetItem *i, QString name) +{ + QString oldname = itemName(i); + + i->setData(Qt::UserRole, name); + i->setData(Qt::DisplayRole, name + "\t" + itemFile(i)); + + if(oldname != "" && oldname != name) emit nameChanged(itemFile(i), name); +} + +void FileList::setItemMaster(QListWidgetItem *i, bool master) +{ + if(master) i->setIcon(QPixmap(":icons/master.png")); + else i->setIcon(QPixmap(":icons/file.png")); +} diff --git a/src/filelist.h b/src/filelist.h new file mode 100644 index 0000000..2ca277c --- /dev/null +++ b/src/filelist.h @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * filelist.h + * + * Mon Nov 30 15:35:52 CET 2009 + * Copyright 2009 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_FILELIST_H__ +#define __DRUMGIZMO_FILELIST_H__ + +#include +#include +#include +#include + +class FileList : public QListWidget { +Q_OBJECT +public: + FileList(); + + QString path; +signals: + void masterFileChanged(QString filename); + void fileAdded(QString file, QString name); + void fileRemoved(QString file, QString name); + void allFilesRemoved(); + void nameChanged(QString file, QString name); + +public slots: + void addFiles(); + void popupMenu(const QPoint &pos); + +private slots: + void selectionChanged(QListWidgetItem *item); + void setMaster(); + void removeFile(); + void removeAllFiles(); + void editName(); + void setItemName(QListWidgetItem *i, QString name); + +private: + QString itemFile(QListWidgetItem *i); + QString itemName(QListWidgetItem *i); + void setItemFile(QListWidgetItem *i, QString file); + void setItemMaster(QListWidgetItem *i, bool master); + + void setMasterFile(QListWidgetItem *i); + void createMenus(); + + QMenu *menu; + QAction *setMasterAction; + QAction *editAction; + QAction *removeAction; + QAction *removeAllAction; + + QListWidgetItem *activeItem; +}; + +#endif/*__DRUMGIZMO_FILELIST_H__*/ diff --git a/src/itemeditor.cc b/src/itemeditor.cc new file mode 100644 index 0000000..1925048 --- /dev/null +++ b/src/itemeditor.cc @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * itemeditor.cc + * + * Tue Dec 1 11:01:40 CET 2009 + * Copyright 2009 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 "itemeditor.h" + +ItemEditor::ItemEditor(QListWidgetItem *i, QString v) +{ + this->i = i; + setText(v); + show(); +} + +void ItemEditor::focusOutEvent(QFocusEvent *) +{ + emit updateItem(i, text()); + close(); +} diff --git a/src/itemeditor.h b/src/itemeditor.h new file mode 100644 index 0000000..b6b9e33 --- /dev/null +++ b/src/itemeditor.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * itemeditor.h + * + * Tue Dec 1 11:01:40 CET 2009 + * Copyright 2009 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_ITEMEDITOR_H__ +#define __DRUMGIZMO_ITEMEDITOR_H__ + +#include +#include +#include + +class ItemEditor : public QLineEdit { +Q_OBJECT +public: + ItemEditor(QListWidgetItem *i, QString v); + +protected: + void focusOutEvent(QFocusEvent *); + +signals: + void updateItem(QListWidgetItem *i, QString v); + +private: + QListWidgetItem *i; +}; + +#endif/*__DRUMGIZMO_ITEMEDITOR_H__*/ diff --git a/src/mainwindow.cc b/src/mainwindow.cc new file mode 100644 index 0000000..05562b6 --- /dev/null +++ b/src/mainwindow.cc @@ -0,0 +1,555 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * mainwindow.cc + * + * Tue Nov 10 10:21:04 CET 2009 + * Copyright 2009 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 "mainwindow.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sleep.h" +#include "canvastool.h" +#include "canvastoolthreshold.h" +#include "volumefader.h" +#include "selectioneditor.h" +#include "zoomslider.h" + + +#define MAXVAL 10000000L +/* +#define SINGLESTEP MAXVAL/100000 +#define PAGESTEP MAXVAL/10000 +*/ + +static void addTool(QToolBar *toolbar, Canvas *canvas, CanvasTool *tool) +{ + QAction *action = new QAction(tool->name(), toolbar); + action->setCheckable(true); + toolbar->addAction(action); + tool->connect(action, SIGNAL(toggled(bool)), tool, SLOT(setActive(bool))); + tool->setActive(false); + canvas->tools.push_back(tool); +} + +MainWindow::MainWindow() +{ + { + int start = 44100 * 60; + Selection p(start, start + 44100 * 60, 0, 0); // one minute selection + selections_preview.add(p); + } + + QWidget *central = new QWidget(); + QHBoxLayout *lh = new QHBoxLayout(); + QVBoxLayout *lv = new QVBoxLayout(); + central->setLayout(lv); + setCentralWidget(central); + + extractor = new AudioExtractor(selections, this); + //canvas = new Canvas(this); + canvaswidget = new CanvasWidget(this); + + QToolBar *toolbar = addToolBar("Tools"); + listen = new CanvasToolListen(canvaswidget->canvas, player); + addTool(toolbar, canvaswidget->canvas, listen); + threshold = new CanvasToolThreshold(canvaswidget->canvas); + canvaswidget->canvas->tools.push_back(threshold);//addTool(toolbar, canvaswidget->canvas, threshold); + tool_selections = new CanvasToolSelections(canvaswidget->canvas, selections, + selections_preview); + connect(threshold, SIGNAL(thresholdChanged(double)), + tool_selections, SLOT(thresholdChanged(double))); + connect(threshold, SIGNAL(thresholdChanging(double)), + tool_selections, SLOT(thresholdChanged(double))); + connect(&selections, SIGNAL(activeChanged(sel_id_t)), + canvaswidget->canvas, SLOT(update())); + connect(&selections, SIGNAL(updated(sel_id_t)), + canvaswidget->canvas, SLOT(update())); + addTool(toolbar, canvaswidget->canvas, tool_selections); + + QMenu *fileMenu = menuBar()->addMenu("&File"); + QAction *act_quit = new QAction("&Quit", this); + fileMenu->addAction(act_quit); + connect(act_quit, SIGNAL(triggered()), this, SLOT(close())); + + // QWidget *dock = new QWidget(); + /* + yoffset = new QScrollBar(Qt::Vertical); + yoffset->setRange(0, MAXVAL); + yoffset->setPageStep(PAGESTEP); + yoffset->setSingleStep(SINGLESTEP); + connect(yoffset, SIGNAL(valueChanged(int)), this, SLOT(setYOffset(int))); + + yscale = new ZoomSlider(Qt::Vertical); + yscale->setRange(0.9, 30); + yscale->setTickWidth(0.1); + connect(yscale, SIGNAL(valueChanged(float)), this, SLOT(setYScale(float))); + + xscale = new ZoomSlider(Qt::Horizontal); + xscale->setRange(1, 0.0001); + xscale->setTickWidth(0.0001); + connect(xscale, SIGNAL(valueChanged(float)), this, SLOT(setXScale(float))); + + xoffset = new QScrollBar(Qt::Horizontal); + xoffset->setRange(0, MAXVAL); + xoffset->setPageStep(PAGESTEP); + xoffset->setSingleStep(SINGLESTEP); + connect(xoffset, SIGNAL(valueChanged(int)), this, SLOT(setXOffset(int))); + */ + sorter = new SampleSorter(selections, selections_preview); + connect(&selections, SIGNAL(added(sel_id_t)), + sorter, SLOT(addSelection(sel_id_t))); + connect(&selections_preview, SIGNAL(added(sel_id_t)), + sorter, SLOT(addSelectionPreview(sel_id_t))); + connect(&selections, SIGNAL(updated(sel_id_t)), sorter, SLOT(relayout())); + connect(&selections_preview, SIGNAL(updated(sel_id_t)), + sorter, SLOT(relayout())); + connect(&selections, SIGNAL(removed(sel_id_t)), sorter, SLOT(relayout())); + connect(&selections_preview, SIGNAL(removed(sel_id_t)), + sorter, SLOT(relayout())); + connect(&selections, SIGNAL(activeChanged(sel_id_t)), + sorter, SLOT(relayout())); + + QPushButton *btn_playsamples = new QPushButton("Play samples"); + connect(btn_playsamples, SIGNAL(clicked()), this, SLOT(playSamples())); + + sb_playsamples = new QScrollBar(Qt::Horizontal); + sb_playsamples->setRange(100, 4000); // ms + + + lh->addWidget(canvaswidget); + //lh->addWidget(yscale); + //lh->addWidget(yoffset); + lv->addLayout(lh, 100); + //lv->addWidget(xscale, 100); + //lv->addWidget(xoffset, 100); + lv->addWidget(sorter, 15); + lv->addWidget(btn_playsamples); + lv->addWidget(sb_playsamples); + + + QDockWidget *dockWidget = new QDockWidget(tr("Dock Widget"), this); + dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + + dockWidget->setWidget(new QWidget()); + dockWidget->widget()->setLayout(new QVBoxLayout()); + +// dockWidget->widget()->layout()->addWidget(new QLabel("Presets:")); +// presets = new QComboBox(); +// connect(presets, SIGNAL(currentIndexChanged(int)), +// this, SLOT(setPreset(int))); +// dockWidget->widget()->layout()->addWidget(presets); + + tabs = new QTabWidget(this); + tabs->addTab(createFilesTab(), "Files"); + generateTabId = tabs->addTab(createGenerateTab(), "Generate"); + tabs->addTab(createEditTab(), "Edit"); + tabs->addTab(createExportTab(), "Export"); + connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); + tabChanged(tabs->currentIndex()); + + dockWidget->widget()->layout()->addWidget(tabs); + + VolumeFader *vol = new VolumeFader(); + connect(vol, SIGNAL(volumeChangedDb(double)), + &player, SLOT(setGainDB(double))); + connect(&player, SIGNAL(peakUpdate(double)), + vol, SLOT(updatePeakPower(double))); +// connect(&player, SIGNAL(peakUpdateDB(double)), +// vol, SLOT(updatePeakDb(double))); + + vol->setVolumeDb(0); + dockWidget->widget()->layout()->addWidget(vol); + + addDockWidget(Qt::LeftDockWidgetArea, dockWidget); + + canvaswidget->yscale->setValue(0.9); + canvaswidget->yoffset->setValue(MAXVAL/2); + canvaswidget->xscale->setValue(0); + canvaswidget->xoffset->setValue(0); + + loadSettings(); + +/* + QSettings settings("presets.ini", QSettings::IniFormat); + QStringList list = settings.childGroups(); + for(int i = 0; i != list.size(); i++) { + QString presetname = list.at(i); + Preset p; + settings.beginGroup(presetname); + p.prefix = settings.value("prefix", "unknown").toString(); + p.attacklength = settings.value("attacklength", 0).toInt(); + p.falloff = settings.value("falloff", 0).toInt(); + p.fadelength = settings.value("fadelength", 0).toInt(); + settings.endGroup(); + QVariant v; + v.setValue(p); + presets->addItem(presetname, v); + } +*/ + + statusBar()->showMessage("Ready"); +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::tabChanged(int tabid) +{ + tool_selections->setShowPreview(tabid == generateTabId); + sorter->setShowPreview(tabid == generateTabId); + tool_selections->autoCreateSelectionsPreview(); + threshold->setActive(tabid == generateTabId); +} + +QWidget *MainWindow::createFilesTab() +{ + QWidget *w = new QWidget(); + QVBoxLayout *l = new QVBoxLayout(); + w->setLayout(l); + + l->addWidget(new QLabel("Files: (double-click to set as master)")); + QPushButton *loadbtn = new QPushButton(); + loadbtn->setText("Add files..."); + l->addWidget(loadbtn); + + filelist = new FileList(); + 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))); + connect(filelist, SIGNAL(fileRemoved(QString, QString)), + extractor, SLOT(removeFile(QString, QString))); + connect(filelist, SIGNAL(nameChanged(QString, QString)), + extractor, SLOT(changeName(QString, QString))); + l->addWidget(filelist); + + return w; +} + +QWidget *MainWindow::createEditTab() +{ + SelectionEditor *se = new SelectionEditor(selections); + + connect(&selections, SIGNAL(added(sel_id_t)), se, SLOT(added(sel_id_t))); + connect(&selections, SIGNAL(updated(sel_id_t)), se, SLOT(updated(sel_id_t))); + connect(&selections, SIGNAL(removed(sel_id_t)), se, SLOT(removed(sel_id_t))); + connect(&selections, SIGNAL(activeChanged(sel_id_t)), + se, SLOT(activeChanged(sel_id_t))); + + return se; +} + +QSlider *createAttribute(QWidget *parent, QString name, + int range_from, int range_to) +{ + QSlider *slider; + + QGridLayout *l = new QGridLayout(); + + l->addWidget(new QLabel(name), 0, 0, 1, 2); + + QSpinBox *spin = new QSpinBox(); + spin->setRange(range_from, range_to); + l->addWidget(spin, 1, 0, 1, 1); + + slider = new QSlider(Qt::Horizontal); + slider->setRange(range_from, range_to); + l->addWidget(slider, 1, 1, 1,1); + + QObject::connect(spin, SIGNAL(valueChanged(int)), + slider, SLOT(setValue(int))); + QObject::connect(slider, SIGNAL(valueChanged(int)), + spin, SLOT(setValue(int))); + + ((QBoxLayout *)parent->layout())->addLayout(l); + + return slider; +} + +QWidget *MainWindow::createGenerateTab() +{ + QWidget *w = new QWidget(); + QVBoxLayout *l = new QVBoxLayout(); + w->setLayout(l); + + QHBoxLayout *btns = new QHBoxLayout(); + + QPushButton *autosel = new QPushButton(); + autosel->setText("Generate"); + connect(autosel, SIGNAL(clicked()), + tool_selections, SLOT(clearSelections())); + connect(autosel, SIGNAL(clicked()), + tool_selections, SLOT(autoCreateSelections())); + + connect(threshold, SIGNAL(thresholdChanged(double)), + tool_selections, SLOT(autoCreateSelectionsPreview())); + connect(threshold, SIGNAL(thresholdChanging(double)), + tool_selections, SLOT(autoCreateSelectionsPreview())); + + QPushButton *clearsel = new QPushButton(); + clearsel->setText("Clear"); + connect(clearsel, SIGNAL(clicked()), + tool_selections, SLOT(clearSelections())); + + btns->addWidget(autosel); + btns->addWidget(clearsel); + + l->addLayout(btns); + + slider_attacklength = createAttribute(w, "Attack length:", 10, 1000); + connect(slider_attacklength, SIGNAL(valueChanged(int)), + sorter, SLOT(setAttackLength(int))); + connect(slider_attacklength, SIGNAL(valueChanged(int)), + tool_selections, SLOT(autoCreateSelectionsPreview())); + slider_attacklength->setValue(300); + + slider_hold = createAttribute(w, "Minimum size (samples):", 0, 200000); + connect(slider_hold, SIGNAL(valueChanged(int)), + tool_selections, SLOT(holdChanged(int))); + connect(slider_hold, SIGNAL(valueChanged(int)), + tool_selections, SLOT(autoCreateSelectionsPreview())); + slider_hold->setValue(100); + + slider_falloff = createAttribute(w, "Falloff:", 10, 5000); + connect(slider_falloff, SIGNAL(valueChanged(int)), + tool_selections, SLOT(noiseFloorChanged(int))); + connect(slider_falloff, SIGNAL(valueChanged(int)), + tool_selections, SLOT(autoCreateSelectionsPreview())); + slider_falloff->setValue(300); + + slider_fadelength = createAttribute(w, "Fadelength:", 0, 2000); + connect(slider_fadelength, SIGNAL(valueChanged(int)), + tool_selections, SLOT(fadeoutChanged(int))); + connect(slider_fadelength, SIGNAL(valueChanged(int)), + tool_selections, SLOT(autoCreateSelectionsPreview())); + slider_fadelength->setValue(666); + + l->addStretch(); + + return w; +} + +QWidget *MainWindow::createExportTab() +{ + QWidget *w = new QWidget(); + QVBoxLayout *l = new QVBoxLayout(); + w->setLayout(l); + + l->addWidget(new QLabel("Prefix:")); + prefix = new QLineEdit(); + connect(prefix, SIGNAL(textChanged(const QString &)), + extractor, SLOT(setOutputPrefix(const QString &))); + l->addWidget(prefix); + + l->addWidget(new QLabel("Export path:")); + QHBoxLayout *lo_exportp = new QHBoxLayout(); + lineed_exportp = new QLineEdit(); + connect(lineed_exportp, SIGNAL(textChanged(const QString &)), + extractor, SLOT(setExportPath(const QString &))); + lo_exportp->addWidget(lineed_exportp); + QPushButton *btn_browse = new QPushButton("..."); + connect(btn_browse, SIGNAL(clicked()), this, SLOT(browse())); + lo_exportp->addWidget(btn_browse); + + l->addLayout(lo_exportp); + + QPushButton *exportsel = new QPushButton(); + exportsel->setText("Export"); + connect(exportsel, SIGNAL(clicked()), this, SLOT(doExport())); + l->addWidget(exportsel); + + QProgressBar *bar = new QProgressBar(); + connect(extractor, SIGNAL(progressUpdate(int)), bar, SLOT(setValue(int))); + connect(extractor, SIGNAL(setMaximumProgress(int)), + bar, SLOT(setMaximum(int))); + l->addWidget(bar); + + l->addStretch(); + + return w; +} + +void MainWindow::playSamples() +{ + Selections *sels = &selections; + if(tabs->currentIndex() == generateTabId) sels = &selections_preview; + + QVector ids = sels->ids(); + for(int v1 = 0; v1 < ids.size(); v1++) { + for(int v2 = 0; v2 < ids.size(); v2++) { + + Selection sel1 = sels->get(ids[v1]); + Selection sel2 = sels->get(ids[v2]); + + if(sel1.energy < sel2.energy) { + sel_id_t vtmp = ids[v1]; + ids[v1] = ids[v2]; + ids[v2] = vtmp; + } + } + } + + QVector::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = sels->get(*i); + + unsigned int length = sb_playsamples->value() * 44100 / 1000; + + unsigned int sample_length = sel.to - sel.from; + + unsigned int to = sel.to; + + if(sample_length > length) to = sel.from + length; + + sels->setActive(*i); + + connect(&player, SIGNAL(positionUpdate(size_t)), + listen, SLOT(update(size_t))); + + player.playSelection(sel, to - sel.from); + QTime t; + t.start(); + while(t.elapsed() < sb_playsamples->value()) { + qApp->processEvents(); + q_usleep(25 * 1000); + } + player.stop(); + + disconnect(&player, SIGNAL(positionUpdate(size_t)), + listen, SLOT(update(size_t))); + i++; + } +} + +void MainWindow::closeEvent(QCloseEvent *) +{ + saveSettings(); + QApplication::quit(); +} + +void MainWindow::loadSettings() +{ + QSettings settings; + + settings.beginGroup("MainWindow"); + lineed_exportp->setText(settings.value("exportpath", "").toString()); + resize(settings.value("size", QSize(700, 800)).toSize()); + move(settings.value("pos", QPoint(0, 0)).toPoint()); + settings.endGroup(); +} + +void MainWindow::saveSettings() +{ + QSettings settings; + + settings.beginGroup("MainWindow"); + settings.setValue("exportpath", lineed_exportp->text()); + settings.setValue("size", size()); + settings.setValue("pos", pos()); + settings.endGroup(); +} +/* +void MainWindow::setXScale(float val) +{ + canvaswidget->canvas->setXScale(val); +} + +void MainWindow::setYScale(float val) +{ + canvaswidget->canvas->setYScale(val); +} + +void MainWindow::setXOffset(int of) +{ + // range 0.0 - 1.0 + float val = (float)of/(float)MAXVAL; + canvaswidget->canvas->setXOffset(val); +} + +void MainWindow::setYOffset(int of) +{ + // range 0.0 - 1.0 + float val = (float)(of * -1 + MAXVAL)/(float)MAXVAL; + canvaswidget->canvas->setYOffset(val); +} +*/ +void MainWindow::doExport() +{ + extractor->exportSelections(); +} + +void MainWindow::loadFile(QString filename) +{ + setCursor(Qt::WaitCursor); + statusBar()->showMessage("Loading..."); + qApp->processEvents(); + + sorter->setWavData(NULL, 0); + player.setPcmData(NULL, 0); + + canvaswidget->canvas->load(filename); + + sorter->setWavData(canvaswidget->canvas->data, canvaswidget->canvas->size); + player.setPcmData(canvaswidget->canvas->data, canvaswidget->canvas->size); + + statusBar()->showMessage("Ready"); + setCursor(Qt::ArrowCursor); +} + +void MainWindow::setPreset(int index) +{ + /* + QVariant v = presets->itemData(index); + Preset p = v.value(); + slider_attacklength->setValue(p.attacklength); + slider_falloff->setValue(p.falloff); + slider_fadelength->setValue(p.fadelength); + prefix->setText(p.prefix); + */ +} + +void MainWindow::browse() { + QString path = QFileDialog::getExistingDirectory(this, "Select export path", + lineed_exportp->text()); + lineed_exportp->setText(path); +} diff --git a/src/mainwindow.h b/src/mainwindow.h new file mode 100644 index 0000000..69a4c5e --- /dev/null +++ b/src/mainwindow.h @@ -0,0 +1,124 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * mainwindow.h + * + * Tue Nov 10 10:21:03 CET 2009 + * Copyright 2009 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_MAINWINDOW_H__ +#define __DRUMGIZMO_MAINWINDOW_H__ + +#include +#include +#include +#include +#include +#include +#include + +#include "canvas.h" +#include "audioextractor.h" +#include "samplesorter.h" +#include "filelist.h" +#include "canvastoolselections.h" +#include "canvastoolthreshold.h" +#include "canvastoollisten.h" +#include "selection.h" +#include "player.h" +#include "zoomslider.h" +#include "canvaswidget.h" + +class Preset { +public: + QString prefix; + int attacklength; + int falloff; + int fadelength; +}; +Q_DECLARE_METATYPE(Preset) + +class MainWindow : public QMainWindow { +Q_OBJECT +public: + MainWindow(); + ~MainWindow(); + +public slots: + /* + void setXScale(float); + void setYScale(float); + void setXOffset(int); + void setYOffset(int); + */ + void doExport(); + void loadFile(QString filename); + void playSamples(); + void setPreset(int); + void browse(); + void tabChanged(int tabid); + +protected: + void closeEvent(QCloseEvent*); + +private: + void loadSettings(); + void saveSettings(); + + QWidget *createFilesTab(); + QWidget *createEditTab(); + QWidget *createGenerateTab(); + QWidget *createExportTab(); + + int generateTabId; + + SampleSorter *sorter; + CanvasToolSelections *tool_selections; + CanvasToolThreshold *threshold; + CanvasToolListen *listen; + AudioExtractor *extractor; + FileList *filelist; + + //Canvas *canvas; + //QScrollBar *yoffset; + //ZoomSlider *yscale; + //ZoomSlider *xscale; + //QScrollBar *xoffset; + CanvasWidget *canvaswidget; + + QScrollBar *sb_playsamples; + QComboBox *presets; + QSlider *slider_attacklength; + QSlider *slider_hold; + QSlider *slider_falloff; + QSlider *slider_fadelength; + QLineEdit *prefix; + QLineEdit *lineed_exportp; + + QTabWidget *tabs; + + // Session state information: + Selections selections; + Selections selections_preview; + Player player; +}; + +#endif/*__DRUMGIZMO_MAINWINDOW_H__*/ diff --git a/src/mipmap.cc b/src/mipmap.cc new file mode 100644 index 0000000..09b15b6 --- /dev/null +++ b/src/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/src/mipmap.h b/src/mipmap.h new file mode 100644 index 0000000..550d6ae --- /dev/null +++ b/src/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/src/player.cc b/src/player.cc new file mode 100644 index 0000000..3a2bfd2 --- /dev/null +++ b/src/player.cc @@ -0,0 +1,190 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * player.cc + * + * Tue Apr 15 10:34:18 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 "player.h" + +#include + +#define BUFSZ 512 + +Player::Player() +{ + peak = 0; + pos = 0; + gain_scalar = 1.0; + pcm_data = NULL; + pcm_size = 0; + end = 0; + new_selection = false; + + connect(&report_timer, SIGNAL(timeout()), this, SLOT(reportTimeout())); + report_timer.start(50); // Update 25 times per second + + start(); +} + +Player::~Player() +{ + running = false; // Signal player thread to stop + wait(); // Wait for player thread to stop. +} + +#define _MIN(a, b) (a (sel.to - sel.fadeout)) { + // Apply linear fade-out + double fp = (double)(((int)sel.to - (int)sel.fadeout) - (int)p); + fade = 1 + (fp / (double)sel.fadeout); + } + + sample = pcm_data[p] * fade * gain_scalar; + } + if(fabs(sample) > peak) { + peak = fabs(sample); + } + s[i] = _MIN(sample * SHRT_MAX, SHRT_MAX); + } + + ao_play(dev, (char*)s, BUFSZ * sizeof(short)); + + pos += BUFSZ; + } + + ao_close(dev); + ao_shutdown(); +} + +bool Player::playSelectionDone() +{ + return pos >= sel_end || pos >= selection.to; +} + +void Player::playSelection(Selection s, int len) +{ + { // Enqueue new Selection for player consumation + QMutexLocker lock(&mutex); + + selection = s; + + if(len > 0) sel_end = len; + else sel_end = selection.to - selection.from; + + sel_end += selection.from; + + new_selection = true; + } + + // Wait until player actually consumed the new Selection. + while(new_selection) { + msleep(1); + } +} + +void Player::setGainScalar(double g) +{ + gain_scalar = g; +} + +void Player::setGainDB(double gain_db) +{ + setGainScalar(pow(10, gain_db/ 20.0)); +} + +void Player::reportTimeout() +{ + emit peakUpdate(peak); + emit peakUpdateDB(20 * log10(peak)); + peak = 0.0; + + emit positionUpdate(pos); + peak = 0.0; +} + +void Player::setPcmData(float *data, size_t size) +{ + pcm_data = data; + pcm_size = size; +} + +void Player::setPosition(size_t position) +{ + Selection s; + s.from = position; + s.to = pcm_size; + s.fadein = 0; + s.fadeout = 0; + playSelection(s); +} + +void Player::stop() +{ + Selection s; + s.from = 0; + s.to = 0; + s.fadein = 0; + s.fadeout = 0; + playSelection(s, pos); +} diff --git a/src/player.h b/src/player.h new file mode 100644 index 0000000..60b2ccb --- /dev/null +++ b/src/player.h @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * player.h + * + * Tue Apr 15 10:34:18 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. + */ +#ifndef __DRUMGIZMO_PLAYER_H__ +#define __DRUMGIZMO_PLAYER_H__ + +#include +#include +#include + +#include + +#include "selection.h" + +class Player : public QThread { +Q_OBJECT +public: + Player(); + ~Player(); + + void run(); + + // TODO: Make these private. + // These two need to be public in order for the ugly hack in + // CanvasToolListen::playRange to work... + // volatile bool playing; + volatile size_t pos; + volatile size_t end; + +public slots: + /** + * Assign PCM data to the player. + */ + void setPcmData(float *data, size_t num_samples); + + /** + * Set gain scalar. + * This value is multiplied with each sample before it is played. + */ + void setGainScalar(double gain_scalar); + + /** + * Set gain is dB. + * Convenience method for setGainScalar. It simple recalculates the dB value + * to a scalar and sets the gain scalar accordingly. + */ + void setGainDB(double gain_db); + + /** + * Set player position as sample offset. + */ + void setPosition(size_t position); + + /** + * Play range based on selection including fade-in/out. + * @param length Stop playing after length samples. -1 means play all. + */ + void playSelection(Selection selection, int length = -1); + + /** + * Return true if last selection is done playing. + */ + bool playSelectionDone(); + + /** + * Stop playing + */ + void stop(); + +signals: + /** + * The absolute maximum of samples seen since last update. + */ + void peakUpdate(double peak); + + /** + * The absolute maximum of samples seen since last update in dB. + */ + void peakUpdateDB(double peak_db); + + /** + * The sample position of the player. + */ + void positionUpdate(size_t position); + +private slots: + void reportTimeout(); + +private: + ao_device *dev; + + float *pcm_data; + size_t pcm_size; + + QTimer report_timer; + + double gain_scalar; + double peak; + + bool running; + + QMutex mutex; + volatile bool new_selection; + size_t sel_end; + Selection selection; +}; + +#endif/*__DRUMGIZMO_PLAYER_H__*/ diff --git a/src/samplesorter.cc b/src/samplesorter.cc new file mode 100644 index 0000000..00139e2 --- /dev/null +++ b/src/samplesorter.cc @@ -0,0 +1,271 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * samplesorter.cc + * + * Mon Nov 30 07:45:58 CET 2009 + * Copyright 2009 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 "samplesorter.h" + +#include +#include + +#include + +#include +#ifndef MAXFLOAT +#define MAXFLOAT (3.40282347e+38F) +#endif + +SampleSorter::SampleSorter(Selections &s, Selections &p) + : selections(s), selections_preview(p) +{ + setMouseTracking(true); + + data = NULL; + size = 0; + attlen = 666; // Magical constants needs biblical proportions... + + sel_moving = SEL_NONE; +} + +void SampleSorter::setShowPreview(bool s) +{ + show_preview = s; + update(); +} + +void SampleSorter::setWavData(const float *data, size_t size) +{ + this->data = data; + this->size = size; + relayout(); +} + +int SampleSorter::attackLength() +{ + return attlen; +} + +void SampleSorter::setAttackLength(int len) +{ + attlen = len; + relayout(); +} + +void SampleSorter::addSelection(sel_id_t id) +{ + 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]; + } + + s.energy = energy; + selections.update(id, s); + + relayout(); +} + +void SampleSorter::addSelectionPreview(sel_id_t id) +{ + Selection s = selections_preview.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]; + } + + s.energy = energy; + selections_preview.update(id, s); + + relayout(); +} + +void SampleSorter::relayout() +{ + min = MAXFLOAT; + max = 0.0; + + { + QVector ids = selections.ids(); + QVector::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections.get(*i); + + if(sel.energy < min) min = sel.energy; + if(sel.energy > max) max = sel.energy; + + i++; + } + } + + if(show_preview) { + QVector ids = selections_preview.ids(); + QVector::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections_preview.get(*i); + + if(sel.energy < min) min = sel.energy; + if(sel.energy > max) max = sel.energy; + + i++; + } + } + + update(); +} + +#define MAP(p) (height()-(int)(p*((float)height()/(float)width()))) + +#define unmapX(x) ((double)x/(double)(width()-1)) +#define unmapY(x) x +#define mapX(x) (((double)x)*(width()-1)) +#define mapY(x) x + +#define C_RADIUS 2 +static void drawCircle(QPainter &p, int x, int y) +{ + p.drawEllipse(x - C_RADIUS, y - C_RADIUS, 2 * C_RADIUS, 2 * C_RADIUS); +} + +void SampleSorter::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + + QColor colBg = QColor(180, 200, 180, 160); + QColor colFg = QColor(160, 180, 160, 160); + QColor colPt = QColor(255, 100, 100, 160); + QColor colPtPreview = QColor(0, 0, 255, 160); + QColor colPtSel = QColor(255, 255, 100, 160); + + painter.setPen(colBg); + painter.setBrush(colBg); + painter.drawRect(event->rect()); + + painter.setPen(colFg); + painter.drawLine(0,height(),width(),0); + + { + QVector ids = selections.ids(); + QVector::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections.get(*i); + if(*i == selections.active()) painter.setPen(colPtSel); + else painter.setPen(colPt); + float x = sel.energy / max; + x = sqrt(x); + x *= (float)width(); + drawCircle(painter, x, MAP(x)); + i++; + } + } + + if(show_preview) { + QVector ids = selections_preview.ids(); + QVector::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections_preview.get(*i); + painter.setPen(colPtPreview); + float x = sel.energy / max; + x = sqrt(x); + x *= (float)width(); + drawCircle(painter, x, MAP(x)); + i++; + } + } + + +} + +sel_id_t SampleSorter::getSelectionByCoordinate(int px, int py) +{ + // Hit radius is slithly larger than the circles themselves. + int hit_r = C_RADIUS + 1; + + QVector ids = selections.ids(); + QVector::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections.get(*i); + float x = (sel.energy/max); + x = sqrt(x); + x *= (float)width(); + if(px < (x + hit_r) && px > (x - hit_r) && + py < (MAP(x) + hit_r) && py > (MAP(x) - hit_r)) { + return *i; + } + i++; + } + + return SEL_NONE; +} + +void SampleSorter::mouseMoveEvent(QMouseEvent *event) +{ + 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; + } else { + sel_id_t psel = getSelectionByCoordinate(event->x(), event->y()); + if(psel != SEL_NONE) { + setCursor(Qt::UpArrowCursor); + } else { + setCursor(Qt::ArrowCursor); + } + } +} + +void SampleSorter::mousePressEvent(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) { + sel_id_t psel = getSelectionByCoordinate(event->x(), event->y()); + sel_moving = psel; + selections.setActive(psel); + if(psel != SEL_NONE) { + setCursor(Qt::UpArrowCursor); + } + } +} + +void SampleSorter::mouseReleaseEvent(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) { + sel_moving = SEL_NONE; + setCursor(Qt::ArrowCursor); + } +} diff --git a/src/samplesorter.h b/src/samplesorter.h new file mode 100644 index 0000000..ada7fd8 --- /dev/null +++ b/src/samplesorter.h @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * samplesorter.h + * + * Mon Nov 30 07:45:58 CET 2009 + * Copyright 2009 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_SAMPLESORTER_H__ +#define __DRUMGIZMO_SAMPLESORTER_H__ + +#include +#include +#include "selection.h" + +class SampleSorter : public QWidget { +Q_OBJECT +public: + SampleSorter(Selections &selections, Selections &selections_preview); + +public slots: + void setWavData(const float *data, size_t size); + void setAttackLength(int len); + int attackLength(); + + void addSelection(sel_id_t id); + void addSelectionPreview(sel_id_t id); + + void relayout(); + + void setShowPreview(bool show_preview); + +protected: + void paintEvent(QPaintEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +private: + sel_id_t getSelectionByCoordinate(int x, int y); + + Selections &selections; + Selections &selections_preview; + + bool show_preview; + + float min; + float max; + int attlen; + + // Wav data + const float *data; + size_t size; + + Selection sel; + + sel_id_t sel_moving; +}; + +#endif/*__DRUMGIZMO_SAMPLESORTER_H__*/ diff --git a/src/selection.cc b/src/selection.cc new file mode 100644 index 0000000..c0300a4 --- /dev/null +++ b/src/selection.cc @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * selection.cc + * + * Mon Apr 14 10:13:21 CEST 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "selection.h" + +Selections::Selections() + : QObject(NULL) +{ + nextid = 0; + act = SEL_NONE; +} + +sel_id_t Selections::add(Selection selection) +{ + sel_id_t id = nextid++; + sels[id] = selection; + added(id); + return id; +} + +Selection Selections::get(sel_id_t id) +{ + if(sels.find(id) == sels.end()) { + Selection s(0,0,0,0); + return s; + } + return sels[id]; +} + +QVector Selections::ids() +{ + QVector v; + + QMap::iterator i = sels.begin(); + while(i != sels.end()) { + v.push_back(i.key()); + i++; + } + + return v; +} + +void Selections::update(sel_id_t id, Selection selection) +{ + if(sels.find(id) != sels.end()) { + sels[id] = selection; + emit updated(id); + } +} + +void Selections::remove(sel_id_t id) +{ + if(sels.find(id) != sels.end()) { + sels.erase(sels.find(id)); + if(id == act) setActive(SEL_NONE); + emit removed(id); + } +} + +void Selections::clear() +{ + QVector _ids = ids(); + QVector::iterator i = _ids.begin(); + while(i != _ids.end()) { + remove(*i); + i++; + } +} + +void Selections::setActive(sel_id_t id) +{ + if(sels.find(id) != sels.end()) { + act = id; + } else { + act = SEL_NONE; + } + emit activeChanged(act); +} + +sel_id_t Selections::active() +{ + return act; +} diff --git a/src/selection.h b/src/selection.h new file mode 100644 index 0000000..c6c7ecc --- /dev/null +++ b/src/selection.h @@ -0,0 +1,135 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * selection.h + * + * Sat Nov 21 13:20:46 CET 2009 + * Copyright 2009 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_SELECTION_H__ +#define __DRUMGIZMO_SELECTION_H__ + +#include + +#include +#include + +class Selection { +public: + Selection(int from = 0, int to = 0, int fadein = 0, int fadeout = 0) { + this->from = from; + this->to = to; + this->fadein = fadein; + this->fadeout = fadeout; + } + size_t from; + size_t to; + size_t fadein; + size_t fadeout; + + double energy; + + QString name; +}; + +typedef int sel_id_t; +#define SEL_NONE -1 + +class Selections : public QObject { +Q_OBJECT +public: + Selections(); + + /** + * Add a new selection object. The new id is returned. + * Adding a new selections will emit an added signal with the new id. + */ + sel_id_t add(Selection selection); + + /** + * Get a stack copy of a specific selection object, by id. + * NOTE: If id does not exist an empty selection (from = to = 0) is + * returned. + */ + Selection get(sel_id_t id); + + /** + * Return vector (unsorted) of all ids in the object. + */ + QVector ids(); + + /** + * Set active selection (to be rendered yellow) + */ + void setActive(sel_id_t id); + + /** + * Get active selection id. + */ + sel_id_t active(); + +public slots: + /** + * Update a selection by id. + * Updating a selection will emit a updated signal. + */ + void update(sel_id_t id, Selection selection); + + /** + * Delete a selection by id. + * Deleting a selection will emit a deleted signal. + */ + void remove(sel_id_t id); + + /** + * Delete all selections + */ + void clear(); + +signals: + /** + * This signal is emitted when a new selection has been added. + */ + void added(sel_id_t id); + + /** + * This signal is emitted when an existing selection has been updated. + */ + void updated(sel_id_t id); + + /** + * This signal is emitted when a selection has been removed. + */ + void removed(sel_id_t id); + + /** + * The active selection changed. + */ + void activeChanged(sel_id_t id); + +private: + QMap sels; + sel_id_t nextid; + sel_id_t act; +}; + + +#endif/*__DRUMGIZMO_SELECTION_H__*/ diff --git a/src/selectioneditor.cc b/src/selectioneditor.cc new file mode 100644 index 0000000..e8db104 --- /dev/null +++ b/src/selectioneditor.cc @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * selectioneditor.cc + * + * Thu Apr 17 17:25:18 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 "selectioneditor.h" + +#include +#include +#include + +QLineEdit *createWidget(QString name, QWidget *parent) +{ + QHBoxLayout *l = new QHBoxLayout(); + + l->addWidget(new QLabel(name)); + + QLineEdit *edt = new QLineEdit(); + QObject::connect(edt, SIGNAL(editingFinished()), + parent, SLOT(updateSelection())); + + l->addWidget(edt); + + ((QHBoxLayout *)parent->layout())->addLayout(l); + + return edt; +} + +SelectionEditor::SelectionEditor(Selections &s) + : selections(s) +{ + cur = SEL_NONE; + + setLayout(new QVBoxLayout()); + + from = createWidget("From:", this); + to = createWidget("To:", this); + fadein = createWidget("FadeIn:", this); + fadeout = createWidget("FadeOut:", this); + energy = createWidget("Energy:", this); + name = createWidget("Name:", this); +} + +void SelectionEditor::updateSelection() +{ + Selection sel; + + sel.from = from->text().toInt(); + sel.to = to->text().toInt(); + sel.fadein = fadein->text().toInt(); + sel.fadeout = fadeout->text().toInt(); + sel.energy = energy->text().toDouble(); + sel.name = name->text(); + + selections.update(cur, sel); +} + +void SelectionEditor::update() +{ + Selection sel = selections.get(cur); + from->setText(QString::number(sel.from)); + to->setText(QString::number(sel.to)); + fadein->setText(QString::number(sel.fadein)); + fadeout->setText(QString::number(sel.fadeout)); + energy->setText(QString::number(sel.energy)); + name->setText(sel.name); +} + +void SelectionEditor::added(sel_id_t id) +{ + // Nothing to do here... +} + +void SelectionEditor::updated(sel_id_t id) +{ + if(cur == id) { + update(); + } +} + +void SelectionEditor::removed(sel_id_t id) +{ + if(cur == id) { + cur = SEL_NONE; + update(); + } +} + +void SelectionEditor::activeChanged(sel_id_t id) +{ + cur = id; + update(); +} diff --git a/src/selectioneditor.h b/src/selectioneditor.h new file mode 100644 index 0000000..55d8e33 --- /dev/null +++ b/src/selectioneditor.h @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * selectioneditor.h + * + * Thu Apr 17 17:25:17 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. + */ +#ifndef __DRUMGIZMO_SELECTIONEDITOR_H__ +#define __DRUMGIZMO_SELECTIONEDITOR_H__ + +#include + +#include +#include "selection.h" + +class SelectionEditor : public QWidget { +Q_OBJECT +public: + SelectionEditor(Selections &selections); + +public slots: + void added(sel_id_t id); + void updated(sel_id_t id); + void removed(sel_id_t id); + void activeChanged(sel_id_t id); + +private slots: + void update(); + void updateSelection(); + +private: + Selections &selections; + + sel_id_t cur; + + QLineEdit *from; + QLineEdit *to; + QLineEdit *fadein; + QLineEdit *fadeout; + QLineEdit *energy; + QLineEdit *name; +}; + +#endif/*__DRUMGIZMO_SELECTIONEDITOR_H__*/ diff --git a/src/sleep.h b/src/sleep.h new file mode 100644 index 0000000..107b7a8 --- /dev/null +++ b/src/sleep.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * sleep.h + * + * Sun Apr 20 18:54:58 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. + */ +#ifndef __DRUMGIZMO_SLEEP_H__ +#define __DRUMGIZMO_SLEEP_H__ + +#include + +class __Sleeper : public QThread { +public: + void msleep(unsigned long msecs) { QThread::msleep(msecs); } + void sleep(unsigned long secs) { QThread::sleep(secs); } + void usleep(unsigned long usecs) { QThread::usleep(usecs); } +}; + +inline void q_msleep(unsigned long msecs) +{ + __Sleeper s; + s.msleep(msecs); +} + +inline void q_sleep(unsigned long secs) +{ + __Sleeper s; + s.sleep(secs); +} + +inline void q_usleep(unsigned long usecs) +{ + __Sleeper s; + s.usleep(usecs); +} + +#endif/*__DRUMGIZMO_SLEEP_H__*/ diff --git a/src/volumefader.cc b/src/volumefader.cc new file mode 100644 index 0000000..08bab80 --- /dev/null +++ b/src/volumefader.cc @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * volumefader.cc + * + * Tue Apr 15 15:46:00 CEST 2014 + * Copyright 2014 Jonas Suhr Christensen + * jsc@umbraculum.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 "volumefader.h" + +#include +#include + +#include + +#define SCALAR 10 +#define P 0.5 + +VolumeFader::VolumeFader() +{ + peak = 0; + volslider = new QSlider(); + volslider->setRange(-60 * SCALAR , 10 * SCALAR); + volslider->setOrientation(Qt::Horizontal); + + volumepeak = new QLabel(); + + volume = new QLabel(); + + connect(volslider, SIGNAL(valueChanged(int)), this, SLOT(handleValueChanged())); + + QVBoxLayout* lo = new QVBoxLayout(); + lo->addWidget(volslider); + + lo->addWidget(volumepeak); + lo->addWidget(volume); + + setLayout(lo); +} + +VolumeFader::~VolumeFader() +{ + +} + +void VolumeFader::updatePeakDb(double db) +{ +// updatePeakPower(pow(10, db/20)); +} + +void VolumeFader::updatePeakPower(double newpeak) +{ + peak = (newpeak * (1.0-P) + peak * P); + volumepeak->setText("Peak " + QString::number(peak, 'f', 5)); + handleValueChanged(); +} + +void VolumeFader::setVolumeDb(double db) +{ + volslider->setValue(db*SCALAR); + handleValueChanged(); +} + +void VolumeFader::setVolumePower(double power) +{ + double db = 20 * log10(power); + setVolumeDb(db); + handleValueChanged(); +} + +void VolumeFader::handleValueChanged() +{ + double db = ((double)volslider->value())/((double)SCALAR); + double power = pow(10, db/20); + emit volumeChangedDb(db); + emit volumeChangedPower(power); + + volume->setText("Gain " + QString::number(volslider->value()/SCALAR) + " dB"); +} diff --git a/src/volumefader.h b/src/volumefader.h new file mode 100644 index 0000000..7209956 --- /dev/null +++ b/src/volumefader.h @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * volumefader.h + * + * Tue Apr 15 15:46:00 CEST 2014 + * Copyright 2014 Jonas Suhr Christensen + * jsc@umbraculum.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_VOLUMEFADER_H__ +#define __DRUMGIZMO_VOLUMEFADER_H__ + +#include +#include +#include + +#include + +class VolumeFader : public QWidget { +Q_OBJECT +public: + VolumeFader(); + ~VolumeFader(); + + void volumeDb(); + void volumePower(); + +public slots: + void updatePeakDb(double vol); + void updatePeakPower(double vol); + void setVolumeDb(double vol); + void setVolumePower(double vol); + +private slots: + void handleValueChanged(); + +signals: + void volumeChangedDb(double vol); + void volumeChangedPower(double vol); + +private: + QSlider *volslider; + QLabel *volumepeak; + QLabel *volume; + double peak; +}; + +#endif/*__DRUMGIZMO_VOLUMEFADER_H__*/ diff --git a/src/zoomslider.cc b/src/zoomslider.cc new file mode 100644 index 0000000..0a2abb1 --- /dev/null +++ b/src/zoomslider.cc @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * zoomslider.cc + * + * Fri May 2 21:23:26 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 45Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "zoomslider.h" + +#include + +ZoomSlider::ZoomSlider(Qt::Orientation orientation) + : QSlider(orientation) +{ + inverted = false; + from = 0; + to = 1; + tick_width = 0.1; + + connect(this, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int))); +} + +void ZoomSlider::paintEvent(QPaintEvent *ev) +{ + /* + QPainter p(this); + p.drawLine(0, 0, width(), height()); + */ + QSlider::paintEvent(ev); +} + +void ZoomSlider::setRange(float from, float to) +{ + this->inverted = false; + this->from = from; + this->to = to; + + int i_from = from / tick_width; + int i_to = to / tick_width; + + if(i_from > i_to) { + this->inverted = true; + int tmp; + tmp = i_from; + i_from = i_to; + i_to = tmp; + } + + QSlider::setRange(i_from, i_to); +} + +float ZoomSlider::fromSlider(int value) +{ + float val = (float)value * tick_width; + + if(inverted) { + val *= -1; + val = val - to + from; + + if(value == QSlider::minimum()) val = from; + if(value == QSlider::maximum()) val = to; + } else { + if(value == QSlider::minimum()) val = from; + if(value == QSlider::maximum()) val = to; + } + + return val; +} + +void ZoomSlider::sliderValueChanged(int value) +{ + emit valueChanged(fromSlider(value)); +} + +void ZoomSlider::setTickWidth(float tick_width) +{ + this->tick_width = tick_width; + setRange(from, to); // Update slider value span. +} + +void ZoomSlider::setValue(float value) +{ + int i_value = value * tick_width; + if(inverted) { + i_value *= -1; + i_value += from; + } + QSlider::setValue(i_value); +} diff --git a/src/zoomslider.h b/src/zoomslider.h new file mode 100644 index 0000000..60b6772 --- /dev/null +++ b/src/zoomslider.h @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * zoomslider.h + * + * Fri May 2 21:23:26 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. + */ +#ifndef __DRUMGIZMO_ZOOMSLIDER_H__ +#define __DRUMGIZMO_ZOOMSLIDER_H__ + +#include +#include + +class ZoomSlider : public QSlider { +Q_OBJECT +public: + ZoomSlider(Qt::Orientation orientation); + + /** + * Range of the slider. 'from' may be lesser than 'to' which will invert the + * slider. + */ + void setRange(float from, float to); + + /** + * Set the distance between emitting of valueChanged signals. + * Example: from:=0, to:=1 and width:=0.5 will emit valueChanged signals on + * 0.0, 0.5 and 1.0 (ie. the slider will have 3 actual values) + * NOTE: If 'width' is greater than the span of [from; to] only the 'from' + * and 'to' values can be selected on the slider. + */ + void setTickWidth(float width); + + void setValue(float value); + +signals: + void valueChanged(float value); + +private slots: + void sliderValueChanged(int value); + +protected: + void paintEvent(QPaintEvent *ev); + +private: + float fromSlider(int value); + + bool inverted; + float from; + float to; + float tick_width; +}; + +#endif/*__DRUMGIZMO_ZOOMSLIDER_H__*/ -- cgit v1.2.3