diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 130 | ||||
-rw-r--r-- | src/audiocache.cc | 28 | ||||
-rw-r--r-- | src/audiocache.h | 55 | ||||
-rw-r--r-- | src/audiodata.h | 28 | ||||
-rw-r--r-- | src/audioextractor.cc | 24 | ||||
-rw-r--r-- | src/audioextractor.h | 4 | ||||
-rw-r--r-- | src/audiofile.h | 28 | ||||
-rw-r--r-- | src/canvastool.cc | 2 | ||||
-rw-r--r-- | src/canvastool.h | 2 | ||||
-rw-r--r-- | src/canvastoollisten.cc | 3 | ||||
-rw-r--r-- | src/canvastoolposition.cc | 161 | ||||
-rw-r--r-- | src/canvastoolposition.h | 72 | ||||
-rw-r--r-- | src/canvastoolranges.cc (renamed from src/canvastoolselections.cc) | 222 | ||||
-rw-r--r-- | src/canvastoolranges.h (renamed from src/canvastoolselections.h) | 51 | ||||
-rw-r--r-- | src/canvastoolthreshold.cc | 34 | ||||
-rw-r--r-- | src/canvastoolthreshold.h | 13 | ||||
-rw-r--r-- | src/detector.cc | 28 | ||||
-rw-r--r-- | src/detector.h | 44 | ||||
-rw-r--r-- | src/filelist.cc | 652 | ||||
-rw-r--r-- | src/filelist.h | 58 | ||||
-rw-r--r-- | src/instrumentwidget.cc | 275 | ||||
-rw-r--r-- | src/instrumentwidget.h | 22 | ||||
-rw-r--r-- | src/player.cc | 40 | ||||
-rw-r--r-- | src/player.h | 14 | ||||
-rw-r--r-- | src/project.cc | 56 | ||||
-rw-r--r-- | src/project.h | 36 | ||||
-rw-r--r-- | src/projectrenderer.cc | 6 | ||||
-rw-r--r-- | src/projectserialiser.cc | 36 | ||||
-rw-r--r-- | src/range.cc (renamed from src/selection.cc) | 34 | ||||
-rw-r--r-- | src/range.h (renamed from src/selection.h) | 78 | ||||
-rw-r--r-- | src/rangeeditor.cc (renamed from src/selectioneditor.cc) | 33 | ||||
-rw-r--r-- | src/rangeeditor.h (renamed from src/selectioneditor.h) | 13 | ||||
-rw-r--r-- | src/samplesorter.cc | 205 | ||||
-rw-r--r-- | src/samplesorter.h | 24 | ||||
-rw-r--r-- | src/ts/dgedit_da.ts | 152 | ||||
-rw-r--r-- | src/ts/dgedit_fr.ts | 153 |
36 files changed, 1953 insertions, 863 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index a38b804..596767e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,74 +10,76 @@ dgedit_CXXFLAGS = -g $(SNDFILE_CXXFLAGS) $(QT_CFLAGS) $(AO_CFLAGS) \ AM_CXXFLAGS = $(QT_CFLAGS) dgedit_TRANSLATIONS = \ - ts/dgedit_da.ts \ - ts/dgedit_fr.ts + $(top_srcdir)/src/ts/dgedit_da.ts \ + $(top_srcdir)/src/ts/dgedit_fr.ts dgedit_SOURCES = \ - dgedit.cc \ - aboutdialog.cc \ - audioextractor.cc \ - canvas.cc \ - canvastool.cc \ - canvastoollisten.cc \ - canvastoolselections.cc \ - canvastoolthreshold.cc \ - canvaswidget.cc \ - channeldialog.cc \ - channelswidget.cc \ - filelist.cc \ - imageeditor.cc \ - instrumentdialog.cc \ - instrumentwidget.cc \ - itemeditor.cc \ - localehandler.cc \ - mainwindow.cc \ - mipmap.cc \ - player.cc \ - project.cc \ - projectdialog.cc \ - projectrenderer.cc \ - projectserialiser.cc \ - renderdialog.cc \ - samplesorter.cc \ - selection.cc \ - selectioneditor.cc \ - settings.cc \ - volumefader.cc \ - zoomslider.cc + $(top_srcdir)/src/dgedit.cc \ + $(top_srcdir)/src/aboutdialog.cc \ + $(top_srcdir)/src/audioextractor.cc \ + $(top_srcdir)/src/canvas.cc \ + $(top_srcdir)/src/canvastool.cc \ + $(top_srcdir)/src/canvastoollisten.cc \ + $(top_srcdir)/src/canvastoolposition.cc \ + $(top_srcdir)/src/canvastoolranges.cc \ + $(top_srcdir)/src/canvastoolthreshold.cc \ + $(top_srcdir)/src/canvaswidget.cc \ + $(top_srcdir)/src/channeldialog.cc \ + $(top_srcdir)/src/channelswidget.cc \ + $(top_srcdir)/src/filelist.cc \ + $(top_srcdir)/src/imageeditor.cc \ + $(top_srcdir)/src/instrumentdialog.cc \ + $(top_srcdir)/src/instrumentwidget.cc \ + $(top_srcdir)/src/itemeditor.cc \ + $(top_srcdir)/src/localehandler.cc \ + $(top_srcdir)/src/mainwindow.cc \ + $(top_srcdir)/src/mipmap.cc \ + $(top_srcdir)/src/player.cc \ + $(top_srcdir)/src/project.cc \ + $(top_srcdir)/src/projectdialog.cc \ + $(top_srcdir)/src/projectrenderer.cc \ + $(top_srcdir)/src/projectserialiser.cc \ + $(top_srcdir)/src/renderdialog.cc \ + $(top_srcdir)/src/samplesorter.cc \ + $(top_srcdir)/src/range.cc \ + $(top_srcdir)/src/rangeeditor.cc \ + $(top_srcdir)/src/settings.cc \ + $(top_srcdir)/src/volumefader.cc \ + $(top_srcdir)/src/zoomslider.cc HDRS = \ - aboutdialog.h \ - audioextractor.h \ - canvas.h \ - canvastool.h \ - canvastoollisten.h \ - canvastoolselections.h \ - canvastoolthreshold.h \ - canvaswidget.h \ - channeldialog.h \ - channelswidget.h \ - filelist.h \ - imageeditor.h \ - instrumentdialog.h \ - instrumentwidget.h \ - itemeditor.h \ - localehandler.h \ - mainwindow.h \ - mipmap.h \ - player.h \ - project.h \ - projectdialog.h \ - projectrenderer.h \ - projectserialiser.h \ - renderdialog.h \ - samplesorter.h \ - selection.h \ - selectioneditor.h \ - sleep.h \ - settings.h \ - volumefader.h \ - zoomslider.h + $(top_srcdir)/src/aboutdialog.h \ + $(top_srcdir)/src/audioextractor.h \ + $(top_srcdir)/src/canvas.h \ + $(top_srcdir)/src/canvastool.h \ + $(top_srcdir)/src/canvastoollisten.h \ + $(top_srcdir)/src/canvastoolposition.h \ + $(top_srcdir)/src/canvastoolranges.h \ + $(top_srcdir)/src/canvastoolthreshold.h \ + $(top_srcdir)/src/canvaswidget.h \ + $(top_srcdir)/src/channeldialog.h \ + $(top_srcdir)/src/channelswidget.h \ + $(top_srcdir)/src/filelist.h \ + $(top_srcdir)/src/imageeditor.h \ + $(top_srcdir)/src/instrumentdialog.h \ + $(top_srcdir)/src/instrumentwidget.h \ + $(top_srcdir)/src/itemeditor.h \ + $(top_srcdir)/src/localehandler.h \ + $(top_srcdir)/src/mainwindow.h \ + $(top_srcdir)/src/mipmap.h \ + $(top_srcdir)/src/player.h \ + $(top_srcdir)/src/project.h \ + $(top_srcdir)/src/projectdialog.h \ + $(top_srcdir)/src/projectrenderer.h \ + $(top_srcdir)/src/projectserialiser.h \ + $(top_srcdir)/src/renderdialog.h \ + $(top_srcdir)/src/samplesorter.h \ + $(top_srcdir)/src/range.h \ + $(top_srcdir)/src/rangeeditor.h \ + $(top_srcdir)/src/sleep.h \ + $(top_srcdir)/src/settings.h \ + $(top_srcdir)/src/volumefader.h \ + $(top_srcdir)/src/zoomslider.h EXTRA_DIST = \ $(dgedit_TRANSLATIONS) \ diff --git a/src/audiocache.cc b/src/audiocache.cc new file mode 100644 index 0000000..74b6498 --- /dev/null +++ b/src/audiocache.cc @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * audiocache.cc + * + * Wed Mar 15 09:06:46 CET 2023 + * Copyright 2023 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 "audiocache.h" + diff --git a/src/audiocache.h b/src/audiocache.h new file mode 100644 index 0000000..fc5fd5b --- /dev/null +++ b/src/audiocache.h @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * audiocache.h + * + * Wed Mar 15 09:06:46 CET 2023 + * Copyright 2023 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. + */ +#pragma once + +class AudioData +{ +public: + AudioData(const AudioFile& audiofile); + + //load(); + //unload(); + + AudioData::ID id; + std::vector<float> data; +}; + +class AudioCache +{ +public: + using ID = int; + + static AudioCache& get() + { + static AudioCache cache; + return cache; + } + + ID add(const AudioFile&); + AudioData& get(ID); + void remove(ID); +}; diff --git a/src/audiodata.h b/src/audiodata.h new file mode 100644 index 0000000..884717b --- /dev/null +++ b/src/audiodata.h @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * audiodata.h + * + * Wed Mar 15 08:58:33 CET 2023 + * Copyright 2023 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. + */ +#pragma once + diff --git a/src/audioextractor.cc b/src/audioextractor.cc index 95fe6b2..681edaf 100644 --- a/src/audioextractor.cc +++ b/src/audioextractor.cc @@ -50,14 +50,14 @@ AudioExtractor::AudioExtractor(Instrument& instrument, QObject *parent) { } -bool AudioExtractor::exportSelections() +bool AudioExtractor::exportRanges() { - auto selections = instrument.getSelections(); + auto ranges = instrument.getRanges(); auto exportpath = instrument.getProject().getExportPath(); auto prefix = instrument.getPrefix(); int samplerate = -1; - emit setMaximumProgress(selections.ids().size() + 1/* for xml writing*/); + emit setMaximumProgress(ranges.ids().size() + 1/* for xml writing*/); int progress = 0; emit progressUpdate(progress++); qApp->processEvents(); @@ -92,15 +92,16 @@ bool AudioExtractor::exportSelections() } idx = 1; - QVector<sel_id_t> sels = selections.ids(); + QVector<sel_id_t> sels = ranges.ids(); - // Sort selections by velocity +/* + // Sort ranges 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]); + Range sel1 = ranges.get(sels[v1]); + Range sel2 = ranges.get(sels[v2]); if(sel1.energy < sel2.energy) { @@ -110,7 +111,7 @@ bool AudioExtractor::exportSelections() } } } - +*/ if(samplerate == -1) { // For some reason we never got a samplerate. Set it to 44k1Hz @@ -121,7 +122,7 @@ bool AudioExtractor::exportSelections() QVector<sel_id_t>::iterator si = sels.begin(); while(si != sels.end()) { - Selection sel = selections.get(*si); + Range sel = ranges.get(*si); size_t offset = sel.from; size_t size = sel.to - sel.from; size_t fadein = sel.fadein; @@ -241,15 +242,16 @@ bool AudioExtractor::exportSelections() { index++; - Selection i = selections.get(*si); + Range i = ranges.get(*si); i.name = prefix + "-" + QString::number(index); QDomElement sample = doc.createElement("sample"); sample.setAttribute("name", i.name); sample.setAttribute("power", QString::number(i.energy)); + sample.setAttribute("position", QString::number(i.position)); samples.appendChild(sample); - selections.update(*si, i); + ranges.update(*si, i); int channelnum = 1; // Filechannel numbers are 1-based. diff --git a/src/audioextractor.h b/src/audioextractor.h index 134c582..aa85d98 100644 --- a/src/audioextractor.h +++ b/src/audioextractor.h @@ -32,7 +32,7 @@ #include <QString> #include <QVector> -#include "selection.h" +#include "range.h" #include "samplesorter.h" class Instrument; @@ -45,7 +45,7 @@ public: AudioExtractor(Instrument& instrument, QObject* parent); public slots: - bool exportSelections(); + bool exportRanges(); signals: void progressUpdate(int value); diff --git a/src/audiofile.h b/src/audiofile.h new file mode 100644 index 0000000..0513f64 --- /dev/null +++ b/src/audiofile.h @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * audiofile.h + * + * Wed Mar 15 08:47:33 CET 2023 + * Copyright 2023 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. + */ +#pragma once + diff --git a/src/canvastool.cc b/src/canvastool.cc index a00a5a2..0ec7f6d 100644 --- a/src/canvastool.cc +++ b/src/canvastool.cc @@ -66,7 +66,7 @@ void CanvasTool::activate() setActive(true); } -void CanvasTool::disactivate() +void CanvasTool::deactivate() { setActive(false); } diff --git a/src/canvastool.h b/src/canvastool.h index c890422..dd4a8b3 100644 --- a/src/canvastool.h +++ b/src/canvastool.h @@ -54,7 +54,7 @@ signals: public slots: void setActive(bool active); void activate(); - void disactivate(); + void deactivate(); private: bool _active; diff --git a/src/canvastoollisten.cc b/src/canvastoollisten.cc index b49e8bc..145d4f9 100644 --- a/src/canvastoollisten.cc +++ b/src/canvastoollisten.cc @@ -27,6 +27,8 @@ #include "canvastoollisten.h" #include <QApplication> +#include <iostream> + CanvasToolListen::CanvasToolListen(Canvas* c, Player& p) : player(p) @@ -42,6 +44,7 @@ bool CanvasToolListen::mousePressEvent(QMouseEvent* event) return false; } player.setPosition(canvas->unmapX(event->x())); + std::cout << (size_t)canvas->unmapX(event->x()) << std::endl; canvas->update(); connect(&player, SIGNAL(positionUpdate(size_t)), this, SLOT(update(size_t))); return true; diff --git a/src/canvastoolposition.cc b/src/canvastoolposition.cc new file mode 100644 index 0000000..7784720 --- /dev/null +++ b/src/canvastoolposition.cc @@ -0,0 +1,161 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoolposition.cc + * + * Sat Mar 25 11:45:34 CET 2023 + * Copyright 2023 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 "canvastoolposition.h" + +#include "project.h" +#include "canvas.h" +#include "range.h" + +#include <iostream> + +#define mapX(x) canvas.mapX(x) +#define mapY(x) canvas.mapY(x) +#define unmapX(x) canvas.unmapX(x) +#define unmapY(x) canvas.unmapY(x) + +CanvasToolPosition::CanvasToolPosition(Instrument& instrument, + Canvas& canvas, + Ranges& ranges, + Ranges& ranges_preview) + : instrument(instrument) + , canvas(canvas) + , ranges(ranges) + , ranges_preview(ranges_preview) +{ + 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 CanvasToolPosition::mouseMoveEvent(QMouseEvent* event) +{ + return false; +} + +bool CanvasToolPosition::mousePressEvent(QMouseEvent* event) +{ + return false; +} + +bool CanvasToolPosition::mouseReleaseEvent(QMouseEvent* event) +{ + return false; +} + +namespace { +void drawRange(const Range& range, Canvas& canvas, QPainter& painter) +{ + int x1 = mapX(range.pos1); + int x2 = mapX(range.pos2); + + if(x1 > x2) + { + std::swap(x1, x2); + } + + // x1 x2 + // | | + // | | + // |<---->| + // | | + // | | + constexpr auto len = 8; + painter.drawLine(x1, mapY(-1.0), x1, mapY(1.0)); // left bar + + painter.drawLine(x1, mapY( 0.0), x1 + len, mapY(0.0) + len); // left arrow + painter.drawLine(x1, mapY( 0.0), x1 + len, mapY(0.0) - len); // left arrow + + painter.drawLine(x1, mapY( 0.0), x2, mapY(0.0)); // horizontal line + + painter.drawLine(x2, mapY( 0.0), x2 - len, mapY(0.0) + len); // right arrow + painter.drawLine(x2, mapY( 0.0), x2 - len, mapY(0.0) - len); // right arrow + + painter.drawLine(x2, mapY(-1.0), x2, mapY(1.0)); // right bar +} +} + +void CanvasToolPosition::paintEvent(QPaintEvent* event, QPainter& painter) +{ + int pos = unmapX(event->rect().x()); + int width = unmapX(event->rect().width()); + + { + QVector<sel_id_t> ids = ranges.ids(); + QVector<sel_id_t>::iterator i = ids.begin(); + while(i != ids.end()) + { + Range range = ranges.get(*i); + + if(ranges.active() == *i) + { + painter.setBrush(colActiveSelBg); + painter.setPen(colActiveSel); + } + else + { + painter.setBrush(colSelBg); + painter.setPen(colSel); + } + + drawRange(range, canvas, painter); + i++; + } + } + + if(show_preview) + { + QVector<sel_id_t> ids = ranges_preview.ids(); + QVector<sel_id_t>::iterator i = ids.begin(); + while(i != ids.end()) + { + Range range = ranges.get(*i); + painter.setBrush(colPreviewSelBg); + painter.setPen(colPreviewSel); + drawRange(range, canvas, painter); + i++; + } + } +} + +void CanvasToolPosition::keyReleaseEvent(QKeyEvent* event) +{ +} + +void CanvasToolPosition::rangesChanged() +{ + //auto ranges = instrument.getRanges(); + canvas.update(); +} + +void CanvasToolPosition::setShowPreview(bool show_preview) +{ + this->show_preview = show_preview; + canvas.update(); +} diff --git a/src/canvastoolposition.h b/src/canvastoolposition.h new file mode 100644 index 0000000..0265a37 --- /dev/null +++ b/src/canvastoolposition.h @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoolposition.h + * + * Sat Mar 25 11:45:34 CET 2023 + * Copyright 2023 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. + */ +#pragma once + +#include "canvastool.h" + +#include <QColor> + +class Instrument; +class Canvas; +class Ranges; + +class CanvasToolPosition + : public CanvasTool +{ + Q_OBJECT +public: + CanvasToolPosition(Instrument& instrument, + Canvas& canvas, + Ranges& ranges, + Ranges& ranges_preview); + + QString name() override { return tr("Position"); } + bool mouseMoveEvent(QMouseEvent* event) override; + bool mousePressEvent(QMouseEvent* event) override; + bool mouseReleaseEvent(QMouseEvent* event) override; + void paintEvent(QPaintEvent* event, QPainter& painter) override; + void keyReleaseEvent(QKeyEvent* event) override; + +public slots: + void rangesChanged(); + void setShowPreview(bool show_preview); + +private: + Instrument& instrument; + Canvas& canvas; + Ranges& ranges; + Ranges& ranges_preview; + + QColor colSelBg; + QColor colSel; + QColor colActiveSelBg; + QColor colActiveSel; + QColor colPreviewSelBg; + QColor colPreviewSel; + + bool show_preview{false}; +}; diff --git a/src/canvastoolselections.cc b/src/canvastoolranges.cc index d3e90f1..9a76163 100644 --- a/src/canvastoolselections.cc +++ b/src/canvastoolranges.cc @@ -1,6 +1,6 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** - * canvastoolselections.cc + * canvastoolranges.cc * * Thu Jul 28 20:16:59 CEST 2011 * Copyright 2011 Bent Bisballe Nyeng @@ -24,28 +24,32 @@ * 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 "canvastoolranges.h" + +#include "project.h" #include <math.h> #include <stdio.h> +#include <iostream> #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) +CanvasToolRanges::CanvasToolRanges(Instrument& instrument, + Canvas* c, Ranges& s, + Ranges& p) + : instrument(instrument) + , ranges(s) + , ranges_preview(p) { - threshold = 0.5; // Default from CanvasToolThreshold hold = 100; canvas = c; - selection_is_moving_left = false; - selection_is_moving_right = false; + range_is_moving_left = false; + range_is_moving_right = false; colSelBg = QColor(255, 0, 0, 60); colSel = QColor(255, 0, 0, 160); @@ -55,39 +59,39 @@ CanvasToolSelections::CanvasToolSelections(Canvas* c, Selections& s, colPreviewSel = QColor(0, 0, 255, 160); } -bool CanvasToolSelections::mouseMoveEvent(QMouseEvent* event) +bool CanvasToolRanges::mouseMoveEvent(QMouseEvent* event) { - sel_id_t active_selection = selections.active(); - Selection act_sel = selections.get(active_selection); + sel_id_t active_range = ranges.active(); + Range act_sel = ranges.get(active_range); - if(selection_is_moving_left) + if(range_is_moving_left) { float val = unmapX(event->x()); if(val > act_sel.to) val = act_sel.to - 1; act_sel.from = std::max(0.0f, val); - selections.update(active_selection, act_sel); + ranges.update(active_range, act_sel); canvas->update(); return true; } - if(selection_is_moving_right) + if(range_is_moving_right) { float val = unmapX(event->x()); if(val < act_sel.from) val = act_sel.from + 1; act_sel.to = std::min(val, (float)canvas->size); - selections.update(active_selection, act_sel); + ranges.update(active_range, act_sel); canvas->update(); return true; } if(event->button() != Qt::LeftButton) { - // Check if a selection is being dragged. - QVector<sel_id_t> ids = selections.ids(); + // Check if a range is being dragged. + QVector<sel_id_t> ids = ranges.ids(); QVector<sel_id_t>::iterator i = ids.begin(); while(i != ids.end()) { - Selection sel = selections.get(*i); + Range sel = ranges.get(*i); if(abs(event->x() - mapX(sel.from)) < 2 || abs(event->x() - mapX(sel.to)) < 2) { @@ -101,42 +105,42 @@ bool CanvasToolSelections::mouseMoveEvent(QMouseEvent* event) return false; } -bool CanvasToolSelections::mousePressEvent(QMouseEvent* event) +bool CanvasToolRanges::mousePressEvent(QMouseEvent* event) { if(event->button() == Qt::LeftButton) { - // Check if a selection is being dragged. - QVector<sel_id_t> ids = selections.ids(); + // Check if a range is being dragged. + QVector<sel_id_t> ids = ranges.ids(); QVector<sel_id_t>::iterator i = ids.begin(); while(i != ids.end()) { - Selection sel = selections.get(*i); + Range sel = ranges.get(*i); if(abs(event->x() - mapX(sel.from)) < 2) { - selections.setActive(*i); - selection_is_moving_left = true; + ranges.setActive(*i); + range_is_moving_left = true; return true; } if(abs(event->x() - mapX(sel.to)) < 2) { - selections.setActive(*i); - selection_is_moving_right = true; + ranges.setActive(*i); + range_is_moving_right = true; return true; } i++; } - // Check if a selection is being selected. + // Check if a range is being selected. i = ids.begin(); while(i != ids.end()) { - Selection sel = selections.get(*i); + Range sel = ranges.get(*i); if(event->x() > mapX(sel.from) && event->x() < mapX(sel.to)) { - selections.setActive(*i); + ranges.setActive(*i); canvas->update(); return true; } @@ -144,12 +148,12 @@ bool CanvasToolSelections::mousePressEvent(QMouseEvent* event) i++; } - // Make new selection + // Make new range 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; + Range new_range{.from = from, .to = from}; + sel_id_t id = ranges.add(new_range); + ranges.setActive(id); + range_is_moving_right = true; canvas->update(); return true; } @@ -157,14 +161,14 @@ bool CanvasToolSelections::mousePressEvent(QMouseEvent* event) return false; } -bool CanvasToolSelections::mouseReleaseEvent(QMouseEvent* event) +bool CanvasToolRanges::mouseReleaseEvent(QMouseEvent* event) { if(event->button() == Qt::LeftButton) { - if(selection_is_moving_left || selection_is_moving_right) + if(range_is_moving_left || range_is_moving_right) { - selection_is_moving_left = false; - selection_is_moving_right = false; + range_is_moving_left = false; + range_is_moving_right = false; canvas->setCursor(Qt::ArrowCursor); canvas->update(); return true; @@ -174,24 +178,24 @@ bool CanvasToolSelections::mouseReleaseEvent(QMouseEvent* event) return false; } -void CanvasToolSelections::paintEvent(QPaintEvent* event, QPainter& painter) +void CanvasToolRanges::paintEvent(QPaintEvent* event, QPainter& painter) { int pos = unmapX(event->rect().x()); int width = unmapX(event->rect().width()); { - QVector<sel_id_t> ids = selections.ids(); + QVector<sel_id_t> ids = ranges.ids(); QVector<sel_id_t>::iterator i = ids.begin(); while(i != ids.end()) { - Selection sel = selections.get(*i); + Range sel = ranges.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) + if(ranges.active() == *i) { painter.setBrush(colActiveSelBg); painter.setPen(colActiveSel); @@ -213,11 +217,11 @@ void CanvasToolSelections::paintEvent(QPaintEvent* event, QPainter& painter) if(show_preview) { - QVector<sel_id_t> ids = selections_preview.ids(); + QVector<sel_id_t> ids = ranges_preview.ids(); QVector<sel_id_t>::iterator i = ids.begin(); while(i != ids.end()) { - Selection sel = selections_preview.get(*i); + Range sel = ranges_preview.get(*i); int from = sel.from; int to = sel.to; int fadein = sel.fadein; @@ -238,56 +242,68 @@ void CanvasToolSelections::paintEvent(QPaintEvent* event, QPainter& painter) } } -void CanvasToolSelections::keyReleaseEvent(QKeyEvent* event) +void CanvasToolRanges::keyReleaseEvent(QKeyEvent* event) { - if(selections.active() != SEL_NONE && event->key() == Qt::Key_Delete) + if(ranges.active() != SEL_NONE && event->key() == Qt::Key_Delete) { - selections.remove(selections.active()); + ranges.remove(ranges.active()); canvas->update(); } } -void CanvasToolSelections::thresholdChanged(double t) -{ - threshold = t; -} - -void CanvasToolSelections::holdChanged(int h) +void CanvasToolRanges::holdChanged(int h) { hold = h; } -void CanvasToolSelections::noiseFloorChanged(int t) +void CanvasToolRanges::noiseFloorChanged(int t) { double div = 666.0 / 0.00003; noise_floor = (double)t/div; } -void CanvasToolSelections::fadeoutChanged(int t) +void CanvasToolRanges::fadeoutChanged(int t) { fadeout = (double)t/1000.0; } -void CanvasToolSelections::autoCreateSelections() +void CanvasToolRanges::autoCreateRanges() { - doAutoCreateSelections(false); + doAutoCreateRanges(false); } -void CanvasToolSelections::autoCreateSelectionsPreview() +void CanvasToolRanges::autoCreateRangesPreview() { - doAutoCreateSelections(true); + doAutoCreateRanges(true); } -void CanvasToolSelections::doAutoCreateSelections(bool preview) +void CanvasToolRanges::setPositionData(const float* positionData1, + size_t positionSize1, + const float* positionData2, + size_t positionSize2) { + std::cout << __PRETTY_FUNCTION__ << std::endl; + std::cout << positionSize1 << " " << positionSize2 << std::endl; + this->positionData1 = positionData1; + this->positionSize1 = positionSize1; + + this->positionData2 = positionData2; + this->positionSize2 = positionSize2; +} + +void CanvasToolRanges::doAutoCreateRanges(bool preview) +{ + std::cout << __PRETTY_FUNCTION__ << std::endl; + + // TODO: Get data from master file instead of canvas float* data = canvas->data; size_t size = canvas->size; - if(preview) selections_preview.clear(); + if(preview) ranges_preview.clear(); for(size_t i = 0; i < size; i++) { - if(fabs(data[i]) > fabs(threshold)) + if(fabs(data[i]) > fabs(instrument.getThreshold())) { int from = i; @@ -320,32 +336,94 @@ void CanvasToolSelections::doAutoCreateSelections(bool preview) to++; } - Selection s(from, to, 2, ((to - from) / 3) * fadeout); + Range range{ + .from = from, + .to = to, + .fadein = 2, + .fadeout = ((to - from) / 3) * fadeout + }; + + ///////////////////////////////////////////////////////////////////////// + if(positionData1 && positionData2) + { + //TODO: set window in ms instead of samples + int pos_window_size{1000}; // +/- 500 from detected, + double threshold = 0.1; // 1/3 is about right + + float norm{0}; + for(int idx = range.from - pos_window_size / 2; + idx < range.from + pos_window_size / 2; + ++idx) + { + norm = std::max(std::abs(positionData1[idx]), norm); + } + + int pos1{range.from - pos_window_size / 2}; + for(int idx = range.from - pos_window_size / 2; + idx < range.from + pos_window_size / 2; + ++idx) + { + if(std::abs(positionData1[idx]) / norm > threshold) + { + pos1 = idx; + range.pos1 = pos1; + break; + } + } + + norm = 0; + for(int idx = range.from - pos_window_size / 2; + idx < range.from + pos_window_size / 2; + ++idx) + { + norm = std::max(std::abs(positionData1[idx]), norm); + } + + int pos2{range.from + pos_window_size / 2}; + for(int idx = range.from - pos_window_size / 2; + idx < range.from + pos_window_size / 2; + ++idx) + { + if(std::abs(positionData2[idx]) / norm > threshold) + { + pos2 = idx; + range.pos2 = pos2; + break; + } + } + + constexpr double speed_of_sound{343100}; // mm/s + constexpr double samplerate{48000}; // 48kHz - TODO get from audio + + range.position = std::abs(pos1 - pos2) * speed_of_sound / samplerate / 2.0; + } + ///////////////////////////////////////////////////////////////////////// + if(preview) { - selections_preview.add(s); + ranges_preview.add(range); } else { - selections.add(s); + ranges.add(range); } - i = to+1; + i = to + 1; } } canvas->update(); } -void CanvasToolSelections::clearSelections() +void CanvasToolRanges::clearRanges() { - selections.clear(); - selection_is_moving_left = false; - selection_is_moving_right = false; + ranges.clear(); + range_is_moving_left = false; + range_is_moving_right = false; canvas->setCursor(Qt::ArrowCursor); canvas->update(); } -void CanvasToolSelections::setShowPreview(bool s) +void CanvasToolRanges::setShowPreview(bool s) { show_preview = s; canvas->update(); diff --git a/src/canvastoolselections.h b/src/canvastoolranges.h index 21f00c6..164532a 100644 --- a/src/canvastoolselections.h +++ b/src/canvastoolranges.h @@ -1,6 +1,6 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** - * canvastoolselections.h + * canvastoolranges.h * * Thu Jul 28 20:16:59 CEST 2011 * Copyright 2011 Bent Bisballe Nyeng @@ -32,48 +32,56 @@ #include "canvas.h" -#include "selection.h" +#include "range.h" -class CanvasToolSelections +class Instrument; + +class CanvasToolRanges : public CanvasTool { Q_OBJECT public: - CanvasToolSelections(Canvas* canvas, Selections& selections, - Selections& selections_preview); + CanvasToolRanges(Instrument& instrument, + Canvas* canvas, Ranges& ranges, + Ranges& ranges_preview); - QString name() { return tr("Selections"); } + QString name() { return tr("Ranges"); } bool mouseMoveEvent(QMouseEvent* event); bool mousePressEvent(QMouseEvent* event); bool mouseReleaseEvent(QMouseEvent* event); void paintEvent(QPaintEvent* event, QPainter& painter); void keyReleaseEvent(QKeyEvent* event); - //Selections selections(); + //Ranges ranges(); + + void setPositionData(const float* positionData1, + size_t positionSize1, + const float* positionData2, + size_t positionSize2); signals: - //void selectionsChanged(Selections selections); - //void activeSelectionChanged(sel_id_t id); + //void rangesChanged(Ranges ranges); + //void activeRangeChanged(sel_id_t id); public slots: - void autoCreateSelections(); - void autoCreateSelectionsPreview(); - void clearSelections(); - void thresholdChanged(double threshold); + void autoCreateRanges(); + void autoCreateRangesPreview(); + void clearRanges(); void noiseFloorChanged(int t); void holdChanged(int h); void fadeoutChanged(int f); void setShowPreview(bool show_preview); private: - void doAutoCreateSelections(bool preview); + void doAutoCreateRanges(bool preview); - bool selection_is_moving_left; - bool selection_is_moving_right; + Instrument& instrument; + + bool range_is_moving_left; + bool range_is_moving_right; Canvas* canvas; - double threshold; double noise_floor; double fadeout; int hold; @@ -85,8 +93,13 @@ private: QColor colPreviewSelBg; QColor colPreviewSel; - Selections& selections; - Selections& selections_preview; + Ranges& ranges; + Ranges& ranges_preview; bool show_preview; + + const float* positionData1{}; + size_t positionSize1{}; + const float* positionData2{}; + size_t positionSize2{}; }; diff --git a/src/canvastoolthreshold.cc b/src/canvastoolthreshold.cc index a905766..65a195b 100644 --- a/src/canvastoolthreshold.cc +++ b/src/canvastoolthreshold.cc @@ -27,24 +27,23 @@ #include "canvastoolthreshold.h" #include <math.h> +#include <iostream> +#include "canvas.h" #include "project.h" -#define mapX(x) canvas->mapX(x) -#define mapY(x) canvas->mapY(x) -#define unmapX(x) canvas->unmapX(x) -#define unmapY(x) canvas->unmapY(x) +#define mapY(x) canvas.mapY(x) +#define unmapY(x) canvas.unmapY(x) -CanvasToolThreshold::CanvasToolThreshold(Canvas* c, Instrument& instrument) - : instrument(instrument) +CanvasToolThreshold::CanvasToolThreshold(Canvas& canvas, double default_value, + QColor color, QColor moving_color) + : canvas(canvas) + , colThreshold(color) + , colThresholdMoving(moving_color) { - canvas = c; - threshold = instrument.getThreshold(); + threshold = default_value; threshold_is_moving = false; - - colThreshold = QColor(255, 127, 127); - colThresholdMoving = QColor(180, 0, 0); } bool CanvasToolThreshold::mouseMoveEvent(QMouseEvent* event) @@ -60,7 +59,7 @@ bool CanvasToolThreshold::mouseMoveEvent(QMouseEvent* event) abs(event->y() - mapY(-threshold)) < 2 ) { - canvas->setCursor(Qt::SplitVCursor); + canvas.setCursor(Qt::SplitVCursor); return true; } } @@ -73,10 +72,10 @@ bool CanvasToolThreshold::mouseMoveEvent(QMouseEvent* event) val = 1.0; } threshold = fabs(val); - canvas->update(); + canvas.update(); emit thresholdChanging(threshold); - instrument.setThreshold(threshold); + std::cout << threshold << "\n"; return true; } @@ -97,7 +96,7 @@ bool CanvasToolThreshold::mousePressEvent(QMouseEvent* event) abs(event->y() - mapY(-threshold)) < 2) { threshold_is_moving = true; - canvas->update(); + canvas.update(); return true; } } @@ -117,11 +116,10 @@ bool CanvasToolThreshold::mouseReleaseEvent(QMouseEvent* event) if(threshold_is_moving) { threshold_is_moving = false; - canvas->setCursor(Qt::ArrowCursor); - canvas->update(); + canvas.setCursor(Qt::ArrowCursor); + canvas.update(); emit thresholdChanged(threshold); - instrument.setThreshold(threshold); return true; } } diff --git a/src/canvastoolthreshold.h b/src/canvastoolthreshold.h index 936bf68..8847ecb 100644 --- a/src/canvastoolthreshold.h +++ b/src/canvastoolthreshold.h @@ -30,16 +30,15 @@ #include <QColor> -#include "canvas.h" - -class Instrument; +class Canvas; class CanvasToolThreshold : public CanvasTool { Q_OBJECT public: - CanvasToolThreshold(Canvas* canvas, Instrument& instrument); + CanvasToolThreshold(Canvas& canvas, double default_value, + QColor color, QColor moving_color); QString name() { return tr("Threshold"); } bool mouseMoveEvent(QMouseEvent* event); @@ -52,13 +51,11 @@ signals: void thresholdChanging(double threshold); private: - float threshold; + double threshold; bool threshold_is_moving; - Canvas* canvas; + Canvas& canvas; QColor colThreshold; QColor colThresholdMoving; - - Instrument& instrument; }; diff --git a/src/detector.cc b/src/detector.cc new file mode 100644 index 0000000..4a83659 --- /dev/null +++ b/src/detector.cc @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * detector.cc + * + * Wed Mar 15 08:34:24 CET 2023 + * Copyright 2023 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 "detector.h" + diff --git a/src/detector.h b/src/detector.h new file mode 100644 index 0000000..8bd84d1 --- /dev/null +++ b/src/detector.h @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * detector.h + * + * Wed Mar 15 08:34:24 CET 2023 + * Copyright 2023 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. + */ +#pragma once + +#include <QObject> + +class Detector + : public QObject +{ +public slots: + // threshold changed (double) + // master file changed (float*, size) + + // pos threshold changed, 1/2 (double) + // pos file changed, 1/2 (float*, size) + +signals: + // ranges changed + // pos changed, 1/2 +}; diff --git a/src/filelist.cc b/src/filelist.cc index e1467e3..b746450 100644 --- a/src/filelist.cc +++ b/src/filelist.cc @@ -35,7 +35,6 @@ #include "itemeditor.h" #include "project.h" -#include <QAbstractItemModel> #include <QTreeView> #include <iostream> @@ -43,7 +42,6 @@ #include <QComboBox> #include <QLineEdit> #include <QCheckBox> -#include <QStyledItemDelegate> #include <QPainter> #include <QHeaderView> #include <QStyleOptionButton> @@ -51,378 +49,225 @@ #include <sndfile.h> -class ChannelMapDeligate - : public QStyledItemDelegate +FileDataModel::FileDataModel(Instrument& instrument, FileList* fileList) + : instrument(instrument) + , fileList(fileList) +{ +} + +QModelIndex FileDataModel::index(int row, int column, const QModelIndex &parent) const { -public: - ChannelMapDeligate(Instrument& instrument) - : instrument(instrument) + if(!hasIndex(row, column, parent)) { + return QModelIndex(); } - QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, - const QModelIndex &index) const override + auto audiofile_ids = instrument.getAudioFileList(); + if(!parent.isValid()) { - // Main channel: - if(index.column() == 2) - { - auto w = new QCheckBox(parent); - auto audiofile_ids = instrument.getAudioFileList(); - auto audiofile_id = audiofile_ids.begin() + index.row(); - auto& audiofile = instrument.getAudioFile(*audiofile_id); - - connect(w, &QCheckBox::stateChanged, - [&audiofile](int state) - { - audiofile.setMainChannel(state == Qt::Checked); - }); - - return w; - } - - // Name: - if(index.column() == 3) + if(row < audiofile_ids.size()) { - auto w = new QLineEdit(parent); - - auto audiofile_ids = instrument.getAudioFileList(); - auto audiofile_id = audiofile_ids.begin() + index.row(); - auto& audiofile = instrument.getAudioFile(*audiofile_id); - - connect(w, &QLineEdit::textEdited, - [&audiofile](const QString& name) - { - audiofile.setName(name); - }); - return w; + return createIndex(row, column, &instrument); } - - // Channel Map ID: - if(index.column() == 4) + else { - auto w = new QComboBox(parent); - w->addItem(tr("<None>"), -1); - auto channel_ids = instrument.getProject().getChannelList(); - for(auto channel_id : channel_ids) - { - const auto& channel = instrument.getProject().getChannel(channel_id); - w->addItem(channel.getChannelName(), channel.getId()); - } - - auto audiofile_ids = instrument.getAudioFileList(); - auto audiofile_id = audiofile_ids.begin() + index.row(); - auto& audiofile = instrument.getAudioFile(*audiofile_id); - - connect(w, - // This wierd line points the compiler to the correct overloaded - // version of QComboBox::currentIndexChanged - // ie. chooses the (int) version over the (const QString&) version - QOverload<int>::of(&QComboBox::currentIndexChanged), - [w, &audiofile](int idx) - { - audiofile.setChannelMapId(w->itemData(idx).toInt()); - }); - return w; + return QModelIndex(); // row is out of bounds. } - - return QStyledItemDelegate::createEditor(parent, option, index); } - void setEditorData(QWidget *editor, const QModelIndex &index) const override - { - // Main channel: - if(index.column() == 2) - { - auto w = static_cast<QCheckBox*>(editor); - auto b = index.data(Qt::EditRole).toBool(); - w->setCheckState(b ? Qt::Checked : Qt::Unchecked); - } - - // Name: - if(index.column() == 3) - { - auto w = static_cast<QLineEdit*>(editor); - auto s = index.data(Qt::EditRole).toString(); - w->setText(s); - } + return QModelIndex(); +} - // Channel Map ID: - if(index.column() == 4) - { - auto w = static_cast<QComboBox*>(editor); - auto i = w->findData(index.data(Qt::EditRole).toInt()); - w->setCurrentIndex(i); - } +QModelIndex FileDataModel::parent(const QModelIndex &index) const +{ + return QModelIndex(); // no parent } - void setModelData(QWidget *editor, QAbstractItemModel *model, - const QModelIndex &index) const override +int FileDataModel::rowCount(const QModelIndex &parent) const +{ + if(parent.column() > 0) // only return row count on first column { - // Main channel: - if(index.column() == 2) - { - model->setData(index, - static_cast<QCheckBox*>(editor)->checkState() == Qt::Checked, - Qt::EditRole); - } - - // Name: - if(index.column() == 3) - { - model->setData(index, static_cast<QLineEdit*>(editor)->text(), - Qt::EditRole); - } - - // Channel Map ID: - if(index.column() == 4) - { - model->setData(index, static_cast<QComboBox*>(editor)->currentData(), - Qt::EditRole); - } + return 0; } - void paint(QPainter* painter, const QStyleOptionViewItem& option, - const QModelIndex& index) const override + if(!parent.isValid()) { - if(index.column() == 2) // Main Channel - { - auto audiofile_ids = instrument.getAudioFileList(); - auto audiofile_id = audiofile_ids.begin() + index.row(); - const auto& audiofile = instrument.getAudioFile(*audiofile_id); - - bool checked = audiofile.getMainChannel(); - QStyleOptionButton butOpt; - butOpt.state = QStyle::State_Enabled; - butOpt.state |= checked ? QStyle::State_On : QStyle::State_Off; - butOpt.rect = option.rect; - QApplication::style()->drawControl( QStyle::CE_CheckBox, - &butOpt, painter ); - } - else - { - QStyledItemDelegate::paint(painter, option, index); - } + auto audiofile_ids = instrument.getAudioFileList(); + return audiofile_ids.size(); // root level } -private: - Instrument& instrument; -}; + return 0; // no children +} -class FileDataModel - : public QAbstractItemModel +int FileDataModel::columnCount(const QModelIndex &parent) const { -public: - FileDataModel(Instrument& instrument) - : instrument(instrument) + return 6; +} + +QVariant FileDataModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) { + return QVariant(); } - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override - { - if(!hasIndex(row, column, parent)) - { - return QModelIndex(); - } + auto audiofile_ids = instrument.getAudioFileList(); - auto audiofile_ids = instrument.getAudioFileList(); - if(!parent.isValid()) + auto audiofile_id = audiofile_ids.begin() + index.row(); + const auto& audiofile = instrument.getAudioFile(*audiofile_id); + + if(role == Qt::DecorationRole ) + { + if(index.column() == 0) { - if(row < audiofile_ids.size()) + if(audiofile.getAbsoluteFile() == instrument.getMasterFile()) { - return createIndex(row, column, &instrument); + return QPixmap(":/icons/master.png"); } else { - return QModelIndex(); // row is out of bounds. + return QPixmap(":/icons/file.png"); } } - - return QModelIndex(); - } - - QModelIndex parent(const QModelIndex &index) const override - { - return QModelIndex(); // no parent - } - - int rowCount(const QModelIndex &parent = QModelIndex()) const override - { - if(parent.column() > 0) // only return row count on first column - { - return 0; - } - - if(!parent.isValid()) - { - auto audiofile_ids = instrument.getAudioFileList(); - return audiofile_ids.size(); // root level - } - - return 0; // no children } - int columnCount(const QModelIndex &parent = QModelIndex()) const override + if(role == Qt::DisplayRole) { - return 5; - } - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override - { - if(!index.isValid()) - { - return QVariant(); - } - - auto audiofile_ids = instrument.getAudioFileList(); - - auto audiofile_id = audiofile_ids.begin() + index.row(); - const auto& audiofile = instrument.getAudioFile(*audiofile_id); - - if(role == Qt::DecorationRole ) - { - if(index.column() == 0) - { - if(audiofile.getAbsoluteFile() == instrument.getMasterFile()) - { - return QPixmap(":/icons/master.png"); - } - else - { - return QPixmap(":/icons/file.png"); - } - } - } - - if(role == Qt::DisplayRole) + switch(index.column()) { - switch(index.column()) - { - case 0: return QVariant(); // Master - case 1: return audiofile.getFile(); - case 2: return audiofile.getMainChannel() ? "x" : " "; - case 3: return audiofile.getName(); - case 4: - { - auto channelMapId = audiofile.getChannelMapId(); - if(channelMapId == -1) - { - return tr("<None>"); - } - return instrument.getProject().getChannel(channelMapId).getChannelName(); - } - default: return QVariant(); - } - } - else if(role == Qt::EditRole) + case 0: return QVariant(); // Master + case 1: return audiofile.getFile(); + case 2: return audiofile.getMainChannel() ? "x" : " "; + case 3: return audiofile.getName(); + case 4: { - switch(index.column()) + auto channelMapId = audiofile.getChannelMapId(); + if(channelMapId == -1) { - case 0: return QVariant(); // Master - case 1: return audiofile.getFile(); - case 2: return audiofile.getMainChannel(); - case 3: return audiofile.getName(); - case 4: return audiofile.getChannelMapId(); - default: return QVariant(); + return tr("<None>"); } + return instrument.getProject().getChannel(channelMapId).getChannelName(); } - else - - { - return QVariant(); + case 5: return audiofile.getPositionChannel() ? "x" : " "; + default: return QVariant(); } } - - QVariant headerData(int section, Qt::Orientation orientation, int role) const override + else if(role == Qt::EditRole) { - if(orientation == Qt::Horizontal && role == Qt::DisplayRole) + switch(index.column()) { - switch(section) - { - case 0: return tr("M"); - case 1: return tr("Filename"); - case 2: return tr("m"); - case 3: return tr("Name"); - case 4: return tr("Kit Channel"); - default: return QVariant(); - } + case 0: return QVariant(); // Master + case 1: return audiofile.getFile(); + case 2: return audiofile.getMainChannel(); + case 3: return audiofile.getName(); + case 4: return audiofile.getChannelMapId(); + case 5: return audiofile.getPositionChannel(); + default: return QVariant(); } + } + else + { return QVariant(); } +} - Qt::ItemFlags flags(const QModelIndex &index) const override +QVariant FileDataModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(orientation == Qt::Horizontal && role == Qt::DisplayRole) { - if(!index.isValid()) + switch(section) { - return 0; - } - - switch(index.column()) - { - case 0: // Master - return QAbstractItemModel::flags(index); - case 1: // File - return QAbstractItemModel::flags(index); - case 2: // Main channel - return Qt::ItemIsEditable | QAbstractItemModel::flags(index); - case 3: // Name - return Qt::ItemIsEditable | QAbstractItemModel::flags(index); - case 4: // Channel map id - return Qt::ItemIsEditable | QAbstractItemModel::flags(index); + case 0: return tr("M"); + case 1: return tr("Filename"); + case 2: return tr("m"); + case 3: return tr("Name"); + case 4: return tr("Kit Channel"); + case 5: return tr("p"); + default: return QVariant(); } } - bool setData(const QModelIndex &index, const QVariant &value, - int role = Qt::EditRole) override + return QVariant(); +} + +Qt::ItemFlags FileDataModel::flags(const QModelIndex &index) const +{ + if(!index.isValid()) { - auto audiofile_ids = instrument.getAudioFileList(); + return 0; + } - if(index.row() > audiofile_ids.size() || - index.column() > (columnCount() - 1)) - { - return false; - } + switch(index.column()) + { + case 0: // Master + return QAbstractItemModel::flags(index); + case 1: // File + return QAbstractItemModel::flags(index); + case 2: // Main channel + return Qt::ItemIsEditable | QAbstractItemModel::flags(index); + case 3: // Name + return Qt::ItemIsEditable | QAbstractItemModel::flags(index); + case 4: // Channel map id + return Qt::ItemIsEditable | QAbstractItemModel::flags(index); + case 5: // Pos channel + return Qt::ItemIsEditable | QAbstractItemModel::flags(index); + } - auto audiofile_id = audiofile_ids.begin() + index.row(); - auto& audiofile = instrument.getAudioFile(*audiofile_id); + return 0; +} - switch(index.column()) - { - case 0: // Master - break; - case 1: // File - break; - case 2: // Main Channel - audiofile.setMainChannel(value.toBool()); - break; - case 3: // Name - audiofile.setName(value.toString()); - break; - case 4: // Channel map id - audiofile.setChannelMapId(value.toInt()); - break; - default: break; - } +bool FileDataModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + auto audiofile_ids = instrument.getAudioFileList(); - return true; + if(index.row() > audiofile_ids.size() || + index.column() > (columnCount() - 1)) + { + return false; } - void refresh() + auto audiofile_id = audiofile_ids.begin() + index.row(); + auto& audiofile = instrument.getAudioFile(*audiofile_id); + + switch(index.column()) { - beginResetModel(); - endResetModel(); + case 0: // Master + break; + case 1: // File + break; + case 2: // Main Channel + audiofile.setMainChannel(value.toBool()); + break; + case 3: // Name + audiofile.setName(value.toString()); + break; + case 4: // Channel map id + audiofile.setChannelMapId(value.toInt()); + break; + case 5: // Pos Channel + audiofile.setPositionChannel(value.toBool()); + fileList->positionFilesChanged(); + break; + default: break; } -private: - Instrument& instrument; -}; + return true; +} + +void FileDataModel::refresh() +{ + beginResetModel(); + endResetModel(); +} + FileList::FileList(Instrument& instrument) : instrument(instrument) { - model = new FileDataModel(instrument); + model = new FileDataModel(instrument, this); setModel(model); - setItemDelegate(new ChannelMapDeligate(instrument)); + setItemDelegate(new ChannelMapDeligate(instrument, this)); setEditTriggers(QAbstractItemView::AllEditTriggers); // show list on click setContextMenuPolicy(Qt::CustomContextMenu); // enable context menu @@ -584,3 +429,202 @@ void FileList::removeAllFiles() emit masterFileChanged(""); // Clear canvas emit allFilesRemoved(); } + + +ChannelMapDeligate::ChannelMapDeligate(Instrument& instrument, FileList* fileList) + : instrument(instrument) + , fileList(fileList) +{ +} + +QWidget* ChannelMapDeligate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + // Main channel: + if(index.column() == 2) + { + auto w = new QCheckBox(parent); + auto audiofile_ids = instrument.getAudioFileList(); + auto audiofile_id = audiofile_ids.begin() + index.row(); + auto& audiofile = instrument.getAudioFile(*audiofile_id); + + connect(w, &QCheckBox::stateChanged, + [&audiofile](int state) + { + audiofile.setMainChannel(state == Qt::Checked); + }); + + return w; + } + + // Name: + if(index.column() == 3) + { + auto w = new QLineEdit(parent); + + auto audiofile_ids = instrument.getAudioFileList(); + auto audiofile_id = audiofile_ids.begin() + index.row(); + auto& audiofile = instrument.getAudioFile(*audiofile_id); + + connect(w, &QLineEdit::textEdited, + [&audiofile](const QString& name) + { + audiofile.setName(name); + }); + return w; + } + + // Channel Map ID: + if(index.column() == 4) + { + auto w = new QComboBox(parent); + w->addItem(tr("<None>"), -1); + auto channel_ids = instrument.getProject().getChannelList(); + for(auto channel_id : channel_ids) + { + const auto& channel = instrument.getProject().getChannel(channel_id); + w->addItem(channel.getChannelName(), channel.getId()); + } + + auto audiofile_ids = instrument.getAudioFileList(); + auto audiofile_id = audiofile_ids.begin() + index.row(); + auto& audiofile = instrument.getAudioFile(*audiofile_id); + + connect(w, + // This wierd line points the compiler to the correct overloaded + // version of QComboBox::currentIndexChanged + // ie. chooses the (int) version over the (const QString&) version + QOverload<int>::of(&QComboBox::currentIndexChanged), + [w, &audiofile](int idx) + { + audiofile.setChannelMapId(w->itemData(idx).toInt()); + }); + return w; + } + + // Pos channel: + if(index.column() == 5) + { + auto w = new QCheckBox(parent); + auto audiofile_ids = instrument.getAudioFileList(); + auto audiofile_id = audiofile_ids.begin() + index.row(); + auto& audiofile = instrument.getAudioFile(*audiofile_id); + + connect(w, &QCheckBox::stateChanged, + [&](int state) + { + audiofile.setPositionChannel(state == Qt::Checked); + fileList->positionFilesChanged(); + }); + + return w; + } + + return QStyledItemDelegate::createEditor(parent, option, index); +} + +void ChannelMapDeligate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + // Main channel: + if(index.column() == 2) + { + auto w = static_cast<QCheckBox*>(editor); + auto b = index.data(Qt::EditRole).toBool(); + w->setCheckState(b ? Qt::Checked : Qt::Unchecked); + } + + // Name: + if(index.column() == 3) + { + auto w = static_cast<QLineEdit*>(editor); + auto s = index.data(Qt::EditRole).toString(); + w->setText(s); + } + + // Channel Map ID: + if(index.column() == 4) + { + auto w = static_cast<QComboBox*>(editor); + auto i = w->findData(index.data(Qt::EditRole).toInt()); + w->setCurrentIndex(i); + } + + // Pos channel: + if(index.column() == 5) + { + auto w = static_cast<QCheckBox*>(editor); + auto b = index.data(Qt::EditRole).toBool(); + w->setCheckState(b ? Qt::Checked : Qt::Unchecked); + } +} + +void ChannelMapDeligate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + // Main channel: + if(index.column() == 2) + { + model->setData(index, + static_cast<QCheckBox*>(editor)->checkState() == Qt::Checked, + Qt::EditRole); + } + + // Name: + if(index.column() == 3) + { + model->setData(index, static_cast<QLineEdit*>(editor)->text(), + Qt::EditRole); + } + + // Channel Map ID: + if(index.column() == 4) + { + model->setData(index, static_cast<QComboBox*>(editor)->currentData(), + Qt::EditRole); + } + + // Pos channel: + if(index.column() == 5) + { + model->setData(index, + static_cast<QCheckBox*>(editor)->checkState() == Qt::Checked, + Qt::EditRole); + } +} + +void ChannelMapDeligate::paint(QPainter* painter, const QStyleOptionViewItem& option, + const QModelIndex& index) const +{ + if(index.column() == 2) // Main Channel + { + auto audiofile_ids = instrument.getAudioFileList(); + auto audiofile_id = audiofile_ids.begin() + index.row(); + const auto& audiofile = instrument.getAudioFile(*audiofile_id); + + bool checked = audiofile.getMainChannel(); + QStyleOptionButton butOpt; + butOpt.state = QStyle::State_Enabled; + butOpt.state |= checked ? QStyle::State_On : QStyle::State_Off; + butOpt.rect = option.rect; + QApplication::style()->drawControl( QStyle::CE_CheckBox, + &butOpt, painter ); + } + else if(index.column() == 5) // Pos Channel + { + auto audiofile_ids = instrument.getAudioFileList(); + auto audiofile_id = audiofile_ids.begin() + index.row(); + const auto& audiofile = instrument.getAudioFile(*audiofile_id); + + bool checked = audiofile.getPositionChannel(); + QStyleOptionButton butOpt; + butOpt.state = QStyle::State_Enabled; + butOpt.state |= checked ? QStyle::State_On : QStyle::State_Off; + butOpt.rect = option.rect; + QApplication::style()->drawControl( QStyle::CE_CheckBox, + &butOpt, painter ); + } + else + { + QStyledItemDelegate::paint(painter, option, index); + } +} diff --git a/src/filelist.h b/src/filelist.h index 165af83..af0d40a 100644 --- a/src/filelist.h +++ b/src/filelist.h @@ -29,9 +29,41 @@ #include <QTreeView> #include <QAction> #include <QMenu> +#include <QStyledItemDelegate> +#include <QAbstractItemModel> class Instrument; -class FileDataModel; +class FileList; + +class FileDataModel + : public QAbstractItemModel +{ + Q_OBJECT +public: + FileDataModel(Instrument& instrument, FileList* fileList); + + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex &index) const override; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + + Qt::ItemFlags flags(const QModelIndex &index) const override; + + bool setData(const QModelIndex &index, const QVariant &value, + int role = Qt::EditRole) override; + + void refresh(); + +private: + Instrument& instrument; + FileList* fileList; +}; class FileList : public QTreeView @@ -44,6 +76,7 @@ public: signals: void masterFileChanged(QString filename); + void positionFilesChanged(); // void fileAdded(QString file, QString name); void fileRemoved(QString file, QString name); void allFilesRemoved(); @@ -83,3 +116,26 @@ private: Instrument& instrument; FileDataModel* model; }; + +class ChannelMapDeligate + : public QStyledItemDelegate +{ + Q_OBJECT +public: + ChannelMapDeligate(Instrument& instrument, FileList* fileList); + + QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const override; + + void setEditorData(QWidget *editor, const QModelIndex &index) const override; + + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const override; + + void paint(QPainter* painter, const QStyleOptionViewItem& option, + const QModelIndex& index) const override; + +private: + Instrument& instrument; + FileList* fileList; +}; diff --git a/src/instrumentwidget.cc b/src/instrumentwidget.cc index 6a2e17e..42b549b 100644 --- a/src/instrumentwidget.cc +++ b/src/instrumentwidget.cc @@ -47,11 +47,13 @@ #include <QTime> #include <QSpinBox> +#include <sndfile.h> + #include "sleep.h" #include "canvastool.h" #include "canvastoolthreshold.h" #include "volumefader.h" -#include "selectioneditor.h" +#include "rangeeditor.h" #include "zoomslider.h" #include "settings.h" #include "project.h" @@ -74,11 +76,11 @@ InstrumentWidget::InstrumentWidget(Settings& settings, Instrument& instrument) { setProperty("id", instrument.getId()); - { - int start = 44100 * 60; - Selection p(start, start + 44100 * 60, 0, 0); // one minute selection - selections_preview.add(p); - } + //{ + // int start = 44100 * 60; + // Range p(start, start + 44100 * 60, 0, 0); // one minute range + // ranges_preview.add(p); + //} QWidget* central = new QWidget(); QHBoxLayout* lh = new QHBoxLayout(); @@ -92,32 +94,66 @@ InstrumentWidget::InstrumentWidget(Settings& settings, Instrument& instrument) QToolBar* toolbar = addToolBar(tr("Tools")); listen = new CanvasToolListen(canvaswidget->canvas, player); addTool(toolbar, canvaswidget->canvas, listen); - threshold = new CanvasToolThreshold(canvaswidget->canvas, instrument); + + threshold = new CanvasToolThreshold(*canvaswidget->canvas, + instrument.getThreshold(), + QColor(255, 127, 127), + QColor(180, 0, 0)); + + pos_threshold = new CanvasToolThreshold(*canvaswidget->canvas, + instrument.getPositionThreshold(), + QColor(127, 127, 255), + QColor(0, 0, 180)); + canvaswidget->canvas->tools.push_back(threshold); - tool_selections = new CanvasToolSelections(canvaswidget->canvas, selections, - selections_preview); - connect(threshold, SIGNAL(thresholdChanged(double)), - tool_selections, SLOT(thresholdChanged(double))); + canvaswidget->canvas->tools.push_back(pos_threshold); + + tool_ranges = new CanvasToolRanges(instrument, + canvaswidget->canvas, ranges, + ranges_preview); + + tool_position = new CanvasToolPosition(instrument, + *canvaswidget->canvas, ranges, + ranges_preview); + + connect(&instrument, SIGNAL(rangesChanged()), + tool_position, SLOT(rangesChanged())); + + connect(&instrument, SIGNAL(thresholdChanged()), + tool_ranges, SLOT(autoCreateRangesPreview())); + + connect(&instrument, SIGNAL(positionThresholdChanged()), + tool_ranges, SLOT(autoCreateRangesPreview())); + connect(threshold, SIGNAL(thresholdChanging(double)), - tool_selections, SLOT(thresholdChanged(double))); - connect(&selections, SIGNAL(activeChanged(sel_id_t)), + &instrument, SLOT(setThreshold(double))); + connect(threshold, SIGNAL(thresholdChanged(double)), + &instrument, SLOT(setThreshold(double))); + + connect(pos_threshold, SIGNAL(thresholdChanging(double)), + &instrument, SLOT(setPositionThreshold(double))); + connect(pos_threshold, SIGNAL(thresholdChanged(double)), + &instrument, SLOT(setPositionThreshold(double))); + + connect(&ranges, SIGNAL(activeChanged(sel_id_t)), canvaswidget->canvas, SLOT(update())); - connect(&selections, SIGNAL(updated(sel_id_t)), + connect(&ranges, SIGNAL(updated(sel_id_t)), canvaswidget->canvas, SLOT(update())); - addTool(toolbar, canvaswidget->canvas, tool_selections); - - sorter = new SampleSorter(selections, selections_preview, instrument); - 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)), + addTool(toolbar, canvaswidget->canvas, tool_ranges); + addTool(toolbar, canvaswidget->canvas, tool_position); + + sorter = new SampleSorter(ranges, ranges_preview, instrument); + connect(&ranges, SIGNAL(added(sel_id_t)), + sorter, SLOT(addRange(sel_id_t))); + connect(&ranges_preview, SIGNAL(added(sel_id_t)), + sorter, SLOT(addRangePreview(sel_id_t))); + connect(&ranges, SIGNAL(updated(sel_id_t)), sorter, SLOT(relayout())); + connect(&ranges_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)), + connect(&ranges, SIGNAL(removed(sel_id_t)), sorter, SLOT(relayout())); + connect(&ranges_preview, SIGNAL(removed(sel_id_t)), sorter, SLOT(relayout())); - connect(&selections, SIGNAL(activeChanged(sel_id_t)), + connect(&ranges, SIGNAL(activeChanged(sel_id_t)), sorter, SLOT(relayout())); QPushButton* btn_playsamples = new QPushButton(tr("Play samples")); @@ -142,11 +178,11 @@ InstrumentWidget::InstrumentWidget(Settings& settings, Instrument& instrument) dockWidget->widget()->setLayout(new QVBoxLayout()); tabs = new QTabWidget(this); - tabs->setMinimumWidth(350); + tabs->setMinimumWidth(416); tabs->addTab(createFilesTab(), tr("Files")); generateTabId = tabs->addTab(createGenerateTab(), tr("Generate")); tabs->addTab(createEditTab(), tr("Edit")); - //tabs->addTab(createExportTab(), tr("Export")); + tabs->addTab(createExportTab(), tr("Export")); connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); tabChanged(tabs->currentIndex()); @@ -168,8 +204,9 @@ InstrumentWidget::InstrumentWidget(Settings& settings, Instrument& instrument) canvaswidget->xscale->setValue(0); canvaswidget->xoffset->setValue(0); - // Update selections according to threshold - tool_selections->thresholdChanged(instrument.getThreshold()); + // Update ranges according to threshold +// tool_ranges->thresholdChanged(instrument.getThreshold()); + recalcPositions(); } InstrumentWidget::~InstrumentWidget() @@ -178,10 +215,12 @@ InstrumentWidget::~InstrumentWidget() void InstrumentWidget::tabChanged(int tabid) { - tool_selections->setShowPreview(tabid == generateTabId); + tool_ranges->setShowPreview(tabid == generateTabId); + tool_position->setShowPreview(tabid == generateTabId); sorter->setShowPreview(tabid == generateTabId); - tool_selections->autoCreateSelectionsPreview(); + tool_ranges->autoCreateRangesPreview(); threshold->setActive(tabid == generateTabId); + pos_threshold->setActive(tabid == generateTabId); // TODO && current waveform is pos } QWidget* InstrumentWidget::createFilesTab() @@ -198,6 +237,8 @@ QWidget* InstrumentWidget::createFilesTab() filelist = new FileList(instrument); connect(filelist, SIGNAL(masterFileChanged(QString)), this, SLOT(loadFile(QString))); + connect(filelist, SIGNAL(positionFilesChanged()), + this, SLOT(recalcPositions())); connect(loadbtn, SIGNAL(clicked()), filelist, SLOT(addFiles())); l->addWidget(filelist); @@ -211,26 +252,26 @@ QWidget* InstrumentWidget::createFilesTab() QWidget* InstrumentWidget::createEditTab() { - selections = instrument.getSelections(); - SelectionEditor* se = new SelectionEditor(selections, instrument); + ranges = instrument.getRanges(); + RangeEditor* se = new RangeEditor(ranges, instrument); - 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)), + connect(&ranges, SIGNAL(added(sel_id_t)), se, SLOT(added(sel_id_t))); + connect(&ranges, SIGNAL(updated(sel_id_t)), se, SLOT(updated(sel_id_t))); + connect(&ranges, SIGNAL(removed(sel_id_t)), se, SLOT(removed(sel_id_t))); + connect(&ranges, SIGNAL(activeChanged(sel_id_t)), se, SLOT(activeChanged(sel_id_t))); - connect(&selections, SIGNAL(added(sel_id_t)), this, SLOT(selectionChanged())); - connect(&selections, SIGNAL(updated(sel_id_t)), this, SLOT(selectionChanged())); - connect(&selections, SIGNAL(removed(sel_id_t)), this, SLOT(selectionChanged())); - connect(&selections, SIGNAL(activeChanged(sel_id_t)), this, SLOT(selectionChanged())); + connect(&ranges, SIGNAL(added(sel_id_t)), this, SLOT(rangeChanged())); + connect(&ranges, SIGNAL(updated(sel_id_t)), this, SLOT(rangeChanged())); + connect(&ranges, SIGNAL(removed(sel_id_t)), this, SLOT(rangeChanged())); + connect(&ranges, SIGNAL(activeChanged(sel_id_t)), this, SLOT(rangeChanged())); return se; } -void InstrumentWidget::selectionChanged() +void InstrumentWidget::rangeChanged() { - instrument.setSelections(selections); + instrument.setRanges(ranges); } static QSlider* createAttribute(QWidget* parent, QString name, @@ -271,19 +312,14 @@ QWidget* InstrumentWidget::createGenerateTab() QPushButton* autosel = new QPushButton(); autosel->setText(tr("Generate")); connect(autosel, SIGNAL(clicked()), - tool_selections, SLOT(clearSelections())); + tool_ranges, SLOT(clearRanges())); 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())); + tool_ranges, SLOT(autoCreateRanges())); QPushButton* clearsel = new QPushButton(); clearsel->setText(tr("Clear")); connect(clearsel, SIGNAL(clicked()), - tool_selections, SLOT(clearSelections())); + tool_ranges, SLOT(clearRanges())); btns->addWidget(autosel); btns->addWidget(clearsel); @@ -294,7 +330,7 @@ QWidget* InstrumentWidget::createGenerateTab() connect(slider_attacklength, SIGNAL(valueChanged(int)), sorter, SLOT(setAttackLength(int))); connect(slider_attacklength, SIGNAL(valueChanged(int)), - tool_selections, SLOT(autoCreateSelectionsPreview())); + tool_ranges, SLOT(autoCreateRangesPreview())); slider_attacklength->setValue(instrument.getAttackLength()); connect(slider_attacklength, SIGNAL(valueChanged(int)), this, SLOT(generateSlidersChanged())); @@ -303,34 +339,34 @@ QWidget* InstrumentWidget::createGenerateTab() connect(slider_spread, SIGNAL(valueChanged(int)), sorter, SLOT(setSpreadFactor(int))); connect(slider_spread, SIGNAL(valueChanged(int)), - tool_selections, SLOT(autoCreateSelectionsPreview())); + tool_ranges, SLOT(autoCreateRangesPreview())); slider_spread->setValue(instrument.getPowerSpread()); connect(slider_spread, SIGNAL(valueChanged(int)), this, SLOT(generateSlidersChanged())); slider_hold = createAttribute(w, tr("Minimum size (samples):"), 0, 200000); connect(slider_hold, SIGNAL(valueChanged(int)), - tool_selections, SLOT(holdChanged(int))); + tool_ranges, SLOT(holdChanged(int))); connect(slider_hold, SIGNAL(valueChanged(int)), - tool_selections, SLOT(autoCreateSelectionsPreview())); + tool_ranges, SLOT(autoCreateRangesPreview())); slider_hold->setValue(instrument.getMinimumSize()); connect(slider_hold, SIGNAL(valueChanged(int)), this, SLOT(generateSlidersChanged())); slider_falloff = createAttribute(w, tr("Falloff:"), 10, 5000); connect(slider_falloff, SIGNAL(valueChanged(int)), - tool_selections, SLOT(noiseFloorChanged(int))); + tool_ranges, SLOT(noiseFloorChanged(int))); connect(slider_falloff, SIGNAL(valueChanged(int)), - tool_selections, SLOT(autoCreateSelectionsPreview())); + tool_ranges, SLOT(autoCreateRangesPreview())); slider_falloff->setValue(instrument.getFalloff()); connect(slider_falloff, SIGNAL(valueChanged(int)), this, SLOT(generateSlidersChanged())); slider_fadelength = createAttribute(w, tr("Fadelength:"), 0, 2000); connect(slider_fadelength, SIGNAL(valueChanged(int)), - tool_selections, SLOT(fadeoutChanged(int))); + tool_ranges, SLOT(fadeoutChanged(int))); connect(slider_fadelength, SIGNAL(valueChanged(int)), - tool_selections, SLOT(autoCreateSelectionsPreview())); + tool_ranges, SLOT(autoCreateRangesPreview())); slider_fadelength->setValue(instrument.getFadeLength()); connect(slider_fadelength, SIGNAL(valueChanged(int)), this, SLOT(generateSlidersChanged())); @@ -362,7 +398,7 @@ QWidget* InstrumentWidget::createExportTab() connect(prefix, SIGNAL(textChanged(const QString &)), this, SLOT(prefixChanged())); l->addWidget(prefix); - +/* l->addWidget(new QLabel(tr("Export path:"))); QHBoxLayout* lo_exportp = new QHBoxLayout(); lineed_exportp = new QLineEdit(); @@ -386,7 +422,7 @@ QWidget* InstrumentWidget::createExportTab() connect(extractor, SIGNAL(setMaximumProgress(int)), bar, SLOT(setMaximum(int))); l->addWidget(bar); - +*/ l->addStretch(); return w; @@ -404,10 +440,10 @@ void InstrumentWidget::exportPathChanged() void InstrumentWidget::playSamples() { - Selections* sels = &selections; + Ranges* sels = &ranges; if(tabs->currentIndex() == generateTabId) { - sels = &selections_preview; + sels = &ranges_preview; } QVector<sel_id_t> ids = sels->ids(); @@ -415,8 +451,8 @@ void InstrumentWidget::playSamples() { for(int v2 = 0; v2 < ids.size(); v2++) { - Selection sel1 = sels->get(ids[v1]); - Selection sel2 = sels->get(ids[v2]); + Range sel1 = sels->get(ids[v1]); + Range sel2 = sels->get(ids[v2]); if(sel1.energy < sel2.energy) { @@ -430,7 +466,7 @@ void InstrumentWidget::playSamples() QVector<sel_id_t>::iterator i = ids.begin(); while(i != ids.end()) { - Selection sel = sels->get(*i); + Range sel = sels->get(*i); unsigned int length = sb_playsamples->value() * 44100 / 1000; @@ -448,7 +484,7 @@ void InstrumentWidget::playSamples() connect(&player, SIGNAL(positionUpdate(size_t)), listen, SLOT(update(size_t))); - player.playSelection(sel, to - sel.from); + player.playRange(sel, to - sel.from); QTime t; t.start(); while(t.elapsed() < sb_playsamples->value()) @@ -466,7 +502,7 @@ void InstrumentWidget::playSamples() void InstrumentWidget::doExport() { - extractor->exportSelections(); + extractor->exportRanges(); } void InstrumentWidget::loadFile(QString filename) @@ -475,8 +511,8 @@ void InstrumentWidget::loadFile(QString filename) statusBar()->showMessage(tr("Loading...")); qApp->processEvents(); - sorter->setWavData(NULL, 0); - player.setPcmData(NULL, 0, 0); + sorter->setWavData(nullptr, 0); + player.setPcmData(nullptr, 0, 0); canvaswidget->canvas->load(filename); @@ -489,6 +525,103 @@ void InstrumentWidget::loadFile(QString filename) instrument.setMasterFile(filename); } +void InstrumentWidget::recalcPositions() +{ + size_t cnt{0}; + QString file[2]; + for(auto audioFileIdx : instrument.getAudioFileList()) + { + auto& audioFile = instrument.getAudioFile(audioFileIdx); + if(audioFile.getPositionChannel()) + { + file[cnt] = audioFile.getAbsoluteFile(); + cnt++; + } + + if(cnt == 2) + { + break; + } + } + + if(cnt != 2) + { + return; // we need precisely two position files for this to work + } + + //TODO: Load pos files and set data on sample sorter + { + SF_INFO sf_info; + SNDFILE *fh = sf_open(file[0].toStdString().c_str(), SFM_READ, &sf_info); + if(!fh) + { + printf("Load error '%s'\n", file[0].toStdString().c_str()); + // Just clear the canvas + return; + } + + positionSize1 = sf_info.frames; + if(positionData1) + { + delete[] positionData1; + } + positionData1 = new float[positionSize1]; + + sf_read_float(fh, positionData1, positionSize1); + + sf_close(fh); + } + + { + SF_INFO sf_info; + SNDFILE *fh = sf_open(file[1].toStdString().c_str(), SFM_READ, &sf_info); + if(!fh) + { + printf("Load error '%s'\n", file[1].toStdString().c_str()); + // Just clear the canvas + return; + } + + positionSize2 = sf_info.frames; + if(positionData2) + { + delete[] positionData2; + } + positionData2 = new float[positionSize2]; + + sf_read_float(fh, positionData2, positionSize2); + + sf_close(fh); + } + +#if 0 + // Lowpass filter with runnig avarage + float p = 0.999; + { + float running{0}; + for(int i = 0; i < positionSize1; ++i) + { + running = running * (1.0f - p) + positionData1[i] * p; + positionData1[i] = running; + } + } + + { + float running{0}; + for(int i = 0; i < positionSize2; ++i) + { + running = running * (1.0f - p) + positionData2[i] * p; + positionData2[i] = running; + } + } +#endif + + sorter->setPositionData(positionData1, positionSize1, + positionData2, positionSize2); + tool_ranges->setPositionData(positionData1, positionSize1, + positionData2, positionSize2); +} + void InstrumentWidget::browse() { QString path = diff --git a/src/instrumentwidget.h b/src/instrumentwidget.h index 721b829..d3678d2 100644 --- a/src/instrumentwidget.h +++ b/src/instrumentwidget.h @@ -38,10 +38,11 @@ #include "audioextractor.h" #include "samplesorter.h" #include "filelist.h" -#include "canvastoolselections.h" +#include "canvastoolranges.h" +#include "canvastoolposition.h" #include "canvastoolthreshold.h" #include "canvastoollisten.h" -#include "selection.h" +#include "range.h" #include "player.h" #include "zoomslider.h" #include "canvaswidget.h" @@ -70,11 +71,12 @@ public: public slots: void doExport(); void loadFile(QString filename); + void recalcPositions(); void playSamples(); void browse(); void tabChanged(int tabid); void generateSlidersChanged(); - void selectionChanged(); + void rangeChanged(); void prefixChanged(); void exportPathChanged(); @@ -87,8 +89,10 @@ private: int generateTabId; SampleSorter* sorter; - CanvasToolSelections* tool_selections; + CanvasToolRanges* tool_ranges; + CanvasToolPosition* tool_position; CanvasToolThreshold* threshold; + CanvasToolThreshold* pos_threshold; CanvasToolListen* listen; AudioExtractor* extractor; FileList* filelist; @@ -108,10 +112,16 @@ private: QTabWidget* tabs; // Session state information: - Selections selections; - Selections selections_preview; + Ranges ranges; + Ranges ranges_preview; Player player; Settings& settings; Instrument& instrument; + + // TODO: These should not be stored here... + float* positionData1{nullptr}; + size_t positionSize1{0}; + float* positionData2{nullptr}; + size_t positionSize2{0}; }; diff --git a/src/player.cc b/src/player.cc index d598d9f..a3eeaa2 100644 --- a/src/player.cc +++ b/src/player.cc @@ -38,7 +38,7 @@ Player::Player() pcm_data = NULL; pcm_size = 0; end = 0; - new_selection = false; + new_range = false; connect(&report_timer, SIGNAL(timeout()), this, SLOT(reportTimeout())); report_timer.start(50); // Update 25 times per second @@ -55,7 +55,7 @@ Player::~Player() #define _MIN(a, b) (a<b?a:b) void Player::run() { - Selection sel; + Range sel; static int init = 0; if(init == 0) @@ -79,14 +79,14 @@ void Player::run() while(running) { { - // Check for new Selection. + // Check for new Range. QMutexLocker lock(&mutex); - if(new_selection) + if(new_range) { - sel = selection; + sel = range; pos = sel.from; end = sel_end; - new_selection = false; + new_range = false; } } @@ -134,18 +134,18 @@ void Player::run() } } -bool Player::playSelectionDone() +bool Player::playRangeDone() { - return pos >= sel_end || pos >= selection.to; + return pos >= sel_end || pos >= range.to; } -void Player::playSelection(Selection s, int len) +void Player::playRange(Range s, int len) { { - // Enqueue new Selection for player consumation + // Enqueue new Range for player consumation QMutexLocker lock(&mutex); - selection = s; + range = s; if(len > 0) { @@ -153,16 +153,16 @@ void Player::playSelection(Selection s, int len) } else { - sel_end = selection.to - selection.from; + sel_end = range.to - range.from; } - sel_end += selection.from; + sel_end += range.from; - new_selection = true; + new_range = true; } - // Wait until player actually consumed the new Selection. - while(new_selection) + // Wait until player actually consumed the new Range. + while(new_range) { msleep(1); } @@ -197,20 +197,20 @@ void Player::setPcmData(float* data, size_t size, double samplerate) void Player::setPosition(size_t position) { - Selection s; + Range s; s.from = position; s.to = pcm_size; s.fadein = 0; s.fadeout = 0; - playSelection(s); + playRange(s); } void Player::stop() { - Selection s; + Range s; s.from = 0; s.to = 0; s.fadein = 0; s.fadeout = 0; - playSelection(s, pos); + playRange(s, pos); } diff --git a/src/player.h b/src/player.h index 0f5b780..9bc03b7 100644 --- a/src/player.h +++ b/src/player.h @@ -32,7 +32,7 @@ #include <ao/ao.h> -#include "selection.h" +#include "range.h" class Player : public QThread @@ -67,12 +67,12 @@ public slots: //! Set player position as sample offset. void setPosition(size_t position); - //! Play range based on selection including fade-in/out. + //! Play range based on range including fade-in/out. //! \param length Stop playing after length samples. -1 means play all. - void playSelection(Selection selection, int length = -1); + void playRange(Range range, int length = -1); - //! Return true if last selection is done playing. - bool playSelectionDone(); + //! Return true if last range is done playing. + bool playRangeDone(); //! Stop playing void stop(); @@ -105,7 +105,7 @@ private: bool running; QMutex mutex; - volatile bool new_selection; + volatile bool new_range; size_t sel_end; - Selection selection; + Range range; }; diff --git a/src/project.cc b/src/project.cc index 9cac537..bc96e07 100644 --- a/src/project.cc +++ b/src/project.cc @@ -127,8 +127,27 @@ void AudioFile::setMainChannel(bool main_channel) } } +bool AudioFile::getPositionChannel() const +{ + return pos_channel; +} + +void AudioFile::setPositionChannel(bool pos_channel) +{ + if(this->pos_channel == pos_channel) + { + return; + } + + { + Project::RAIIBulkUpdate bulkUpdate(instrument.getProject()); + this->pos_channel = pos_channel; + } +} + Instrument::Instrument(Project& project, int id) - : id(id) + : QObject(nullptr) + , id(id) , project(project) { } @@ -317,12 +336,12 @@ void Instrument::setFadeLength(std::size_t fade_length) } } -float Instrument::getThreshold() const +double Instrument::getThreshold() const { return threshold; } -void Instrument::setThreshold(float threshold) +void Instrument::setThreshold(double threshold) { if(this->threshold == threshold) { @@ -333,19 +352,42 @@ void Instrument::setThreshold(float threshold) Project::RAIIBulkUpdate bulkUpdate(project); this->threshold = threshold; } + + emit thresholdChanged(); } -Selections Instrument::getSelections() const +double Instrument::getPositionThreshold() const { - return selections; + return position_threshold; } -void Instrument::setSelections(const Selections& selections) +void Instrument::setPositionThreshold(double position_threshold) { + std::cout << __PRETTY_FUNCTION__ << std::endl; + std::cout << position_threshold << std::endl; + if(this->position_threshold == position_threshold) + { + return; + } + { Project::RAIIBulkUpdate bulkUpdate(project); - this->selections = selections; + this->position_threshold = position_threshold; } + + emit positionThresholdChanged(); +} + +Ranges Instrument::getRanges() const +{ + return ranges; +} + +void Instrument::setRanges(const Ranges& ranges) +{ + Project::RAIIBulkUpdate bulkUpdate(project); + this->ranges = ranges; + emit rangesChanged(); } QString Instrument::getPrefix() const diff --git a/src/project.h b/src/project.h index 3e2b886..bbc7771 100644 --- a/src/project.h +++ b/src/project.h @@ -26,13 +26,14 @@ */ #pragma once -#include <list> +#include "audioextractor.h" +#include "range.h" #include <QObject> #include <QString> -#include "audioextractor.h" -#include "selection.h" +#include <list> +#include <array> class Project; class Instrument; @@ -57,6 +58,9 @@ public: bool getMainChannel() const; void setMainChannel(bool main); + bool getPositionChannel() const; + void setPositionChannel(bool pos); + private: friend class ProjectSerialiser; @@ -64,15 +68,19 @@ private: QString name; int channel_map_id; bool main_channel; + bool pos_channel{false}; int id; Instrument& instrument; }; class Instrument + : public QObject { + Q_OBJECT public: Instrument(Project& project, int id); + virtual ~Instrument() = default; int getId() const; @@ -102,17 +110,26 @@ public: std::size_t getFadeLength() const; void setFadeLength(std::size_t fade_length); - float getThreshold() const; - void setThreshold(float threshold); + double getThreshold() const; + double getPositionThreshold() const; - Selections getSelections() const; - void setSelections(const Selections& selectios); + Ranges getRanges() const; + void setRanges(const Ranges& ranges); QString getPrefix() const; void setPrefix(const QString& prefix); Project& getProject(); +public slots: + void setThreshold(double threshold); + void setPositionThreshold(double threshold); + +signals: + void thresholdChanged(); + void positionThresholdChanged(); + void rangesChanged(); + private: friend class ProjectSerialiser; @@ -131,10 +148,11 @@ private: std::size_t fade_length{666}; // Canvas - float threshold{0.5f}; + double threshold{0.1}; + double position_threshold{0.1f}; // Edit tab - Selections selections; + Ranges ranges; // Export tab QString prefix; diff --git a/src/projectrenderer.cc b/src/projectrenderer.cc index 62d646e..a8e805b 100644 --- a/src/projectrenderer.cc +++ b/src/projectrenderer.cc @@ -85,8 +85,8 @@ void ProjectRenderer::render() instrument.getInstrumentName()); { - auto selections = instrument.getSelections().ids(); - emit progressRenderStart(selections.count()); + auto ranges = instrument.getRanges().ids(); + emit progressRenderStart(ranges.count()); qApp->processEvents(); } @@ -94,7 +94,7 @@ void ProjectRenderer::render() connect(&extractor, SIGNAL(progressUpdate(int)), this, SIGNAL(progressRenderTask(int))); - if(!extractor.exportSelections()) + if(!extractor.exportRanges()) { emit progressFinished(1); qApp->processEvents(); diff --git a/src/projectserialiser.cc b/src/projectserialiser.cc index 6a204eb..8d9d824 100644 --- a/src/projectserialiser.cc +++ b/src/projectserialiser.cc @@ -188,15 +188,16 @@ QString ProjectSerialiser::serialise(const Project& project) file.setAttribute("channel_map_id", audiofile.getChannelMapId()); file.setAttribute("master", i.master_file == audiofile.getAbsoluteFile()); file.setAttribute("main", audiofile.getMainChannel() ? "true" : "false"); + file.setAttribute("pos", audiofile.getPositionChannel() ? "true" : "false"); file_list.appendChild(file); } auto regions = doc.createElement("regions"); - regions.setAttribute("nextid", i.selections.nextid); - regions.setAttribute("act", i.selections.act); + regions.setAttribute("nextid", i.ranges.nextid); + regions.setAttribute("act", i.ranges.act); instrument.appendChild(regions); - for(auto r = i.selections.sels.begin(); r != i.selections.sels.end(); ++r) + for(auto r = i.ranges.sels.begin(); r != i.ranges.sels.end(); ++r) { auto region = doc.createElement("region"); region.setAttribute("id", (int)r.key()); @@ -205,6 +206,7 @@ QString ProjectSerialiser::serialise(const Project& project) region.setAttribute("fadein", (int)r.value().fadein); region.setAttribute("fadeout", (int)r.value().fadeout); region.setAttribute("energy", r.value().energy); + region.setAttribute("position", r.value().position); region.setAttribute("name", r.value().name); regions.appendChild(region); } @@ -257,7 +259,7 @@ bool ProjectSerialiser::deserialise(const QString& data, Project& project) for(auto& instrument : instruments) { auto id = instrument["id"].toInt(); - project.instruments.emplace_back(Instrument(project, id)); + project.instruments.emplace_back(project, id); auto& instr = project.instruments.back(); instr.instrument_name = instrument("instrument_name").text(); @@ -273,6 +275,7 @@ bool ProjectSerialiser::deserialise(const QString& data, Project& project) audiofile.name = file["name"]; audiofile.channel_map_id = file["channel_map_id"].toInt(); audiofile.main_channel = file["main"] == "true"; + audiofile.pos_channel = file["pos"] == "true"; if(file["master"] == "1") { @@ -292,20 +295,21 @@ bool ProjectSerialiser::deserialise(const QString& data, Project& project) instr.prefix = instrument("prefix").text(); - auto selections = instrument("regions"); - instr.selections.nextid = selections["nextid"].toInt(); - instr.selections.act = selections["act"].toInt(); + auto ranges = instrument("regions"); + instr.ranges.nextid = ranges["nextid"].toInt(); + instr.ranges.act = ranges["act"].toInt(); - for(auto& selection : selections.children()) + for(auto& range : ranges.children()) { - Selection s; - s.from = selection["from"].toInt(); - s.to = selection["to"].toInt(); - s.fadein = selection["fadein"].toInt(); - s.fadeout = selection["fadeout"].toInt(); - s.energy = selection["energy"].toFloat(); - s.name = selection["name"]; - instr.selections.sels[selection["id"].toInt()] = s; + Range s; + s.from = range["from"].toInt(); + s.to = range["to"].toInt(); + s.fadein = range["fadein"].toInt(); + s.fadeout = range["fadeout"].toInt(); + s.energy = range["energy"].toFloat(); + s.position = range["position"].toFloat(); + s.name = range["name"]; + instr.ranges.sels[range["id"].toInt()] = s; } } diff --git a/src/selection.cc b/src/range.cc index e18e485..980a8ae 100644 --- a/src/selection.cc +++ b/src/range.cc @@ -1,6 +1,6 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** - * selection.cc + * range.cc * * Mon Apr 14 10:13:21 CEST 2014 * Copyright 2014 Bent Bisballe Nyeng @@ -24,50 +24,50 @@ * 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" +#include "range.h" -Selections::Selections() +Ranges::Ranges() : QObject(NULL) { nextid = 0; act = SEL_NONE; } -Selections::Selections(const Selections& other) +Ranges::Ranges(const Ranges& other) { *this = other; } -void Selections::operator=(const Selections& other) +void Ranges::operator=(const Ranges& other) { sels = other.sels; nextid = other.nextid; act = other.act; } -sel_id_t Selections::add(Selection selection) +sel_id_t Ranges::add(Range range) { sel_id_t id = nextid++; - sels[id] = selection; + sels[id] = range; added(id); return id; } -Selection Selections::get(sel_id_t id) +Range& Ranges::get(sel_id_t id) { if(sels.find(id) == sels.end()) { - Selection s(0,0,0,0); + static Range s{}; return s; } return sels[id]; } -QVector<sel_id_t> Selections::ids() +QVector<sel_id_t> Ranges::ids() { QVector<sel_id_t> v; - QMap<sel_id_t, Selection>::iterator i = sels.begin(); + QMap<sel_id_t, Range>::iterator i = sels.begin(); while(i != sels.end()) { v.push_back(i.key()); @@ -77,16 +77,16 @@ QVector<sel_id_t> Selections::ids() return v; } -void Selections::update(sel_id_t id, Selection selection) +void Ranges::update(sel_id_t id, Range range) { if(sels.find(id) != sels.end()) { - sels[id] = selection; + sels[id] = range; emit updated(id); } } -void Selections::remove(sel_id_t id) +void Ranges::remove(sel_id_t id) { if(sels.find(id) != sels.end()) { @@ -99,7 +99,7 @@ void Selections::remove(sel_id_t id) } } -void Selections::clear() +void Ranges::clear() { QVector<sel_id_t> _ids = ids(); QVector<sel_id_t>::iterator i = _ids.begin(); @@ -110,7 +110,7 @@ void Selections::clear() } } -void Selections::setActive(sel_id_t id) +void Ranges::setActive(sel_id_t id) { if(sels.find(id) != sels.end()) { @@ -123,7 +123,7 @@ void Selections::setActive(sel_id_t id) emit activeChanged(act); } -sel_id_t Selections::active() +sel_id_t Ranges::active() { return act; } diff --git a/src/selection.h b/src/range.h index 338b381..36782dc 100644 --- a/src/selection.h +++ b/src/range.h @@ -1,6 +1,6 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** - * selection.h + * range.h * * Sat Nov 21 13:20:46 CET 2009 * Copyright 2009 Bent Bisballe Nyeng @@ -31,85 +31,81 @@ #include <QMap> #include <QVector> -class Selection +struct Range { -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; + size_t from{}; + size_t to{}; + size_t fadein{}; + size_t fadeout{}; + + size_t pos1{}; + size_t pos2{}; + + double energy{}; + double position{}; QString name; }; -typedef int sel_id_t; -#define SEL_NONE -1 +using sel_id_t = int; +static constexpr sel_id_t SEL_NONE = -1; -class Selections +class Ranges : public QObject { Q_OBJECT public: - Selections(); - Selections(const Selections&); + Ranges(); + Ranges(const Ranges&); - void operator=(const Selections& other); + void operator=(const Ranges& other); - //! 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); + //! Add a new range object. The new id is returned. + //! Adding a new ranges will emit an added signal with the new id. + sel_id_t add(Range range); - //! Get a stack copy of a specific selection object, by id. - //! NOTE: If id does not exist an empty selection (from = to = 0) is + //! Get a stack copy of a specific range object, by id. + //! NOTE: If id does not exist an empty range (from = to = 0) is //! returned. - Selection get(sel_id_t id); + Range& get(sel_id_t id); //! Return vector (unsorted) of all ids in the object. QVector<sel_id_t> ids(); - //! Set active selection (to be rendered yellow) + //! Set active range (to be rendered yellow) void setActive(sel_id_t id); - //! Get active selection id. + //! Get active range 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); + //! Update a range by id. + //! Updating a range will emit a updated signal. + void update(sel_id_t id, Range range); - //! Delete a selection by id. - //! Deleting a selection will emit a deleted signal. + //! Delete a range by id. + //! Deleting a range will emit a deleted signal. void remove(sel_id_t id); - //! Delete all selections + //! Delete all ranges void clear(); signals: - //! This signal is emitted when a new selection has been added. + //! This signal is emitted when a new range has been added. void added(sel_id_t id); - //! This signal is emitted when an existing selection has been updated. + //! This signal is emitted when an existing range has been updated. void updated(sel_id_t id); - //! This signal is emitted when a selection has been removed. + //! This signal is emitted when a range has been removed. void removed(sel_id_t id); - //! The active selection changed. + //! The active range changed. void activeChanged(sel_id_t id); private: friend class ProjectSerialiser; - QMap<sel_id_t, Selection> sels; + QMap<sel_id_t, Range> sels; sel_id_t nextid; sel_id_t act; }; diff --git a/src/selectioneditor.cc b/src/rangeeditor.cc index 417059d..504500d 100644 --- a/src/selectioneditor.cc +++ b/src/rangeeditor.cc @@ -1,6 +1,6 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** - * selectioneditor.cc + * rangeeditor.cc * * Thu Apr 17 17:25:18 CEST 2014 * Copyright 2014 Bent Bisballe Nyeng @@ -24,7 +24,7 @@ * 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 "rangeeditor.h" #include "project.h" @@ -40,7 +40,7 @@ static QLineEdit *createWidget(QString name, QWidget* parent) QLineEdit* edt = new QLineEdit(); QObject::connect(edt, SIGNAL(editingFinished()), - parent, SLOT(updateSelection())); + parent, SLOT(updateRange())); l->addWidget(edt); @@ -49,8 +49,8 @@ static QLineEdit *createWidget(QString name, QWidget* parent) return edt; } -SelectionEditor::SelectionEditor(Selections &s, Instrument& instrument) - : selections(s) +RangeEditor::RangeEditor(Ranges &s, Instrument& instrument) + : ranges(s) , instrument(instrument) { cur = SEL_NONE; @@ -62,44 +62,47 @@ SelectionEditor::SelectionEditor(Selections &s, Instrument& instrument) fadein = createWidget(tr("FadeIn:"), this); fadeout = createWidget(tr("FadeOut:"), this); energy = createWidget(tr("Energy:"), this); + position = createWidget(tr("Position:"), this); name = createWidget(tr("Name:"), this); ((QHBoxLayout*)layout())->addStretch(); } -void SelectionEditor::updateSelection() +void RangeEditor::updateRange() { - Selection sel; + Range 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.position = position->text().toDouble(); sel.name = name->text(); - selections.update(cur, sel); + ranges.update(cur, sel); - instrument.setSelections(selections); + instrument.setRanges(ranges); } -void SelectionEditor::update() +void RangeEditor::update() { - Selection sel = selections.get(cur); + Range sel = ranges.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)); + position->setText(QString::number(sel.position)); name->setText(sel.name); } -void SelectionEditor::added(sel_id_t id) +void RangeEditor::added(sel_id_t id) { // Nothing to do here... } -void SelectionEditor::updated(sel_id_t id) +void RangeEditor::updated(sel_id_t id) { if(cur == id) { @@ -107,7 +110,7 @@ void SelectionEditor::updated(sel_id_t id) } } -void SelectionEditor::removed(sel_id_t id) +void RangeEditor::removed(sel_id_t id) { if(cur == id) { @@ -116,7 +119,7 @@ void SelectionEditor::removed(sel_id_t id) } } -void SelectionEditor::activeChanged(sel_id_t id) +void RangeEditor::activeChanged(sel_id_t id) { cur = id; update(); diff --git a/src/selectioneditor.h b/src/rangeeditor.h index cdbf2de..d37e82c 100644 --- a/src/selectioneditor.h +++ b/src/rangeeditor.h @@ -1,6 +1,6 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** - * selectioneditor.h + * rangeeditor.h * * Thu Apr 17 17:25:17 CEST 2014 * Copyright 2014 Bent Bisballe Nyeng @@ -29,16 +29,16 @@ #include <QWidget> #include <QLineEdit> -#include "selection.h" +#include "range.h" class Instrument; -class SelectionEditor +class RangeEditor : public QWidget { Q_OBJECT public: - SelectionEditor(Selections& selections, Instrument& instrument); + RangeEditor(Ranges& ranges, Instrument& instrument); public slots: void added(sel_id_t id); @@ -48,10 +48,10 @@ public slots: private slots: void update(); - void updateSelection(); + void updateRange(); private: - Selections& selections; + Ranges& ranges; sel_id_t cur; @@ -60,6 +60,7 @@ private: QLineEdit* fadein; QLineEdit* fadeout; QLineEdit* energy; + QLineEdit* position; QLineEdit* name; Instrument& instrument; diff --git a/src/samplesorter.cc b/src/samplesorter.cc index 29c24e6..4e930e4 100644 --- a/src/samplesorter.cc +++ b/src/samplesorter.cc @@ -26,10 +26,13 @@ */ #include "samplesorter.h" +#include "project.h" + #include <QPainter> #include <QPaintEvent> #include <QKeyEvent> +#include <iostream> #include <stdio.h> #include <math.h> @@ -37,9 +40,9 @@ #define MAXFLOAT (3.40282347e+38F) #endif -SampleSorter::SampleSorter(Selections& s, Selections& p, Instrument& instrument) - : selections(s) - , selections_preview(p) +SampleSorter::SampleSorter(Ranges& s, Ranges& p, Instrument& instrument) + : ranges(s) + , ranges_preview(p) , instrument(instrument) { setMouseTracking(true); @@ -66,6 +69,18 @@ void SampleSorter::setWavData(const float* data, size_t size) relayout(); } +void SampleSorter::setPositionData(const float* positionData1, size_t positionSize1, + const float* positionData2, size_t positionSize2) +{ + this->positionData1 = positionData1; + this->positionSize1 = positionSize1; + + this->positionData2 = positionData2; + this->positionSize2 = positionSize2; + + relayout(); +} + int SampleSorter::attackLength() { return attlen; @@ -84,28 +99,152 @@ void SampleSorter::setAttackLength(int len) relayout(); } -void SampleSorter::addSelection(sel_id_t id) +void SampleSorter::addRange(sel_id_t id) { - Selection s = selections.get(id); + auto range = ranges.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); + for(size_t idx = range.from; + (idx < (size_t)range.from + (size_t)attackLength()) && + (idx < (size_t)range.to) && (idx < size); idx++) { energy += data[idx] * data[idx]; } - s.energy = pow(energy, spread); - selections.update(id, s); + range.energy = pow(energy, spread); + +// constexpr int window_size{10}; // TODO: Specify in ms +// +// std::vector<float> corr; +// corr.resize(window_size); +// +// double position = 0.0; +// +// std::cout << "\n\nRange from: " << range.from << "\n"; +// +// +// float max_val1{0}; +// for(int idx = range.from - window_size / 2; idx < range.from + window_size / 2; ++idx) +// { +// if(std::abs(positionData1[idx]) > max_val1) +// { +// max_val1 = std::abs(positionData1[idx]); +// } +// } +// float norm1 = 1.0f / max_val1; +// +// float max_val2{0}; +// for(int idx = range.from - window_size / 2; idx < range.from + window_size / 2; ++idx) +// { +// if(std::abs(positionData2[idx]) > max_val2) +// { +// max_val2 = std::abs(positionData2[idx]); +// } +// } +// float norm2 = 1.0f / max_val2; +// +// +// //constexpr auto lpf_beta = 0.025f; // 0<ß<1 +// constexpr auto lpf_beta = 1.0f; // 0<ß<1 +// +// auto filter1 = +// [lpf_beta](auto in) +// { +// static auto v{0.0f}; +// v = v - (lpf_beta * (v - in)); +// return v; +// }; +// auto filter2 = +// [lpf_beta](auto in) +// { +// static auto v{0.0f}; +// v = v - (lpf_beta * (v - in)); +// return v; +// }; +// +// +//#if 0 // Cross-correlation +// +// if(positionData1 && positionSize1 && +// positionData2 && positionSize2) +// { +// // From: http://eceweb1.rutgers.edu/~gajic/solmanual/slides/chapter9_CORR.pdf +// for(int k = 0; k < window_size; ++k) +// { +// corr[k] = 0.0f; +// for(int m = range.from - window_size / 2; m < range.from + window_size / 2; ++m) +// { +// corr[k] += +// (filter1(positionData1[m] * norm1)) * +// (filter2(positionData2[m - k] * norm2)); +// } +// } +// } +// +// float max_corr{0.0f}; +// for(int idx = 0; idx < corr.size(); ++idx) +// { +// std::cout << idx << ": " << corr[idx] << "\n"; +// if(corr[idx] > max_corr) +// { +// max_corr = corr[idx]; +// position = idx; +// } +// } +// +// std::cout << "Maximum found: " << max_corr << " at idx " << position << "\n"; +// +//#else // Rising edge detection +// +// float threshold = instrument.getPositionThreshold();//{0.003f}; +// int pos_window_size{100}; // +/- 50 from detected, +// // ~40 samples between left/right impirically detected when at edge, same for main mic to each of +// // the piezos +// norm1 = norm2 = 1.0f; +// int pos1{0}; +// for(int idx = range.from - pos_window_size / 2; +// idx < range.from + pos_window_size / 2; +// ++idx) +// { +// if(std::abs(filter1(positionData1[idx])) * norm1 > threshold) +// { +// pos1 = idx; +// range.pos1 = pos1; +// break; +// } +// } +// +// int pos2{0}; +// for(int idx = range.from - pos_window_size / 2; +// idx < range.from + pos_window_size / 2; +// ++idx) +// { +// if(std::abs(filter2(positionData2[idx])) * norm2 > threshold) +// { +// pos2 = idx; +// range.pos2 = pos1; +// break; +// } +// } +// +// position = std::abs(pos1 - pos2); +//#endif +// +// std::cout << "[" << pos1 << " <-> " << pos2 << "]\n"; +// +// constexpr double speed_of_sound{3431000}; // mm/s +// constexpr double samplerate{48000}; // 48kHz - TODO get from audio +// range.position = position * speed_of_sound / samplerate / 2.0; +// + ranges.update(id, range); relayout(); } -void SampleSorter::addSelectionPreview(sel_id_t id) +void SampleSorter::addRangePreview(sel_id_t id) { - Selection s = selections_preview.get(id); + Range s = ranges_preview.get(id); double energy = 0.0; for(size_t idx = s.from; @@ -117,7 +256,7 @@ void SampleSorter::addSelectionPreview(sel_id_t id) } s.energy = pow(energy, spread); - selections_preview.update(id, s); + ranges_preview.update(id, s); relayout(); } @@ -128,11 +267,11 @@ void SampleSorter::relayout() max = 0.0; { - QVector<sel_id_t> ids = selections.ids(); + QVector<sel_id_t> ids = ranges.ids(); QVector<sel_id_t>::iterator i = ids.begin(); while(i != ids.end()) { - Selection sel = selections.get(*i); + Range sel = ranges.get(*i); if(sel.energy < min) { @@ -149,11 +288,11 @@ void SampleSorter::relayout() if(show_preview) { - QVector<sel_id_t> ids = selections_preview.ids(); + QVector<sel_id_t> ids = ranges_preview.ids(); QVector<sel_id_t>::iterator i = ids.begin(); while(i != ids.end()) { - Selection sel = selections_preview.get(*i); + Range sel = ranges_preview.get(*i); if(sel.energy < min) { @@ -203,12 +342,12 @@ void SampleSorter::paintEvent(QPaintEvent* event) { - QVector<sel_id_t> ids = selections.ids(); + QVector<sel_id_t> ids = ranges.ids(); QVector<sel_id_t>::iterator i = ids.begin(); while(i != ids.end()) { - Selection sel = selections.get(*i); - if(*i == selections.active()) + Range sel = ranges.get(*i); + if(*i == ranges.active()) { painter.setPen(colPtSel); } @@ -226,11 +365,11 @@ void SampleSorter::paintEvent(QPaintEvent* event) if(show_preview) { - QVector<sel_id_t> ids = selections_preview.ids(); + QVector<sel_id_t> ids = ranges_preview.ids(); QVector<sel_id_t>::iterator i = ids.begin(); while(i != ids.end()) { - Selection sel = selections_preview.get(*i); + Range sel = ranges_preview.get(*i); painter.setPen(colPtPreview); float x = (sel.energy / max); x = sqrt(x); @@ -243,16 +382,16 @@ void SampleSorter::paintEvent(QPaintEvent* event) } -sel_id_t SampleSorter::getSelectionByCoordinate(int px, int py) +sel_id_t SampleSorter::getRangeByCoordinate(int px, int py) { // Hit radius is slithly larger than the circles themselves. int hit_r = C_RADIUS + 1; - QVector<sel_id_t> ids = selections.ids(); + QVector<sel_id_t> ids = ranges.ids(); QVector<sel_id_t>::iterator i = ids.begin(); while(i != ids.end()) { - Selection sel = selections.get(*i); + Range sel = ranges.get(*i); float x = (sel.energy/max); x = sqrt(x); x *= (float)width() * 0.9; @@ -273,14 +412,14 @@ void SampleSorter::mouseMoveEvent(QMouseEvent* event) { if(sel_moving != SEL_NONE) { - Selection sel = selections.get(sel_moving); + Range sel = ranges.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); + ranges.update(sel_moving, sel); } update(); @@ -288,7 +427,7 @@ void SampleSorter::mouseMoveEvent(QMouseEvent* event) } else { - sel_id_t psel = getSelectionByCoordinate(event->x(), event->y()); + sel_id_t psel = getRangeByCoordinate(event->x(), event->y()); if(psel != SEL_NONE) { setCursor(Qt::OpenHandCursor); @@ -304,9 +443,9 @@ void SampleSorter::mousePressEvent(QMouseEvent* event) { if(event->button() == Qt::LeftButton) { - sel_id_t psel = getSelectionByCoordinate(event->x(), event->y()); + sel_id_t psel = getRangeByCoordinate(event->x(), event->y()); sel_moving = psel; - selections.setActive(psel); + ranges.setActive(psel); if(psel != SEL_NONE) { setCursor(Qt::ClosedHandCursor); @@ -319,7 +458,7 @@ void SampleSorter::mouseReleaseEvent(QMouseEvent* event) if(event->button() == Qt::LeftButton) { sel_moving = SEL_NONE; - sel_id_t psel = getSelectionByCoordinate(event->x(), event->y()); + sel_id_t psel = getRangeByCoordinate(event->x(), event->y()); if(psel != SEL_NONE) { setCursor(Qt::OpenHandCursor); @@ -333,8 +472,8 @@ void SampleSorter::mouseReleaseEvent(QMouseEvent* event) void SampleSorter::keyReleaseEvent(QKeyEvent* event) { - if(selections.active() != SEL_NONE && event->key() == Qt::Key_Delete) + if(ranges.active() != SEL_NONE && event->key() == Qt::Key_Delete) { - selections.remove(selections.active()); + ranges.remove(ranges.active()); } } diff --git a/src/samplesorter.h b/src/samplesorter.h index 056161d..58a784a 100644 --- a/src/samplesorter.h +++ b/src/samplesorter.h @@ -28,7 +28,7 @@ #include <QWidget> #include <QVector> -#include "selection.h" +#include "range.h" class Instrument; @@ -37,16 +37,18 @@ class SampleSorter { Q_OBJECT public: - SampleSorter(Selections& selections, Selections& selections_preview, + SampleSorter(Ranges& ranges, Ranges& ranges_preview, Instrument& instrument); public slots: void setWavData(const float* data, size_t size); + void setPositionData(const float* positionData1, size_t positionSize1, + const float* positionData2, size_t positionSize2); void setAttackLength(int len); int attackLength(); - void addSelection(sel_id_t id); - void addSelectionPreview(sel_id_t id); + void addRange(sel_id_t id); + void addRangePreview(sel_id_t id); void relayout(); @@ -62,10 +64,10 @@ protected: void keyReleaseEvent(QKeyEvent* event) override; private: - sel_id_t getSelectionByCoordinate(int x, int y); + sel_id_t getRangeByCoordinate(int x, int y); - Selections& selections; - Selections& selections_preview; + Ranges& ranges; + Ranges& ranges_preview; bool show_preview; @@ -77,7 +79,13 @@ private: const float* data; size_t size; - Selection sel; + const float* positionData1{nullptr}; + size_t positionSize1{0}; + + const float* positionData2{nullptr}; + size_t positionSize2{0}; + + Range sel; sel_id_t sel_moving; diff --git a/src/ts/dgedit_da.ts b/src/ts/dgedit_da.ts index bda3ba5..62ea715 100644 --- a/src/ts/dgedit_da.ts +++ b/src/ts/dgedit_da.ts @@ -23,17 +23,32 @@ </message> </context> <context> + <name>CanvasToolPosition</name> + <message> + <location filename="../canvastoolposition.h" line="47"/> + <source>Position</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>CanvasToolRanges</name> + <message> + <location filename="../canvastoolranges.h" line="48"/> + <source>Ranges</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>CanvasToolSelections</name> <message> - <location filename="../canvastoolselections.h" line="45"/> <source>Selections</source> - <translation>Markeringer</translation> + <translation type="vanished">Markeringer</translation> </message> </context> <context> <name>CanvasToolThreshold</name> <message> - <location filename="../canvastoolthreshold.h" line="44"/> + <location filename="../canvastoolthreshold.h" line="43"/> <source>Threshold</source> <translation>Grænseværdi</translation> </message> @@ -54,7 +69,7 @@ <context> <name>ChannelMapDeligate</name> <message> - <location filename="../filelist.cc" line="104"/> + <location filename="../filelist.cc" line="481"/> <source><None></source> <translation><Ingen></translation> </message> @@ -62,50 +77,55 @@ <context> <name>FileDataModel</name> <message> - <location filename="../filelist.cc" line="309"/> + <location filename="../filelist.cc" line="147"/> <source><None></source> <translation><Ingen></translation> </message> <message> - <location filename="../filelist.cc" line="341"/> + <location filename="../filelist.cc" line="181"/> <source>M</source> <translation>M</translation> </message> <message> - <location filename="../filelist.cc" line="342"/> + <location filename="../filelist.cc" line="182"/> <source>Filename</source> <translation>Filnavn</translation> </message> <message> - <location filename="../filelist.cc" line="343"/> + <location filename="../filelist.cc" line="183"/> <source>m</source> <translation>m</translation> </message> <message> - <location filename="../filelist.cc" line="344"/> + <location filename="../filelist.cc" line="184"/> <source>Name</source> <translation>Navn</translation> </message> <message> - <location filename="../filelist.cc" line="345"/> + <location filename="../filelist.cc" line="185"/> <source>Kit Channel</source> <translation>Trommesæt kanal</translation> </message> + <message> + <location filename="../filelist.cc" line="186"/> + <source>p</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>FileList</name> <message> - <location filename="../filelist.cc" line="462"/> + <location filename="../filelist.cc" line="307"/> <source>Open file</source> <translation>Åbn fil</translation> </message> <message> - <location filename="../filelist.cc" line="463"/> + <location filename="../filelist.cc" line="308"/> <source>Audio Files (*.wav)</source> <translation>Lyd filer (*.wav)</translation> </message> <message> - <location filename="../filelist.cc" line="530"/> + <location filename="../filelist.cc" line="375"/> <source>Set as Master (dbl-click)</source> <translation>Vælg hovedkanal (dbl klik)</translation> </message> @@ -114,12 +134,12 @@ <translation type="vanished">Redigér navn</translation> </message> <message> - <location filename="../filelist.cc" line="533"/> + <location filename="../filelist.cc" line="378"/> <source>Remove</source> <translation>Fjern</translation> </message> <message> - <location filename="../filelist.cc" line="536"/> + <location filename="../filelist.cc" line="381"/> <source>Remove all</source> <translation>Fjern alle</translation> </message> @@ -140,108 +160,106 @@ <context> <name>InstrumentWidget</name> <message> - <location filename="../instrumentwidget.cc" line="92"/> + <location filename="../instrumentwidget.cc" line="94"/> <source>Tools</source> <translation>Værktøjer</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="123"/> + <location filename="../instrumentwidget.cc" line="159"/> <source>Play samples</source> <translation>Afspil lydbidder</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="137"/> + <location filename="../instrumentwidget.cc" line="173"/> <source>Process</source> <translation>Processér</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="146"/> + <location filename="../instrumentwidget.cc" line="182"/> <source>Files</source> <translation>Filer</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="147"/> - <location filename="../instrumentwidget.cc" line="272"/> + <location filename="../instrumentwidget.cc" line="183"/> + <location filename="../instrumentwidget.cc" line="313"/> <source>Generate</source> <translation>Generér</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="148"/> + <location filename="../instrumentwidget.cc" line="184"/> <source>Edit</source> <translation>Redigér</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="193"/> + <location filename="../instrumentwidget.cc" line="232"/> <source>Files: (double-click to set as master)</source> <translation>Filer: (dobbeltklik for at vælge som hovedkanal)</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="195"/> + <location filename="../instrumentwidget.cc" line="234"/> <source>Add files...</source> <translation>Tilføj filer...</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="284"/> + <location filename="../instrumentwidget.cc" line="320"/> <source>Clear</source> <translation>Ryd</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="293"/> + <location filename="../instrumentwidget.cc" line="329"/> <source>Attack length:</source> <translation>Attack længde:</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="302"/> + <location filename="../instrumentwidget.cc" line="338"/> <source>Power spread:</source> <translation>Energi spredning:</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="311"/> + <location filename="../instrumentwidget.cc" line="347"/> <source>Minimum size (samples):</source> <translation>Minimum størrelse (samples):</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="320"/> + <location filename="../instrumentwidget.cc" line="356"/> <source>Falloff:</source> <translation>Falloff:</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="329"/> + <location filename="../instrumentwidget.cc" line="365"/> <source>Fadelength:</source> <translation>Fadelængde:</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="359"/> + <location filename="../instrumentwidget.cc" line="395"/> <source>Prefix:</source> <translation>Præfix:</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="366"/> <source>Export path:</source> - <translation>Eksporteringssti:</translation> + <translation type="vanished">Eksporteringssti:</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="373"/> <source>...</source> - <translation>...</translation> + <translation type="vanished">...</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="380"/> + <location filename="../instrumentwidget.cc" line="185"/> <source>Export</source> <translation>Eksportér</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="475"/> + <location filename="../instrumentwidget.cc" line="511"/> <source>Loading...</source> <translation>Indlæser...</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="486"/> + <location filename="../instrumentwidget.cc" line="522"/> <source>Ready</source> <translation>Klar</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="495"/> + <location filename="../instrumentwidget.cc" line="628"/> <source>Select export path</source> <translation>Vælg eksporteringssti</translation> </message> @@ -507,6 +525,44 @@ </message> </context> <context> + <name>RangeEditor</name> + <message> + <location filename="../rangeeditor.cc" line="60"/> + <source>From:</source> + <translation type="unfinished">Fra:</translation> + </message> + <message> + <location filename="../rangeeditor.cc" line="61"/> + <source>To:</source> + <translation type="unfinished">Til:</translation> + </message> + <message> + <location filename="../rangeeditor.cc" line="62"/> + <source>FadeIn:</source> + <translation type="unfinished">FadeIn:</translation> + </message> + <message> + <location filename="../rangeeditor.cc" line="63"/> + <source>FadeOut:</source> + <translation type="unfinished">FadeOut:</translation> + </message> + <message> + <location filename="../rangeeditor.cc" line="64"/> + <source>Energy:</source> + <translation type="unfinished">Energi:</translation> + </message> + <message> + <location filename="../rangeeditor.cc" line="65"/> + <source>Position:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../rangeeditor.cc" line="66"/> + <source>Name:</source> + <translation type="unfinished">Navn:</translation> + </message> +</context> +<context> <name>RenderDialog</name> <message> <location filename="../renderdialog.cc" line="280"/> @@ -537,34 +593,28 @@ <context> <name>SelectionEditor</name> <message> - <location filename="../selectioneditor.cc" line="60"/> <source>From:</source> - <translation>Fra:</translation> + <translation type="vanished">Fra:</translation> </message> <message> - <location filename="../selectioneditor.cc" line="61"/> <source>To:</source> - <translation>Til:</translation> + <translation type="vanished">Til:</translation> </message> <message> - <location filename="../selectioneditor.cc" line="62"/> <source>FadeIn:</source> - <translation>FadeIn:</translation> + <translation type="vanished">FadeIn:</translation> </message> <message> - <location filename="../selectioneditor.cc" line="63"/> <source>FadeOut:</source> - <translation>FadeOut:</translation> + <translation type="vanished">FadeOut:</translation> </message> <message> - <location filename="../selectioneditor.cc" line="64"/> <source>Energy:</source> - <translation>Energi:</translation> + <translation type="vanished">Energi:</translation> </message> <message> - <location filename="../selectioneditor.cc" line="65"/> <source>Name:</source> - <translation>Navn:</translation> + <translation type="vanished">Navn:</translation> </message> </context> <context> diff --git a/src/ts/dgedit_fr.ts b/src/ts/dgedit_fr.ts index deb07bd..17fd995 100644 --- a/src/ts/dgedit_fr.ts +++ b/src/ts/dgedit_fr.ts @@ -23,17 +23,32 @@ </message> </context> <context> + <name>CanvasToolPosition</name> + <message> + <location filename="../canvastoolposition.h" line="47"/> + <source>Position</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>CanvasToolRanges</name> + <message> + <location filename="../canvastoolranges.h" line="48"/> + <source>Ranges</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>CanvasToolSelections</name> <message> - <location filename="../canvastoolselections.h" line="45"/> <source>Selections</source> - <translation>Sélections</translation> + <translation type="vanished">Sélections</translation> </message> </context> <context> <name>CanvasToolThreshold</name> <message> - <location filename="../canvastoolthreshold.h" line="44"/> + <location filename="../canvastoolthreshold.h" line="43"/> <source>Threshold</source> <translation>Seuil de déclenchement</translation> </message> @@ -54,7 +69,7 @@ <context> <name>ChannelMapDeligate</name> <message> - <location filename="../filelist.cc" line="104"/> + <location filename="../filelist.cc" line="481"/> <source><None></source> <translation><None></translation> </message> @@ -62,50 +77,55 @@ <context> <name>FileDataModel</name> <message> - <location filename="../filelist.cc" line="309"/> + <location filename="../filelist.cc" line="147"/> <source><None></source> <translation><Aucun></translation> </message> <message> - <location filename="../filelist.cc" line="341"/> + <location filename="../filelist.cc" line="181"/> <source>M</source> <translation>M</translation> </message> <message> - <location filename="../filelist.cc" line="342"/> + <location filename="../filelist.cc" line="182"/> <source>Filename</source> <translation>Nom de fichier</translation> </message> <message> - <location filename="../filelist.cc" line="343"/> + <location filename="../filelist.cc" line="183"/> <source>m</source> <translation>m</translation> </message> <message> - <location filename="../filelist.cc" line="344"/> + <location filename="../filelist.cc" line="184"/> <source>Name</source> <translation>Nom</translation> </message> <message> - <location filename="../filelist.cc" line="345"/> + <location filename="../filelist.cc" line="185"/> <source>Kit Channel</source> <translation>Canal de kit</translation> </message> + <message> + <location filename="../filelist.cc" line="186"/> + <source>p</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>FileList</name> <message> - <location filename="../filelist.cc" line="462"/> + <location filename="../filelist.cc" line="307"/> <source>Open file</source> <translation>Ouvrir un fichier</translation> </message> <message> - <location filename="../filelist.cc" line="463"/> + <location filename="../filelist.cc" line="308"/> <source>Audio Files (*.wav)</source> <translation>Fichiers audio (*.wav)</translation> </message> <message> - <location filename="../filelist.cc" line="530"/> + <location filename="../filelist.cc" line="375"/> <source>Set as Master (dbl-click)</source> <translation>Paramétrer en tant que maître (dbl-clic)</translation> </message> @@ -114,12 +134,12 @@ <translation type="vanished">Éditer le nom</translation> </message> <message> - <location filename="../filelist.cc" line="533"/> + <location filename="../filelist.cc" line="378"/> <source>Remove</source> <translation>Supprimer</translation> </message> <message> - <location filename="../filelist.cc" line="536"/> + <location filename="../filelist.cc" line="381"/> <source>Remove all</source> <translation>Supprimer tout</translation> </message> @@ -140,108 +160,106 @@ <context> <name>InstrumentWidget</name> <message> - <location filename="../instrumentwidget.cc" line="92"/> + <location filename="../instrumentwidget.cc" line="94"/> <source>Tools</source> <translation>Outils</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="123"/> + <location filename="../instrumentwidget.cc" line="159"/> <source>Play samples</source> <translation>Lire les échantillons</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="137"/> + <location filename="../instrumentwidget.cc" line="173"/> <source>Process</source> <translation>Traiter</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="146"/> + <location filename="../instrumentwidget.cc" line="182"/> <source>Files</source> <translation>Fichiers</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="147"/> - <location filename="../instrumentwidget.cc" line="272"/> + <location filename="../instrumentwidget.cc" line="183"/> + <location filename="../instrumentwidget.cc" line="313"/> <source>Generate</source> <translation>Générer</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="148"/> + <location filename="../instrumentwidget.cc" line="184"/> <source>Edit</source> <translation>Éditer</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="193"/> + <location filename="../instrumentwidget.cc" line="232"/> <source>Files: (double-click to set as master)</source> <translation>Fichiers : (double-clic pour paramétrer en tant que maître)</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="195"/> + <location filename="../instrumentwidget.cc" line="234"/> <source>Add files...</source> <translation>Ajouter des fichiers...</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="284"/> + <location filename="../instrumentwidget.cc" line="320"/> <source>Clear</source> <translation>Vider</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="293"/> + <location filename="../instrumentwidget.cc" line="329"/> <source>Attack length:</source> <translation>Longueur d'attaque :</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="302"/> + <location filename="../instrumentwidget.cc" line="338"/> <source>Power spread:</source> <translation>Étalement de la puissance :</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="311"/> + <location filename="../instrumentwidget.cc" line="347"/> <source>Minimum size (samples):</source> <translation>Taille minimum (échantillons) :</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="320"/> + <location filename="../instrumentwidget.cc" line="356"/> <source>Falloff:</source> <translation>Temps de chute :</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="329"/> + <location filename="../instrumentwidget.cc" line="365"/> <source>Fadelength:</source> <translation>Longueur de fondu :</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="359"/> + <location filename="../instrumentwidget.cc" line="395"/> <source>Prefix:</source> <translation>Préfixe :</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="366"/> <source>Export path:</source> - <translation>Chemin d'exportation :</translation> + <translation type="vanished">Chemin d'exportation :</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="373"/> <source>...</source> - <translation>...</translation> + <translation type="vanished">...</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="380"/> + <location filename="../instrumentwidget.cc" line="185"/> <source>Export</source> <translation>Exporter</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="475"/> + <location filename="../instrumentwidget.cc" line="511"/> <source>Loading...</source> <translation>Chargement...</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="486"/> + <location filename="../instrumentwidget.cc" line="522"/> <source>Ready</source> <translation>Prêt</translation> </message> <message> - <location filename="../instrumentwidget.cc" line="495"/> + <location filename="../instrumentwidget.cc" line="628"/> <source>Select export path</source> <translation>Sélectionner le chemin d'exportation</translation> </message> @@ -507,6 +525,44 @@ </message> </context> <context> + <name>RangeEditor</name> + <message> + <location filename="../rangeeditor.cc" line="60"/> + <source>From:</source> + <translation type="unfinished">Depuis :</translation> + </message> + <message> + <location filename="../rangeeditor.cc" line="61"/> + <source>To:</source> + <translation type="unfinished">Jusqu'à :</translation> + </message> + <message> + <location filename="../rangeeditor.cc" line="62"/> + <source>FadeIn:</source> + <translation type="unfinished">Fondu ouverture :</translation> + </message> + <message> + <location filename="../rangeeditor.cc" line="63"/> + <source>FadeOut:</source> + <translation type="unfinished">Fondu fermeture :</translation> + </message> + <message> + <location filename="../rangeeditor.cc" line="64"/> + <source>Energy:</source> + <translation type="unfinished">Énergie :</translation> + </message> + <message> + <location filename="../rangeeditor.cc" line="65"/> + <source>Position:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../rangeeditor.cc" line="66"/> + <source>Name:</source> + <translation type="unfinished">Nom :</translation> + </message> +</context> +<context> <name>RenderDialog</name> <message> <location filename="../renderdialog.cc" line="280"/> @@ -537,34 +593,28 @@ <context> <name>SelectionEditor</name> <message> - <location filename="../selectioneditor.cc" line="60"/> <source>From:</source> - <translation>Depuis :</translation> + <translation type="vanished">Depuis :</translation> </message> <message> - <location filename="../selectioneditor.cc" line="61"/> <source>To:</source> - <translation>Jusqu'à :</translation> + <translation type="vanished">Jusqu'à :</translation> </message> <message> - <location filename="../selectioneditor.cc" line="62"/> <source>FadeIn:</source> - <translation>Fondu ouverture :</translation> + <translation type="vanished">Fondu ouverture :</translation> </message> <message> - <location filename="../selectioneditor.cc" line="63"/> <source>FadeOut:</source> - <translation>Fondu fermeture :</translation> + <translation type="vanished">Fondu fermeture :</translation> </message> <message> - <location filename="../selectioneditor.cc" line="64"/> <source>Energy:</source> - <translation>Énergie :</translation> + <translation type="vanished">Énergie :</translation> </message> <message> - <location filename="../selectioneditor.cc" line="65"/> <source>Name:</source> - <translation>Nom :</translation> + <translation type="vanished">Nom :</translation> </message> </context> <context> @@ -581,4 +631,3 @@ </message> </context> </TS> - |