summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog79
-rw-r--r--RELEASE-CHECKLIST2
-rwxr-xr-xautogen.sh1
-rw-r--r--drumgizmo/drumgizmoc.cc2
-rw-r--r--drumgizmo/input/jackmidi.cc2
-rw-r--r--drumgizmo/input/midifile.h2
-rw-r--r--drumgizmo/input/test.cc1
-rw-r--r--drumgizmo/input/test.h1
-rw-r--r--plugin/Makefile.mingw32.in2
m---------plugin/plugingizmo0
-rw-r--r--plugingui/diskstreamingframecontent.cc4
-rw-r--r--plugingui/locale/da.po2
-rw-r--r--plugingui/locale/drumgizmo.pot2
-rw-r--r--plugingui/locale/fr.po2
-rw-r--r--plugingui/powerwidget.cc3
-rw-r--r--plugingui/powerwidget.h4
-rw-r--r--plugingui/resamplingframecontent.cc8
-rw-r--r--src/Makefile.am89
-rw-r--r--src/atomic.h20
-rw-r--r--src/audio.h2
-rw-r--r--src/audiocache.cc144
-rw-r--r--src/audiocache.h19
-rw-r--r--src/audiocacheeventhandler.cc54
-rw-r--r--src/audiocacheeventhandler.h10
-rw-r--r--src/audiocachefile.cc64
-rw-r--r--src/audiocachefile.h14
-rw-r--r--src/audiocacheidmanager.cc66
-rw-r--r--src/audiocacheidmanager.h47
-rw-r--r--src/audiofile.cc56
-rw-r--r--src/audiofile.h15
-rw-r--r--src/audioinputengine.h2
-rw-r--r--src/audioinputenginemidi.cc42
-rw-r--r--src/audioinputenginemidi.h13
-rw-r--r--src/audiooutputengine.h2
-rw-r--r--src/bytesizeparser.cc37
-rw-r--r--src/bytesizeparser.h2
-rw-r--r--src/configfile.h2
-rw-r--r--src/curvemap.cc (renamed from src/powermap.cc)122
-rw-r--r--src/curvemap.h94
-rw-r--r--src/directory.cc6
-rw-r--r--src/drumgizmo.cc14
-rw-r--r--src/drumgizmo.h4
-rw-r--r--src/drumgizmoconf.h2
-rw-r--r--src/drumkitloader.cc12
-rw-r--r--src/engineevent.h (renamed from src/event.h)2
-rw-r--r--src/events.h3
-rw-r--r--src/inputfilter.h2
-rw-r--r--src/inputprocessor.cc40
-rw-r--r--src/inputprocessor.h17
-rw-r--r--src/midimapper.cc4
-rw-r--r--src/nolocale.h2
-rw-r--r--src/owner.h24
-rw-r--r--src/path.cc4
-rw-r--r--src/powerlist.cc7
-rw-r--r--src/powermap.h76
-rw-r--r--src/powermapfilter.h4
-rw-r--r--src/sem.cc8
-rw-r--r--src/syncedsettings.h16
-rw-r--r--src/translation.cc8
-rw-r--r--src/versionstr.cc5
-rw-r--r--test/Makefile.am26
-rw-r--r--test/audiocacheidmanagertest.cc14
-rw-r--r--test/curvemaptest.cc267
-rw-r--r--test/dgreftest/midiinputengine.h8
-rw-r--r--test/paintertest.cc2
-rw-r--r--test/powermaptest.cc51
-rwxr-xr-xtools/add_file4
-rw-r--r--version.h2
68 files changed, 1053 insertions, 614 deletions
diff --git a/ChangeLog b/ChangeLog
index b2f40ea..a598f87 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,82 @@
+Version 0.9.20
+==============
+Release date: September 8th 2022
+Contributors: chaot4, corrados, trebmuh, deva
+
+This release was originally intended as a bugfix release, but quite a few
+features also managed to find their way in.
+
+Noteworthy bugs that has been fixed:
+ - Software regression error in cymbal choke code has been fixed. So now
+ choking of cymbals using both directed chokes and after-touch midi
+ events work again as expected.
+ - A compilation error due to an update in LV2 API (we used an
+ obsolete LV2 type) has been fixed, so now compilation should work for
+ everybody again.
+ - Code can now properly be compiled with NSL support disabled at
+ configure time.
+ - Compilation with the modern gcc-11 compiler has been fixed.
+
+On top of this a lot of crash-bugs has been fixed.
+
+Thanks to corrados, this version adds support for midi input through
+the alsa seq driver for the command line version of drumgizmo. So now
+drumgizmo can be run from the commandline entirely without the need
+for jack.
+
+Compilation Bugs:
+ - Fix compilation with gcc-11
+ - Fix compilation issue when compiling without nls enabled.
+ - Remove sndfile.h from audiofile header
+ - Fix missing backslash in libdg includepaths
+ - Fix compiler warning.
+ - Add missing include
+ - Make configure fail if nls is enabled but gettext tools not found.
+
+Crash Bugs:
+ - Fix crash when loading a kit with more channels than the engine
+ was compiled for.
+ - Fix crash when loading Crocell kit in ardour (stack allocation
+ issue) - see Ardour bug report.
+ - Get rid of big stack allocation during resampler (re-)configuration.
+ - Prevent processing jack clients that are being deleted.
+ - Fix crash when pressing play while loading a drumkit.
+ - Skip events whose audio-files has not yet been loaded.
+ - Fix crash when doing async-load in cli.
+
+Other Bugs:
+ - Fixed directed-chokes regression error.
+ - Fix after-touch chokes regression error.
+ - Fix wrong sample selection with instruments having only two samples.
+ - Make aftertouch choke if velocities > 0 instead of == 0 as this
+ seem to be the vdrum vendor concensus.
+ - Clear all active events (ie. stop playing samples) when loading a new kit.
+ - Fix ALSA output frame size change.
+ - added getBufferSize function for alsa out
+
+Features:
+ - Record and measure real cymbal choke-time and use this value
+ instead of the current 68ms.
+ - Adjust choke ramp-down time to better reflect the actual
+ dampening time of a hand-dampened cymbal.
+ - Add support for triggering multiple instruments with one midi note.
+ - Add voice-limit parameters to cli
+ - Add setting for controlling ALSA periods to output module.
+ - Add ALSA MIDI seq input support
+
+Other:
+ - Add unit-test for EventsDS::clear() method.
+ - Add clear member function to EventsDS.
+ - Add assert to break infinite loop in case of a bug.
+ - Add -Wextra to debug compilation flags.
+ - Make it possible to (only) build unit-test in parrallel.
+ - Add dggui namespace to libdggui components.
+ - Split UI code into application/plugin UI and UI library.
+ - Run and fix unit-tests on windows.
+ - Make rcgen compile and work on windows again through autotools.
+ - Improve cocoa/macOS rendering speed by removing redraw on all events.
+ - Reduce UI window height to fit on low-res displays.
+
Version 0.9.19
==============
Release date: November 22nd 2020
diff --git a/RELEASE-CHECKLIST b/RELEASE-CHECKLIST
index eb51141..a46ffc7 100644
--- a/RELEASE-CHECKLIST
+++ b/RELEASE-CHECKLIST
@@ -4,7 +4,7 @@ Check list for releasing:
[ ] Update man page
- [ ] Bump version in version.h
+ [ ] Bump version in version.h and in man pages and po/pot files.
[ ] Update ChangeLog
diff --git a/autogen.sh b/autogen.sh
index ae4952f..9975ca9 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -16,6 +16,7 @@ mkdir -p actest
cat << EOF > actest/configure.ac
AC_INIT([actest], [1.0.0])
AC_PROG_OBJCXX
+AC_OUTPUT([])
EOF
[ -f acinclude.m4 ] && rm acinclude.m4
autoreconf -W error actest 2>/dev/null || echo "AC_DEFUN([AC_PROG_OBJCXX],[echo ' - ObjC++ hack - not support by this platform, but not needed either.'])" > acinclude.m4
diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc
index 8eba4c9..bca55d2 100644
--- a/drumgizmo/drumgizmoc.cc
+++ b/drumgizmo/drumgizmoc.cc
@@ -46,8 +46,6 @@
#include "enginefactory.h"
#include "bytesizeparser.h"
-#include "event.h"
-
#include "nolocale.h"
struct ParmToken
diff --git a/drumgizmo/input/jackmidi.cc b/drumgizmo/input/jackmidi.cc
index 445678b..7081bf1 100644
--- a/drumgizmo/input/jackmidi.cc
+++ b/drumgizmo/input/jackmidi.cc
@@ -122,6 +122,6 @@ void JackMidiInputEngine::process(jack_nframes_t num_frames)
jack_midi_event_get(&event, buffer, i);
processNote(event.buffer, event.size, event.time, events);
}
- jack_midi_clear_buffer(buffer);
+
pos += num_frames;
}
diff --git a/drumgizmo/input/midifile.h b/drumgizmo/input/midifile.h
index 5756718..a8cf574 100644
--- a/drumgizmo/input/midifile.h
+++ b/drumgizmo/input/midifile.h
@@ -25,9 +25,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#pragma once
+
#include <string>
-#include <event.h>
#include <smf.h>
#include "audioinputenginemidi.h"
diff --git a/drumgizmo/input/test.cc b/drumgizmo/input/test.cc
index 955d218..bc88c48 100644
--- a/drumgizmo/input/test.cc
+++ b/drumgizmo/input/test.cc
@@ -27,7 +27,6 @@
#include <stdlib.h>
#include <string>
-#include "event.h"
#include "test.h"
TestInputEngine::TestInputEngine()
diff --git a/drumgizmo/input/test.h b/drumgizmo/input/test.h
index baf7c95..f1e0b42 100644
--- a/drumgizmo/input/test.h
+++ b/drumgizmo/input/test.h
@@ -27,7 +27,6 @@
#pragma once
#include <string>
-#include "event.h"
#include "audioinputengine.h"
class TestInputEngine
diff --git a/plugin/Makefile.mingw32.in b/plugin/Makefile.mingw32.in
index ad47bcc..9cfcc9e 100644
--- a/plugin/Makefile.mingw32.in
+++ b/plugin/Makefile.mingw32.in
@@ -39,7 +39,7 @@ DG_SRC = \
@top_srcdir@/src/midimapper.cc \
@top_srcdir@/src/path.cc \
@top_srcdir@/src/powerlist.cc \
- @top_srcdir@/src/powermap.cc \
+ @top_srcdir@/src/curvemap.cc \
@top_srcdir@/src/powermapfilter.cc \
@top_srcdir@/src/random.cc \
@top_srcdir@/src/sample.cc \
diff --git a/plugin/plugingizmo b/plugin/plugingizmo
-Subproject be64ddf9da525cd5c6757464efc966052731ba7
+Subproject a88c76afd8fbfe31b76010bac34c1437b192724
diff --git a/plugingui/diskstreamingframecontent.cc b/plugingui/diskstreamingframecontent.cc
index 4c63817..5420afd 100644
--- a/plugingui/diskstreamingframecontent.cc
+++ b/plugingui/diskstreamingframecontent.cc
@@ -95,7 +95,7 @@ void DiskstreamingframeContent::resize(std::size_t width, std::size_t height)
void DiskstreamingframeContent::limitSettingsValueChanged(std::size_t value)
{
- float new_slider_value = (float)(value - min_limit)/(max_limit - min_limit);
+ float new_slider_value = (float)(value - min_limit)/(float)(max_limit - min_limit);
slider.setValue(new_slider_value);
if(new_slider_value < 0.99)
@@ -116,7 +116,7 @@ void DiskstreamingframeContent::limitSettingsValueChanged(std::size_t value)
void DiskstreamingframeContent::limitValueChanged(float value)
{
std::size_t new_limit = value < 0.99 ?
- value * (max_limit - min_limit) + min_limit :
+ value * (float)(max_limit - min_limit) + min_limit :
std::numeric_limits<std::size_t>::max();
settings.disk_cache_upper_limit.store(new_limit);
diff --git a/plugingui/locale/da.po b/plugingui/locale/da.po
index e25235f..e3904d0 100644
--- a/plugingui/locale/da.po
+++ b/plugingui/locale/da.po
@@ -6,7 +6,7 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: drumgizmo 0.9.17\n"
+"Project-Id-Version: drumgizmo 0.9.20\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-13 21:07+0200\n"
"PO-Revision-Date: 2019-09-13 19:42+0200\n"
diff --git a/plugingui/locale/drumgizmo.pot b/plugingui/locale/drumgizmo.pot
index 72e600e..e93e387 100644
--- a/plugingui/locale/drumgizmo.pot
+++ b/plugingui/locale/drumgizmo.pot
@@ -6,7 +6,7 @@
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: drumgizmo 0.9.19\n"
+"Project-Id-Version: drumgizmo 0.9.20\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
diff --git a/plugingui/locale/fr.po b/plugingui/locale/fr.po
index b46174c..c2fbb63 100644
--- a/plugingui/locale/fr.po
+++ b/plugingui/locale/fr.po
@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: drumgizmo 0.9.18.1\n"
+"Project-Id-Version: drumgizmo 0.9.20\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-13 21:07+0200\n"
"PO-Revision-Date: 2020-11-21 16:49+0200\n"
diff --git a/plugingui/powerwidget.cc b/plugingui/powerwidget.cc
index 9be0c48..71ad74b 100644
--- a/plugingui/powerwidget.cc
+++ b/plugingui/powerwidget.cc
@@ -31,7 +31,6 @@
#include <notifier.h>
#include <settings.h>
-#include <powermap.h>
#include <hugin.hpp>
#include <cmath>
@@ -120,7 +119,7 @@ PowerWidget::Canvas::Canvas(dggui::Widget* parent,
void PowerWidget::Canvas::repaintEvent(dggui::RepaintEvent *repaintEvent)
{
- if(width() < 1 || height() < 1)
+ if(width() < 4 || height() < 4)
{
return;
}
diff --git a/plugingui/powerwidget.h b/plugingui/powerwidget.h
index 3a7bb8e..3d09e6b 100644
--- a/plugingui/powerwidget.h
+++ b/plugingui/powerwidget.h
@@ -34,7 +34,7 @@
#include <dggui/label.h>
#include <dggui/font.h>
-#include <powermap.h>
+#include <curvemap.h>
struct Settings;
class SettingsNotifier;
@@ -75,7 +75,7 @@ private:
virtual void mouseLeaveEvent() override;
private:
- Powermap power_map;
+ CurveMap power_map;
void parameterChangedFloat(float);
void parameterChangedBool(bool);
diff --git a/plugingui/resamplingframecontent.cc b/plugingui/resamplingframecontent.cc
index d92dc27..6e631c7 100644
--- a/plugingui/resamplingframecontent.cc
+++ b/plugingui/resamplingframecontent.cc
@@ -30,6 +30,8 @@
#include <translation.h>
+#include <algorithm>
+
namespace GUI
{
@@ -70,9 +72,9 @@ ResamplingframeContent::ResamplingframeContent(dggui::Widget* parent,
void ResamplingframeContent::resize(std::size_t width, std::size_t height)
{
Widget::resize(width, height);
- text_field.resize(width - 50, height);
- quality_knob.move(width - 36, 20);
- quality_label.move(width - 40, 0);
+ text_field.resize(std::max(width, std::size_t{51}) - 50, height);
+ quality_knob.move(std::max(width, std::size_t{37}) - 36, 20);
+ quality_label.move(std::max(width, std::size_t{41}) - 40, 0);
}
void ResamplingframeContent::updateContent()
diff --git a/src/Makefile.am b/src/Makefile.am
index 85b10fa..e2a2583 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,49 +33,50 @@ libdg_la_CPPFLAGS = \
$(DEBUG_FLAGS) \
-I$(top_srcdir)/hugin -I$(top_srcdir)/pugixml/src \
$(SSEFLAGS) -I$(top_srcdir)/zita-resampler/libs \
- $(SNDFILE_CFLAGS) $(PTHREAD_CFLAGS)
+ $(SNDFILE_CFLAGS) $(PTHREAD_CFLAGS) \
+ -Wno-deprecated-declarations
libdg_la_LIBADD = \
$(SNDFILE_LIBS) $(PTHREAD_LIBS) libzr.la libpugi.la
libdg_la_SOURCES = \
- audiocachefile.cc \
- audiocache.cc \
- audiocacheeventhandler.cc \
- audiocacheidmanager.cc \
- audioinputenginemidi.cc \
- audiofile.cc \
- bytesizeparser.cc \
- channel.cc \
- channelmixer.cc \
- configfile.cc \
- configparser.cc \
- directory.cc \
- domloader.cc \
- dgxmlparser.cc \
- drumgizmo.cc \
- drumgizmoconf.cc \
- drumkit.cc \
- drumkitloader.cc \
- events.cc \
- events_ds.cc \
- inputprocessor.cc \
- instrument.cc \
- latencyfilter.cc \
- midimapparser.cc \
- midimapper.cc \
- path.cc \
- powerlist.cc \
- powermap.cc \
- powermapfilter.cc \
- random.cc \
- sample.cc \
- sample_selection.cc \
- sem.cc \
- staminafilter.cc \
- thread.cc \
- velocityfilter.cc \
- versionstr.cc
+ $(top_srcdir)/src/audiocachefile.cc \
+ $(top_srcdir)/src/audiocache.cc \
+ $(top_srcdir)/src/audiocacheeventhandler.cc \
+ $(top_srcdir)/src/audiocacheidmanager.cc \
+ $(top_srcdir)/src/audioinputenginemidi.cc \
+ $(top_srcdir)/src/audiofile.cc \
+ $(top_srcdir)/src/bytesizeparser.cc \
+ $(top_srcdir)/src/channel.cc \
+ $(top_srcdir)/src/channelmixer.cc \
+ $(top_srcdir)/src/configfile.cc \
+ $(top_srcdir)/src/configparser.cc \
+ $(top_srcdir)/src/directory.cc \
+ $(top_srcdir)/src/domloader.cc \
+ $(top_srcdir)/src/dgxmlparser.cc \
+ $(top_srcdir)/src/drumgizmo.cc \
+ $(top_srcdir)/src/drumgizmoconf.cc \
+ $(top_srcdir)/src/drumkit.cc \
+ $(top_srcdir)/src/drumkitloader.cc \
+ $(top_srcdir)/src/events.cc \
+ $(top_srcdir)/src/events_ds.cc \
+ $(top_srcdir)/src/inputprocessor.cc \
+ $(top_srcdir)/src/instrument.cc \
+ $(top_srcdir)/src/latencyfilter.cc \
+ $(top_srcdir)/src/midimapparser.cc \
+ $(top_srcdir)/src/midimapper.cc \
+ $(top_srcdir)/src/path.cc \
+ $(top_srcdir)/src/powerlist.cc \
+ $(top_srcdir)/src/curvemap.cc \
+ $(top_srcdir)/src/powermapfilter.cc \
+ $(top_srcdir)/src/random.cc \
+ $(top_srcdir)/src/sample.cc \
+ $(top_srcdir)/src/sample_selection.cc \
+ $(top_srcdir)/src/sem.cc \
+ $(top_srcdir)/src/staminafilter.cc \
+ $(top_srcdir)/src/thread.cc \
+ $(top_srcdir)/src/velocityfilter.cc \
+ $(top_srcdir)/src/versionstr.cc
EXTRA_DIST = \
$(libzr_la_SOURCES) \
@@ -106,7 +107,7 @@ EXTRA_DIST = \
drumgizmoconf.h \
drumkit.h \
drumkitloader.h \
- event.h \
+ engineevent.h \
events.h \
events_ds.h \
grid.h \
@@ -121,10 +122,11 @@ EXTRA_DIST = \
midimapper.h \
nolocale.h \
notifier.h \
+ owner.h \
path.h \
platform.h \
powerlist.h \
- powermap.h \
+ curvemap.h \
powermapfilter.h \
random.h \
range.h \
@@ -140,3 +142,10 @@ EXTRA_DIST = \
velocityfilter.h \
versionstr.h \
zrwrapper.h
+
+%.lint: %.cc
+ clang-tidy --quiet $< -- $(libdg_la_CPPFLAGS) $(CXXFLAGS)
+
+LINT_FILES = $(libdg_la_SOURCES:.cc=.lint)
+
+lint: $(LINT_FILES)
diff --git a/src/atomic.h b/src/atomic.h
index 7ca5d1e..a29eeee 100644
--- a/src/atomic.h
+++ b/src/atomic.h
@@ -69,7 +69,7 @@ public:
: data{}
, mutex{}
{
- std::lock_guard<std::mutex> lock{other.mutex};
+ const std::lock_guard<std::mutex> lock{other.mutex};
data = other.data;
}
@@ -77,13 +77,13 @@ public:
: data{}
, mutex{}
{
- std::lock_guard<std::mutex> lock{other.mutex};
+ const std::lock_guard<std::mutex> lock{other.mutex};
std::swap(data, other.data);
}
T operator=(T data)
{
- std::lock_guard<std::mutex> lock{mutex};
+ const std::lock_guard<std::mutex> lock{mutex};
this->data = std::move(data);
return this->data;
}
@@ -100,42 +100,42 @@ public:
void store(T data)
{
- std::lock_guard<std::mutex> lock{mutex};
+ const std::lock_guard<std::mutex> lock{mutex};
this->data = std::move(data);
}
T load() const {
- std::lock_guard<std::mutex> lock{mutex};
+ const std::lock_guard<std::mutex> lock{mutex};
return data;
}
T exchange(T data){
- std::lock_guard<std::mutex> lock{mutex};
+ const std::lock_guard<std::mutex> lock{mutex};
std::swap(data, this->data);
return data;
}
bool operator==(const T& other) const
{
- std::lock_guard<std::mutex> lock{mutex};
+ const std::lock_guard<std::mutex> lock{mutex};
return other == data;
}
bool operator!=(const T& other) const
{
- std::lock_guard<std::mutex> lock{mutex};
+ const std::lock_guard<std::mutex> lock{mutex};
return !(other == data);
}
bool operator==(const Atomic<T>& other) const
{
- std::lock_guard<std::mutex> lock{mutex};
+ const std::lock_guard<std::mutex> lock{mutex};
return other.load() == data;
}
bool operator!=(const Atomic<T>& other) const
{
- std::lock_guard<std::mutex> lock{mutex};
+ const std::lock_guard<std::mutex> lock{mutex};
return !(other.load() == data);
}
diff --git a/src/audio.h b/src/audio.h
index d022147..289f662 100644
--- a/src/audio.h
+++ b/src/audio.h
@@ -26,4 +26,4 @@
*/
#pragma once
-#include <audiotypes.h>
+#include "audiotypes.h"
diff --git a/src/audiocache.cc b/src/audiocache.cc
index a2d26d9..92d3d61 100644
--- a/src/audiocache.cc
+++ b/src/audiocache.cc
@@ -28,8 +28,8 @@
#include <mutex>
-#include <stdio.h>
-#include <assert.h>
+#include <cstdio>
+#include <cassert>
#include <hugin.hpp>
@@ -64,9 +64,9 @@ void AudioCache::deinit()
}
// Invariant: initial_samples_needed < preloaded audio data
-sample_t* AudioCache::open(const AudioFile& file,
- std::size_t initial_samples_needed,
- int channel, cacheid_t& id)
+gsl::owner<sample_t*> AudioCache::open(const AudioFile& file,
+ std::size_t initial_samples_needed,
+ int channel, cacheid_t& new_cacheid)
{
assert(chunk_size); // Assert updateChunkSize was called before processing.
@@ -74,16 +74,16 @@ sample_t* AudioCache::open(const AudioFile& file,
{
settings.number_of_underruns.fetch_add(1);
// File preload not yet ready - skip this sample.
- id = CACHE_DUMMYID;
+ new_cacheid = CACHE_DUMMYID;
assert(nodata);
return nodata;
}
// Register a new id for this cache session.
- id = id_manager.registerID({});
+ new_cacheid = id_manager.registerID({});
// If we are out of available ids we get CACHE_DUMMYID
- if(id == CACHE_DUMMYID)
+ if(new_cacheid == CACHE_DUMMYID)
{
settings.number_of_underruns.fetch_add(1);
// Use nodata buffer instead.
@@ -91,20 +91,20 @@ sample_t* AudioCache::open(const AudioFile& file,
return nodata;
}
- // Get the cache_t connected with the registered id.
- cache_t& c = id_manager.getCache(id);
+ // Get the CacheBuffer connected with the registered id.
+ CacheBuffer& cache = id_manager.getCache(new_cacheid);
- c.afile = nullptr; // File is opened when needed.
- c.channel = channel;
+ cache.afile = nullptr; // File is opened when needed.
+ cache.channel = channel;
// Next call to 'next()' will read from this point.
- c.localpos = initial_samples_needed;
+ cache.localpos = initial_samples_needed;
- c.ready = false;
- c.front = nullptr; // This is allocated when needed.
- c.back = nullptr; // This is allocated when needed.
+ cache.ready = false;
+ cache.front = nullptr; // This is allocated when needed.
+ cache.back = nullptr; // This is allocated when needed.
- std::size_t cropped_size;
+ std::size_t cropped_size{};
if(file.preloadedsize == file.size)
{
@@ -122,162 +122,162 @@ sample_t* AudioCache::open(const AudioFile& file,
// \----------------------v-------------------/
// cropped_size
- cropped_size = file.preloadedsize - c.localpos;
+ cropped_size = file.preloadedsize - cache.localpos;
cropped_size -= cropped_size % framesize;
cropped_size += initial_samples_needed;
}
- c.preloaded_samples = file.data;
- c.preloaded_samples_size = cropped_size;
+ cache.preloaded_samples = file.data;
+ cache.preloaded_samples_size = cropped_size;
// Next potential read from disk will read from this point.
- c.pos = cropped_size;
+ cache.pos = cropped_size;
// Only load next buffer if there is more data in the file to be loaded...
- if(c.pos < file.size)
+ if(cache.pos < file.size)
{
- c.afile = &event_handler.openFile(file.filename);
+ cache.afile = &event_handler.openFile(file.filename);
- if(c.back == nullptr)
+ if(cache.back == nullptr)
{
- c.back = new sample_t[chunk_size];
+ cache.allocBack(chunk_size);
}
- event_handler.pushLoadNextEvent(c.afile, c.channel, c.pos,
- c.back, &c.ready);
+ event_handler.pushLoadNextEvent(cache.afile, cache.channel, cache.pos,
+ cache.back, &cache.ready);
}
- return c.preloaded_samples; // return preloaded data
+ return cache.preloaded_samples; // return preloaded data
}
-sample_t* AudioCache::next(cacheid_t id, std::size_t& size)
+gsl::owner<sample_t*> AudioCache::next(cacheid_t cacheid, std::size_t& size)
{
- if(id == CACHE_DUMMYID)
+ if(cacheid == CACHE_DUMMYID)
{
settings.number_of_underruns.fetch_add(1);
assert(nodata);
return nodata;
}
- cache_t& c = id_manager.getCache(id);
+ CacheBuffer& cache = id_manager.getCache(cacheid);
- if(c.preloaded_samples)
+ if(cache.preloaded_samples != nullptr)
{
// We are playing from memory:
- if(c.localpos < c.preloaded_samples_size)
+ if(cache.localpos < cache.preloaded_samples_size)
{
- sample_t* s = c.preloaded_samples + c.localpos;
+ sample_t* samples = cache.preloaded_samples + cache.localpos; // NOLINT: Fix with span?
// If only a partial frame is returned. Reflect this in the size
- size = std::min(size, c.preloaded_samples_size - c.localpos);
+ size = std::min(size, cache.preloaded_samples_size - cache.localpos);
- c.localpos += size;
- return s;
+ cache.localpos += size;
+ return samples;
}
- c.preloaded_samples = nullptr; // Start using samples from disk.
+ cache.preloaded_samples = nullptr; // Start using samples from disk.
}
else
{
// We are playing from cache:
- if(c.localpos < chunk_size)
+ if(cache.localpos < chunk_size)
{
- if(c.front == nullptr)
+ if(cache.front == nullptr)
{
// Just return silence.
settings.number_of_underruns.fetch_add(1);
- c.localpos += size; // Skip these samples so we don't loose sync.
+ cache.localpos += size; // Skip these samples so we don't loose sync.
assert(nodata);
return nodata;
}
- sample_t* s = c.front + c.localpos;
+ sample_t* samples = cache.front + cache.localpos;// NOLINT: Fix with span?
// If only a partial frame is returned. Reflect this in the size
- size = std::min(size, chunk_size - c.localpos);
- c.localpos += size;
- return s;
+ size = std::min(size, chunk_size - cache.localpos);
+ cache.localpos += size;
+ return samples;
}
}
// Check for buffer underrun
- if(!c.ready)
+ if(!cache.ready)
{
// Just return silence.
settings.number_of_underruns.fetch_add(1);
- c.localpos += size; // Skip these samples so we don't loose sync.
+ cache.localpos += size; // Skip these samples so we don't loose sync.
assert(nodata);
return nodata;
}
// Swap buffers
- std::swap(c.front, c.back);
+ cache.swap();
// Next time we go here we have already read the first frame.
- c.localpos = size;
+ cache.localpos = size;
- c.pos += chunk_size;
+ cache.pos += chunk_size;
// Does the file have remaining unread samples?
- assert(c.afile); // Assert that we have an audio file.
- if(c.pos < c.afile->getSize())
+ assert(cache.afile); // Assert that we have an audio file.
+ if(cache.pos < cache.afile->getSize())
{
// Do we have a back buffer to read into?
- if(c.back == nullptr)
+ if(cache.back == nullptr)
{
- c.back = new sample_t[chunk_size];
+ cache.allocBack(chunk_size);
}
- event_handler.pushLoadNextEvent(c.afile, c.channel, c.pos,
- c.back, &c.ready);
+ event_handler.pushLoadNextEvent(cache.afile, cache.channel, cache.pos,
+ cache.back, &cache.ready);
}
// We should always have a front buffer at this point.
- assert(c.front);
- return c.front;
+ assert(cache.front);
+ return cache.front;
}
-bool AudioCache::isReady(cacheid_t id)
+bool AudioCache::isReady(cacheid_t cacheid)
{
- if(id == CACHE_DUMMYID)
+ if(cacheid == CACHE_DUMMYID)
{
return true;
}
- cache_t& cache = id_manager.getCache(id);
+ const CacheBuffer& cache = id_manager.getCache(cacheid);
return cache.ready;
}
-void AudioCache::close(cacheid_t id)
+void AudioCache::close(cacheid_t cacheid)
{
- if(id == CACHE_DUMMYID)
+ if(cacheid == CACHE_DUMMYID)
{
return;
}
- event_handler.pushCloseEvent(id);
+ event_handler.pushCloseEvent(cacheid);
}
void AudioCache::setFrameSize(std::size_t framesize)
{
// Make sure the event handler thread is stalled while we set the framesize
// state.
- std::lock_guard<AudioCacheEventHandler> event_handler_lock(event_handler);
+ const std::lock_guard<AudioCacheEventHandler> event_handler_lock(event_handler);
// NOTE: Not threaded...
//std::lock_guard<AudioCacheIDManager> id_manager_lock(id_manager);
if(framesize > nodata_framesize)
{
- if(nodata)
+ if(nodata != nullptr)
{
- nodata_dirty.emplace_back(std::move(nodata)); // Store for later deletion.
+ nodata_dirty.emplace_back(nodata); // Store for later deletion.
}
nodata = new sample_t[framesize];
nodata_framesize = framesize;
for(std::size_t i = 0; i < framesize; ++i)
{
- nodata[i] = 0.0f;
+ nodata[i] = 0.0f;// NOLINT: Fix with span?
}
}
@@ -292,9 +292,11 @@ std::size_t AudioCache::getFrameSize() const
void AudioCache::updateChunkSize(std::size_t output_channels)
{
// Make sure we won't get out-of-range chunk sizes.
- std::size_t disk_cache_chunk_size =
- std::max(settings.disk_cache_chunk_size.load(), std::size_t(512u * 1024u));
- output_channels = std::max(output_channels, std::size_t(1u));
+ constexpr std::size_t max_cache_chunk_size{512ul * 1024ul};
+ const auto disk_cache_chunk_size =
+ std::max(settings.disk_cache_chunk_size.load(), max_cache_chunk_size);
+ constexpr std::size_t min_output_channels{1};
+ output_channels = std::max(output_channels, min_output_channels);
// 1MB pr. chunk divided over 16 channels, 4 bytes pr. sample.
const auto ideal_chunk_size =
diff --git a/src/audiocache.h b/src/audiocache.h
index 9c6fa53..632aae9 100644
--- a/src/audiocache.h
+++ b/src/audiocache.h
@@ -38,6 +38,7 @@
#include "audiocacheidmanager.h"
#include "audiocacheeventhandler.h"
#include "settings.h"
+#include "owner.h"
class AudioCache
{
@@ -68,8 +69,10 @@ public:
//! \param [out] new_id The newly created cache id.
//! \return A pointer to the first buffer containing the
//! 'initial_samples_needed' number of samples.
- sample_t* open(const AudioFile& file, std::size_t initial_samples_needed, int channel,
- cacheid_t& new_id);
+ gsl::owner<sample_t*> open(const AudioFile& file,
+ std::size_t initial_samples_needed,
+ int channel,
+ cacheid_t& new_cacheid);
//! Get next buffer.
//! Returns the next buffer for reading based on cache id.
@@ -78,9 +81,9 @@ public:
//! \param id The cache id to read from.
//! \param [out] size The size of the returned buffer.
//! \return A pointer to the buffer.
- sample_t* next(cacheid_t id, std::size_t &size);
+ gsl::owner<sample_t*> next(cacheid_t id, std::size_t &size);
- //! Returns true iff the next chunk of the supplied id has been read from disk.
+ //! Returns true iff next chunk of the supplied id has been read from disk.
bool isReady(cacheid_t id);
//! Unregister cache entry.
@@ -103,10 +106,10 @@ public:
bool isAsyncMode() const;
private:
- std::size_t framesize{0};
- sample_t* nodata{nullptr};
- std::size_t nodata_framesize{0};
- std::size_t chunk_size{0};
+ std::size_t framesize{};
+ gsl::owner<sample_t*> nodata{};
+ std::size_t nodata_framesize{};
+ std::size_t chunk_size{};
std::list<std::unique_ptr<sample_t[]>> nodata_dirty;
AudioCacheIDManager id_manager;
diff --git a/src/audiocacheeventhandler.cc b/src/audiocacheeventhandler.cc
index a0327b5..ffd183c 100644
--- a/src/audiocacheeventhandler.cc
+++ b/src/audiocacheeventhandler.cc
@@ -26,7 +26,7 @@
*/
#include "audiocacheeventhandler.h"
-#include <assert.h>
+#include <cassert>
#include <hugin.hpp>
@@ -34,13 +34,14 @@
#include "audiocache.h"
#include "audiocacheidmanager.h"
-enum class EventType {
+enum class EventType
+{
LoadNext,
Close,
};
-class CacheEvent {
-public:
+struct CacheEvent
+{
EventType event_type;
// For close event:
@@ -63,9 +64,9 @@ AudioCacheEventHandler::~AudioCacheEventHandler()
clearEvents();
auto active_ids = id_manager.getActiveIDs();
- for(auto id : active_ids)
+ for(auto active_id : active_ids)
{
- handleCloseCache(id);
+ handleCloseCache(active_id);
}
}
@@ -115,32 +116,32 @@ void AudioCacheEventHandler::unlock()
}
void AudioCacheEventHandler::pushLoadNextEvent(AudioCacheFile* afile,
- size_t channel,
+ size_t channel_index,
size_t pos, sample_t* buffer,
volatile bool* ready)
{
- CacheEvent cache_event;
+ CacheEvent cache_event{};
cache_event.event_type = EventType::LoadNext;
cache_event.pos = pos;
cache_event.afile = afile;
- CacheChannel c;
- c.channel = channel;
- c.samples = buffer;
+ CacheChannel cache_channel{};
+ cache_channel.channel_index = channel_index;
+ cache_channel.samples = buffer;
*ready = false;
- c.ready = ready;
+ cache_channel.ready = ready;
- cache_event.channels.insert(cache_event.channels.end(), c);
+ cache_event.channels.insert(cache_event.channels.end(), cache_channel);
pushEvent(cache_event);
}
-void AudioCacheEventHandler::pushCloseEvent(cacheid_t id)
+void AudioCacheEventHandler::pushCloseEvent(cacheid_t cacheid)
{
- CacheEvent cache_event;
+ CacheEvent cache_event{};
cache_event.event_type = EventType::Close;
- cache_event.id = id;
+ cache_event.id = cacheid;
pushEvent(cache_event);
}
@@ -179,7 +180,7 @@ size_t AudioCacheEventHandler::getChunkSize() const
AudioCacheFile& AudioCacheEventHandler::openFile(const std::string& filename)
{
- std::lock_guard<std::mutex> lock(mutex);
+ const std::lock_guard<std::mutex> lock(mutex);
return files.getFile(filename);
}
@@ -197,7 +198,7 @@ void AudioCacheEventHandler::clearEvents()
eventqueue.clear();
}
-void AudioCacheEventHandler::handleLoadNextEvent(CacheEvent& cache_event)
+void AudioCacheEventHandler::handleLoadNextEvent(CacheEvent& cache_event) const
{
assert(cache_event.afile); // Assert that we have an audio file
@@ -207,24 +208,25 @@ void AudioCacheEventHandler::handleLoadNextEvent(CacheEvent& cache_event)
void AudioCacheEventHandler::handleCloseEvent(CacheEvent& cache_event)
{
- std::lock_guard<std::mutex> lock(mutex);
+ const std::lock_guard<std::mutex> lock(mutex);
handleCloseCache(cache_event.id);
}
-void AudioCacheEventHandler::handleCloseCache(cacheid_t id)
+void AudioCacheEventHandler::handleCloseCache(cacheid_t cacheid)
{
- auto& cache = id_manager.getCache(id);
+ auto& cache = id_manager.getCache(cacheid);
// Only close the file if we have also opened it.
- if(cache.afile)
+ if(cache.afile != nullptr)
{
files.releaseFile(cache.afile->getFilename());
}
- delete[] cache.front;
- delete[] cache.back;
+ //delete[] cache.front;
+ //delete[] cache.back;
+ cache.deleteChunks();
- id_manager.releaseID(id);
+ id_manager.releaseID(cacheid);
}
void AudioCacheEventHandler::handleEvent(CacheEvent& cache_event)
@@ -272,7 +274,7 @@ void AudioCacheEventHandler::pushEvent(CacheEvent& cache_event)
}
{
- std::lock_guard<std::mutex> lock(mutex);
+ const std::lock_guard<std::mutex> lock(mutex);
bool found = false;
diff --git a/src/audiocacheeventhandler.h b/src/audiocacheeventhandler.h
index f80b4c8..e676f6e 100644
--- a/src/audiocacheeventhandler.h
+++ b/src/audiocacheeventhandler.h
@@ -36,7 +36,7 @@
#include "audiocachefile.h"
#include "audiocacheidmanager.h"
-class CacheEvent;
+struct CacheEvent;
class AudioCacheEventHandler
: protected Thread
@@ -68,10 +68,10 @@ public:
//! This methods are supplied to make this class lockable by std::lock_guard
void unlock();
- void pushLoadNextEvent(AudioCacheFile* afile, size_t channel,
+ void pushLoadNextEvent(AudioCacheFile* afile, size_t channel_index,
size_t pos, sample_t* buffer,
volatile bool* ready);
- void pushCloseEvent(cacheid_t id);
+ void pushCloseEvent(cacheid_t cacheid);
void setChunkSize(size_t chunksize);
size_t getChunkSize() const;
@@ -81,13 +81,13 @@ public:
protected:
void clearEvents();
- void handleLoadNextEvent(CacheEvent& cache_event);
+ void handleLoadNextEvent(CacheEvent& cache_event) const;
//! Lock the mutex and calls handleCloseCache
void handleCloseEvent(CacheEvent& cache_event);
//! Close decrease the file ref and release the cache id.
- void handleCloseCache(cacheid_t id);
+ void handleCloseCache(cacheid_t cacheid);
void handleEvent(CacheEvent& cache_event);
diff --git a/src/audiocachefile.cc b/src/audiocachefile.cc
index 2c2888c..daf4fc1 100644
--- a/src/audiocachefile.cc
+++ b/src/audiocachefile.cc
@@ -26,23 +26,19 @@
*/
#include "audiocachefile.h"
-#include <assert.h>
-
-#include <hugin.hpp>
-
+#include <cassert>
#include <cstring>
+#include <functional>
-#include "audiocache.h"
+#include <hugin.hpp>
AudioCacheFile::AudioCacheFile(const std::string& filename,
std::vector<sample_t>& read_buffer)
: filename(filename)
, read_buffer(read_buffer)
{
- std::memset(&sf_info, 0, sizeof(SF_INFO));
-
fh = sf_open(filename.c_str(), SFM_READ, &sf_info);
- if(!fh)
+ if(fh == nullptr)
{
ERR(audiofile,"SNDFILE Error (%s): %s\n",
filename.c_str(), sf_strerror(fh));
@@ -57,7 +53,7 @@ AudioCacheFile::AudioCacheFile(const std::string& filename,
AudioCacheFile::~AudioCacheFile()
{
- if(fh)
+ if(fh != nullptr)
{
sf_close(fh);
fh = nullptr;
@@ -80,10 +76,10 @@ size_t AudioCacheFile::getChannelCount() const
}
void AudioCacheFile::readChunk(const CacheChannels& channels,
- size_t pos, size_t num_samples)
+ std::size_t pos, std::size_t num_samples)
{
//assert(fh != nullptr); // File handle must never be nullptr
- if(!fh)
+ if(fh == nullptr)
{
return;
}
@@ -95,9 +91,9 @@ void AudioCacheFile::readChunk(const CacheChannels& channels,
return;
}
- sf_seek(fh, pos, SEEK_SET);
+ sf_seek(fh, static_cast<sf_count_t>(pos), SEEK_SET);
- size_t size = sf_info.frames - pos;
+ auto size = sf_info.frames - pos;
if(size > num_samples)
{
size = num_samples;
@@ -108,38 +104,42 @@ void AudioCacheFile::readChunk(const CacheChannels& channels,
read_buffer.resize(size * sf_info.channels);
}
- size_t read_size = sf_readf_float(fh, read_buffer.data(), size);
- (void)read_size;
+ const size_t read_size = sf_readf_float(fh, read_buffer.data(),
+ static_cast<sf_count_t>(size));
+ assert(read_size == size);
- for(auto it = channels.begin(); it != channels.end(); ++it)
+ for(const auto& channel : channels)
{
- size_t channel = it->channel;
- sample_t* data = it->samples;
+ auto channel_index = channel.channel_index;
+ auto* data = channel.samples;
for (size_t i = 0; i < size; ++i)
{
- data[i] = read_buffer[(i * sf_info.channels) + channel];
+ data[i] = read_buffer[(i * sf_info.channels) + channel_index]; // NOLINT: will be fixed with std::span
}
}
- for(auto it = channels.begin(); it != channels.end(); ++it)
+ for(const auto & channel : channels)
{
- *(it->ready) = true;
+ *(channel.ready) = true;
}
}
AudioCacheFile& AudioCacheFiles::getFile(const std::string& filename)
{
- std::lock_guard<std::mutex> lock(mutex);
+ const std::lock_guard<std::mutex> lock(mutex);
- auto it = audiofiles.find(filename);
- if(it == audiofiles.end())
+ auto audiofile_it = audiofiles.find(filename);
+ if(audiofile_it == audiofiles.end())
{
// Construct a new AudioCacheFile in place. The in place construction is relevant.
- it = audiofiles.emplace(std::piecewise_construct, std::make_tuple(filename),
- std::make_tuple(filename, std::ref(read_buffer))).first;
+ audiofile_it =
+ audiofiles.emplace(std::piecewise_construct,
+ std::make_tuple(filename),
+ std::make_tuple(filename,
+ std::ref(read_buffer))).first; // FIXME: This must be possible to do in a more easy-to-read way!
}
- auto& cache_audio_file = it->second;
+ auto& cache_audio_file = audiofile_it->second;
// Increase ref count.
++cache_audio_file.ref;
@@ -149,22 +149,22 @@ AudioCacheFile& AudioCacheFiles::getFile(const std::string& filename)
void AudioCacheFiles::releaseFile(const std::string& filename)
{
- std::lock_guard<std::mutex> lock(mutex);
+ const std::lock_guard<std::mutex> lock(mutex);
- auto it = audiofiles.find(filename);
- if(it == audiofiles.end())
+ auto audiofile_it = audiofiles.find(filename);
+ if(audiofile_it == audiofiles.end())
{
assert(false); // This should never happen!
return; // not open
}
- auto& audiofile = it->second;
+ auto& audiofile = audiofile_it->second;
assert(audiofile.ref); // If ref is not > 0 it shouldn't be in the map.
--audiofile.ref;
if(audiofile.ref == 0)
{
- audiofiles.erase(it);
+ audiofiles.erase(audiofile_it);
}
}
diff --git a/src/audiocachefile.h b/src/audiocachefile.h
index 66a6529..63170cf 100644
--- a/src/audiocachefile.h
+++ b/src/audiocachefile.h
@@ -31,16 +31,17 @@
#include <map>
#include <vector>
#include <mutex>
+#include <cstddef>
#include <sndfile.h>
-#include <audiotypes.h>
+#include "audiotypes.h"
//! Channel data container in the cache world.
class CacheChannel
{
public:
- size_t channel; //< Channel number
+ size_t channel_index; //< Channel number
sample_t* samples; //< Sample buffer pointer.
size_t num_samples; //< Number of samples in the sample buffer
volatile bool* ready; //< Is set to true when the loading is done.
@@ -72,12 +73,13 @@ public:
size_t getChannelCount() const;
//! Read audio data from the file into the supplied channel caches.
- void readChunk(const CacheChannels& channels, size_t pos, size_t num_samples);
+ void readChunk(const CacheChannels& channels, std::size_t pos,
+ std::size_t num_samples);
private:
- int ref{0};
- SNDFILE* fh{nullptr};
- SF_INFO sf_info;
+ int ref{};
+ SNDFILE* fh{};
+ SF_INFO sf_info{};
std::string filename;
std::vector<sample_t>& read_buffer;
};
diff --git a/src/audiocacheidmanager.cc b/src/audiocacheidmanager.cc
index efef17e..80b0f98 100644
--- a/src/audiocacheidmanager.cc
+++ b/src/audiocacheidmanager.cc
@@ -27,7 +27,23 @@
#include "audiocacheidmanager.h"
#include <limits>
-#include <assert.h>
+#include <cassert>
+
+void CacheBuffer::allocBack(std::size_t chunk_size)
+{
+ back = new sample_t[chunk_size];
+}
+
+void CacheBuffer::deleteChunks() const
+{
+ delete[] front;
+ delete[] back;
+}
+
+void CacheBuffer::swap() noexcept
+{
+ std::swap(front, back);
+}
AudioCacheIDManager::~AudioCacheIDManager()
{
@@ -36,34 +52,34 @@ AudioCacheIDManager::~AudioCacheIDManager()
void AudioCacheIDManager::init(unsigned int capacity)
{
- std::lock_guard<std::mutex> guard(mutex);
+ const std::lock_guard<std::mutex> guard(mutex);
id2cache.resize(capacity);
available_ids.resize(capacity);
- for(size_t i = 0; i < capacity; ++i)
+ for(int i = 0; i < static_cast<int>(capacity); ++i)
{
available_ids[i] = i;
}
}
-cache_t& AudioCacheIDManager::getCache(cacheid_t id)
+CacheBuffer& AudioCacheIDManager::getCache(cacheid_t cacheid)
{
- std::lock_guard<std::mutex> guard(mutex);
+ const std::lock_guard<std::mutex> guard(mutex);
- assert(id != CACHE_NOID);
- assert(id != CACHE_DUMMYID);
- assert(id >= 0);
- assert(id < (int)id2cache.size());
- assert(id2cache[id].id == id);
+ assert(cacheid != CACHE_NOID);
+ assert(cacheid != CACHE_DUMMYID);
+ assert(cacheid >= 0);
+ assert(cacheid < (int)id2cache.size());
+ assert(id2cache[cacheid].id == cacheid);
- return id2cache[id];
+ return id2cache[cacheid];
}
-cacheid_t AudioCacheIDManager::registerID(const cache_t& cache)
+cacheid_t AudioCacheIDManager::registerID(const CacheBuffer& cache)
{
- std::lock_guard<std::mutex> guard(mutex);
+ const std::lock_guard<std::mutex> guard(mutex);
- cacheid_t id = CACHE_NOID;
+ cacheid_t cacheid = CACHE_NOID;
if(available_ids.empty())
{
@@ -71,32 +87,32 @@ cacheid_t AudioCacheIDManager::registerID(const cache_t& cache)
}
else
{
- id = available_ids.back();
+ cacheid = available_ids.back();
available_ids.pop_back();
}
- assert(id2cache[id].id == CACHE_NOID); // Make sure it is not already in use
+ assert(id2cache[cacheid].id == CACHE_NOID); // Make sure it is not already in use
- id2cache[id] = cache;
- id2cache[id].id = id;
+ id2cache[cacheid] = cache;
+ id2cache[cacheid].id = cacheid;
- return id;
+ return cacheid;
}
-void AudioCacheIDManager::releaseID(cacheid_t id)
+void AudioCacheIDManager::releaseID(cacheid_t cacheid)
{
- std::lock_guard<std::mutex> guard(mutex);
+ const std::lock_guard<std::mutex> guard(mutex);
- assert(id2cache[id].id != CACHE_NOID); // Test if it wasn't already released.
+ assert(id2cache[cacheid].id != CACHE_NOID); // Test if it wasn't already released.
- id2cache[id].id = CACHE_NOID;
+ id2cache[cacheid].id = CACHE_NOID;
- available_ids.push_back(id);
+ available_ids.push_back(cacheid);
}
void AudioCacheIDManager::disableActive()
{
- // Run through all active cache_ts and disable them.
+ // Run through all active CacheBuffers and disable them.
for(auto& cache : id2cache)
{
if(cache.id != CACHE_NOID)
diff --git a/src/audiocacheidmanager.h b/src/audiocacheidmanager.h
index 0aa40e3..d440415 100644
--- a/src/audiocacheidmanager.h
+++ b/src/audiocacheidmanager.h
@@ -26,35 +26,40 @@
*/
#pragma once
-#include <stdlib.h>
+#include <cstdlib>
#include <vector>
-
-#include <audiotypes.h>
-
#include <mutex>
+#include "audiotypes.h"
+#include "owner.h"
+
class AudioCacheFile;
-#define CACHE_DUMMYID -2
-#define CACHE_NOID -1
+using cacheid_t = int;
-typedef int cacheid_t;
+constexpr cacheid_t CACHE_DUMMYID{-2};
+constexpr cacheid_t CACHE_NOID{-1};
-struct cache_t
+class CacheBuffer
{
- cacheid_t id{CACHE_NOID}; //< Current id of this cache_t. CACHE_NOID means not in use.
+public:
+ void allocBack(std::size_t chunk_size);
+ void deleteChunks() const;
+ void swap() noexcept;
+
+ cacheid_t id{CACHE_NOID}; //< Current id of this CacheBuffer. CACHE_NOID means not in use.
- AudioCacheFile* afile{nullptr};
- size_t channel{0};
- size_t pos{0}; //< File position
+ AudioCacheFile* afile{};
+ size_t channel{};
+ size_t pos{}; //< File position
volatile bool ready{false};
- sample_t* front{nullptr};
- sample_t* back{nullptr};
- size_t localpos{0}; //< Intra buffer (front) position.
+ gsl::owner<sample_t*> front{};
+ gsl::owner<sample_t*> back{};
+ size_t localpos{}; //< Intra buffer (front) position.
- sample_t* preloaded_samples{nullptr}; // nullptr means preload buffer not active.
- size_t preloaded_samples_size{0};
+ sample_t* preloaded_samples{}; // nullptr means preload buffer not active.
+ size_t preloaded_samples_size{};
};
class AudioCacheIDManager
@@ -71,16 +76,16 @@ public:
//! Get the cache object connected with the specified cacheid.
//! Note: The cacheid MUST be active.
- cache_t& getCache(cacheid_t id);
+ CacheBuffer& getCache(cacheid_t cacheid);
//! Reserve a new cache object and return its cacheid.
//! The contents of the supplied cache object will be copied to the new
//! cache object.
- cacheid_t registerID(const cache_t& cache);
+ cacheid_t registerID(const CacheBuffer& cache);
//! Release a cache object and its correseponding cacheid.
//! After this call the cacheid can no longer be used.
- void releaseID(cacheid_t id);
+ void releaseID(cacheid_t cacheid);
protected:
// For AudioCacheEventHandler
@@ -89,6 +94,6 @@ protected:
std::mutex mutex;
- std::vector<cache_t> id2cache;
+ std::vector<CacheBuffer> id2cache;
std::vector<cacheid_t> available_ids;
};
diff --git a/src/audiofile.cc b/src/audiofile.cc
index 2d61eb5..1228044 100644
--- a/src/audiofile.cc
+++ b/src/audiofile.cc
@@ -30,6 +30,7 @@
#include <cassert>
#include <sndfile.h>
+#include <array>
#include <config.h>
@@ -37,9 +38,9 @@
#include "channel.h"
-AudioFile::AudioFile(const std::string& filename, std::size_t filechannel,
+AudioFile::AudioFile(std::string filename, std::size_t filechannel,
InstrumentChannel* instrument_channel)
- : filename(filename)
+ : filename(std::move(filename))
, filechannel(filechannel)
, magic{this}
, instrument_channel(instrument_channel)
@@ -61,9 +62,9 @@ bool AudioFile::isValid() const
void AudioFile::unload()
{
// Make sure we don't unload the object while loading it...
- std::lock_guard<std::mutex> guard(mutex);
+ const std::lock_guard<std::mutex> guard(mutex);
- is_loaded = false;
+ is_loaded.store(false);
preloadedsize = 0;
size = 0;
@@ -71,28 +72,28 @@ void AudioFile::unload()
data = nullptr;
}
-#define BUFFER_SIZE 4096
+constexpr std::size_t buffer_size{4096};
-void AudioFile::load(LogFunction logger, std::size_t sample_limit)
+void AudioFile::load(const LogFunction& logger, std::size_t sample_limit)
{
// Make sure we don't unload the object while loading it...
- std::lock_guard<std::mutex> guard(mutex);
+ const std::lock_guard<std::mutex> guard(mutex);
- if(this->data) // already loaded
+ if(this->data != nullptr) // already loaded
{
return;
}
SF_INFO sf_info{};
- SNDFILE *fh = sf_open(filename.c_str(), SFM_READ, &sf_info);
- if(!fh)
+ SNDFILE *file_handle = sf_open(filename.c_str(), SFM_READ, &sf_info);
+ if(file_handle == nullptr)
{
ERR(audiofile,"SNDFILE Error (%s): %s\n",
- filename.c_str(), sf_strerror(fh));
+ filename.c_str(), sf_strerror(file_handle));
if(logger)
{
logger(LogLevel::Warning, "Could not load '" + filename +
- "': " + sf_strerror(fh));
+ "': " + sf_strerror(file_handle));
}
return;
}
@@ -108,7 +109,7 @@ void AudioFile::load(LogFunction logger, std::size_t sample_limit)
return;
}
- std::size_t size = sf_info.frames;
+ const std::size_t size = sf_info.frames;
std::size_t preloadedsize = sf_info.frames;
if(preloadedsize > sample_limit)
@@ -116,10 +117,12 @@ void AudioFile::load(LogFunction logger, std::size_t sample_limit)
preloadedsize = sample_limit;
}
- sample_t* data = new sample_t[preloadedsize];
+ gsl::owner<sample_t*> data{};
+ data = new sample_t[preloadedsize];
if(sf_info.channels == 1)
{
- preloadedsize = sf_read_float(fh, data, preloadedsize);
+ preloadedsize =
+ sf_read_float(file_handle, data, static_cast<sf_count_t>(preloadedsize));
}
else
{
@@ -134,19 +137,22 @@ void AudioFile::load(LogFunction logger, std::size_t sample_limit)
filechannel = sf_info.channels - 1;
}
- sample_t buffer[BUFFER_SIZE];
- std::size_t frame_count = BUFFER_SIZE / sf_info.channels;
- std::size_t total_frames_read = 0;
- int frames_read;
+ std::array<sample_t, buffer_size> buffer{};
+ const sf_count_t frame_count{static_cast<sf_count_t>(buffer.size()) /
+ sf_info.channels};
+ std::size_t total_frames_read{};
+ std::size_t frames_read{};
do
{
- frames_read = sf_readf_float(fh, buffer, frame_count);
- for(int i = 0;
+ frames_read = static_cast<std::size_t>(
+ sf_readf_float(file_handle, buffer.data(), frame_count));
+ for(std::size_t i = 0;
(i < frames_read) && (total_frames_read < sample_limit);
++i)
{
- data[total_frames_read++] = buffer[i * sf_info.channels + filechannel];
+ data[total_frames_read++] =
+ buffer[i * sf_info.channels + filechannel]; // NOLINT - span
}
}
while( (frames_read > 0) &&
@@ -157,17 +163,17 @@ void AudioFile::load(LogFunction logger, std::size_t sample_limit)
preloadedsize = total_frames_read;
}
- sf_close(fh);
+ sf_close(file_handle);
this->data = data;
this->size = size;
this->preloadedsize = preloadedsize;
- is_loaded = true;
+ is_loaded.store(true);
}
bool AudioFile::isLoaded() const
{
- return is_loaded;
+ return is_loaded.load();
}
main_state_t AudioFile::mainState() const
diff --git a/src/audiofile.h b/src/audiofile.h
index 504d0ae..cff4f3b 100644
--- a/src/audiofile.h
+++ b/src/audiofile.h
@@ -31,28 +31,31 @@
#include <vector>
#include <limits>
#include <mutex>
+#include <atomic>
#include "audio.h"
#include "channel.h"
#include "logger.h"
+#include "owner.h"
class InstrumentChannel;
class AudioFile
{
public:
- AudioFile(const std::string& filename, std::size_t filechannel,
+ AudioFile(std::string filename, std::size_t filechannel,
InstrumentChannel* instrument_channel = nullptr);
~AudioFile();
- void load(LogFunction logger, std::size_t sample_limit = std::numeric_limits<std::size_t>::max());
+ void load(const LogFunction& logger,
+ std::size_t sample_limit = std::numeric_limits<std::size_t>::max());
void unload();
bool isLoaded() const;
volatile std::size_t size{0}; // Full size of the file
volatile std::size_t preloadedsize{0}; // Number of samples preloaded (in data)
- sample_t* data{nullptr};
+ gsl::owner<sample_t*> data{nullptr};
std::string filename;
@@ -70,7 +73,7 @@ private:
friend class DOMLoaderTest;
friend class InstrumentParserTest;
- void* magic{nullptr};
- volatile bool is_loaded{false};
- InstrumentChannel* instrument_channel;
+ void* magic{};
+ std::atomic<bool> is_loaded{false};
+ InstrumentChannel* instrument_channel{};
};
diff --git a/src/audioinputengine.h b/src/audioinputengine.h
index 71a86c2..55a06ae 100644
--- a/src/audioinputengine.h
+++ b/src/audioinputengine.h
@@ -29,7 +29,7 @@
#include <string>
#include <vector>
-#include <event.h>
+#include "engineevent.h"
#include "instrument.h"
diff --git a/src/audioinputenginemidi.cc b/src/audioinputenginemidi.cc
index 69aeeb6..2e794f4 100644
--- a/src/audioinputenginemidi.cc
+++ b/src/audioinputenginemidi.cc
@@ -28,26 +28,20 @@
#include "midimapparser.h"
-#include "drumgizmo.h"
+#include <cassert>
#include <hugin.hpp>
-AudioInputEngineMidi::AudioInputEngineMidi()
- : refs(REFSFILE)
-{
- is_valid = false;
-}
-
-bool AudioInputEngineMidi::loadMidiMap(const std::string& file,
+bool AudioInputEngineMidi::loadMidiMap(const std::string& midimap_file,
const Instruments& instruments)
{
- std::string f = file;
+ std::string file = midimap_file;
if(refs.load())
{
if(file.size() > 1 && file[0] == '@')
{
- f = refs.getValue(file.substr(1));
+ file = refs.getValue(file.substr(1));
}
}
else
@@ -58,16 +52,16 @@ bool AudioInputEngineMidi::loadMidiMap(const std::string& file,
midimap = "";
is_valid = false;
- DEBUG(mmap, "loadMidiMap(%s, i.size() == %d)\n", f.c_str(),
+ DEBUG(mmap, "loadMidiMap(%s, i.size() == %d)\n", file.c_str(),
(int)instruments.size());
- if(f == "")
+ if(file.empty())
{
return false;
}
MidiMapParser midimap_parser;
- if(!midimap_parser.parseFile(f))
+ if(!midimap_parser.parseFile(file))
{
return false;
}
@@ -75,7 +69,7 @@ bool AudioInputEngineMidi::loadMidiMap(const std::string& file,
instrmap_t instrmap;
for(size_t i = 0; i < instruments.size(); i++)
{
- instrmap[instruments[i]->getName()] = i;
+ instrmap[instruments[i]->getName()] = static_cast<int>(i);
}
mmap.swap(instrmap, midimap_parser.midimap);
@@ -97,12 +91,12 @@ bool AudioInputEngineMidi::isValid() const
}
// Note types:
-static const std::uint8_t NoteOff = 0x80;
-static const std::uint8_t NoteOn = 0x90;
-static const std::uint8_t NoteAftertouch = 0xA0;
+constexpr std::uint8_t NoteOff{0x80};
+constexpr std::uint8_t NoteOn{0x90};
+constexpr std::uint8_t NoteAftertouch{0xA0};
// Note type mask:
-static int const NoteMask = 0xF0;
+constexpr std::uint8_t NoteMask{0xF0};
void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer,
std::size_t midi_buffer_length,
@@ -114,13 +108,13 @@ void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer,
return;
}
- auto key = midi_buffer[1];
- auto velocity = midi_buffer[2];
+ auto key = midi_buffer[1]; // NOLINT - span
+ auto velocity = midi_buffer[2]; // NOLINT - span
auto instrument_idx = mmap.lookup(key);
auto instruments = mmap.lookup(key);
for(const auto& instrument_idx : instruments)
{
- switch(midi_buffer[0] & NoteMask)
+ switch(midi_buffer[0] & NoteMask) // NOLINT - span
{
case NoteOff:
// Ignore for now
@@ -129,8 +123,12 @@ void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer,
case NoteOn:
if(velocity != 0)
{
+ constexpr float lower_offset{0.5f};
+ constexpr float midi_velocity_max{127.0f};
// maps velocities to [.5/127, 126.5/127]
- auto centered_velocity = (velocity-.5f)/127.0f;
+ assert(velocity <= 127); // MIDI only support up to 127
+ auto centered_velocity =
+ (static_cast<float>(velocity) - lower_offset) / midi_velocity_max;
events.push_back({EventType::OnSet, (std::size_t)instrument_idx,
offset, centered_velocity});
}
diff --git a/src/audioinputenginemidi.h b/src/audioinputenginemidi.h
index 8da7bd2..386a055 100644
--- a/src/audioinputenginemidi.h
+++ b/src/audioinputenginemidi.h
@@ -37,7 +37,7 @@ class AudioInputEngineMidi
: public AudioInputEngine
{
public:
- AudioInputEngineMidi();
+ AudioInputEngineMidi() = default;
virtual ~AudioInputEngineMidi() = default;
virtual bool init(const Instruments &instruments) = 0;
@@ -51,14 +51,15 @@ public:
virtual void run(size_t pos, size_t len, std::vector<event_t>& events) = 0;
virtual void post() = 0;
- virtual bool loadMidiMap(const std::string& file, const Instruments& i);
+ virtual bool loadMidiMap(const std::string& midimap_file,
+ const Instruments& i);
std::string getMidimapFile() const;
bool isValid() const;
- void processNote(const std::uint8_t* note_data,
- std::size_t note_data_size,
+ void processNote(const std::uint8_t* midi_buffer,
+ std::size_t midi_buffer_length,
std::size_t offset,
std::vector<event_t>& events);
@@ -67,7 +68,7 @@ protected:
private:
std::string midimap;
- bool is_valid;
+ bool is_valid{false};
- ConfigFile refs;
+ ConfigFile refs{REFSFILE};
};
diff --git a/src/audiooutputengine.h b/src/audiooutputengine.h
index f69fd75..a69c56d 100644
--- a/src/audiooutputengine.h
+++ b/src/audiooutputengine.h
@@ -29,7 +29,7 @@
#include <cstddef>
#include <string>
-#include <audiotypes.h>
+#include "audiotypes.h"
#include "channel.h"
diff --git a/src/bytesizeparser.cc b/src/bytesizeparser.cc
index 08c7b5b..78a525b 100644
--- a/src/bytesizeparser.cc
+++ b/src/bytesizeparser.cc
@@ -25,23 +25,28 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#include "bytesizeparser.h"
+
#include <iostream>
#include <stdexcept>
-
-static std::size_t suffixToSize(const char& suffix)
+namespace {
+std::size_t suffixToSize(const char& suffix)
{
- int size = 1;
+ constexpr std::size_t kilo{10};
+ constexpr std::size_t mega{20};
+ constexpr std::size_t giga{30};
+
+ std::size_t size{1};
switch(suffix)
{
case 'k':
- size <<= 10;
+ size <<= kilo;
break;
case 'M':
- size <<= 20;
+ size <<= mega;
break;
case 'G':
- size <<= 30;
+ size <<= giga;
break;
default:
size = 0;
@@ -49,14 +54,14 @@ static std::size_t suffixToSize(const char& suffix)
}
return size;
}
-
+}
std::size_t byteSizeParser(const std::string& argument)
{
- std::string::size_type suffix_index;
- std::size_t size;
+ std::string::size_type suffix_index{};
+ std::size_t size{};
std::string suffix;
- bool error = false;
+ bool error{false};
if(argument.find('-') != std::string::npos)
{
@@ -69,14 +74,15 @@ std::size_t byteSizeParser(const std::string& argument)
}
catch(std::invalid_argument&)
{
- std::cerr << "Invalid argument for diskstreamsize" << std::endl;
+ std::cerr << "Invalid argument for diskstreamsize\n";
error = true;
}
catch(std::out_of_range&)
{
- std::cerr << "Number too big. Try using bigger suffix for diskstreamsize" << std::endl;
+ std::cerr << "Number too big. Try using bigger suffix for diskstreamsize\n";
error = true;
}
+
if(!error)
{
suffix = argument.substr(suffix_index);
@@ -85,14 +91,17 @@ std::size_t byteSizeParser(const std::string& argument)
error = true;
}
}
- if(!error && suffix.size() > 0)
+
+ if(!error && !suffix.empty())
{
- std::size_t suffix_size = suffixToSize(suffix[0]);
+ const std::size_t suffix_size = suffixToSize(suffix[0]);
size *= suffix_size;
}
+
if(error)
{
return 0;
}
+
return size;
}
diff --git a/src/bytesizeparser.h b/src/bytesizeparser.h
index 3007454..e1ffeab 100644
--- a/src/bytesizeparser.h
+++ b/src/bytesizeparser.h
@@ -25,8 +25,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#pragma once
-#include <string>
+#include <string>
//! Returns size in bytes
//! \param argument The size in n{k,M,G} format
diff --git a/src/configfile.h b/src/configfile.h
index c17811b..49dbdee 100644
--- a/src/configfile.h
+++ b/src/configfile.h
@@ -30,6 +30,8 @@
#include <map>
#include <fstream>
+static const std::string REFSFILE{"refs.conf"};
+
class ConfigFile
{
public:
diff --git a/src/powermap.cc b/src/curvemap.cc
index 2bb45b7..073dde4 100644
--- a/src/powermap.cc
+++ b/src/curvemap.cc
@@ -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 "powermap.h"
+#include "curvemap.h"
#include <cassert>
#include <cmath>
@@ -32,31 +32,31 @@
namespace
{
-using Power = Powermap::Power;
-using PowerPair = Powermap::PowerPair;
+using CurveValue = CurveMap::CurveValue;
+using CurveValuePair = CurveMap::CurveValuePair;
-Power h00(Power x)
+CurveValue h00(CurveValue x)
{
return (1 + 2 * x) * pow(1 - x, 2);
}
-Power h10(Power x)
+CurveValue h10(CurveValue x)
{
return x * pow(1 - x, 2);
}
-Power h01(Power x)
+CurveValue h01(CurveValue x)
{
return x * x * (3 - 2 * x);
}
-Power h11(Power x)
+CurveValue h11(CurveValue x)
{
return x * x * (x - 1);
}
-Power computeValue(const Power x, const PowerPair& P0, const PowerPair& P1,
- const Power m0, const Power m1)
+CurveValue computeValue(const CurveValue x, const CurveValuePair& P0, const CurveValuePair& P1,
+ const CurveValue m0, const CurveValue m1)
{
const auto x0 = P0.in;
const auto x1 = P1.in;
@@ -74,21 +74,22 @@ Power computeValue(const Power x, const PowerPair& P0, const PowerPair& P1,
} // end anonymous namespace
-Powermap::Powermap()
-{
- reset();
-}
+constexpr std::array<CurveValuePair, 3> CurveMap::default_fixed;
-Power Powermap::map(Power in)
+CurveValue CurveMap::map(CurveValue in)
{
assert(in >= 0. && in <= 1.);
+ if (invert)
+ {
+ in = 1.0 - in;
+ }
if (spline_needs_update)
{
updateSpline();
}
- Power out;
+ CurveValue out;
if (in < fixed[0].in)
{
out = shelf ? fixed[0].out
@@ -113,84 +114,100 @@ Power Powermap::map(Power in)
return out;
}
-void Powermap::reset()
+void CurveMap::reset()
{
- setFixed0({eps, eps});
- setFixed1({.5, .5});
- setFixed2({1 - eps, 1 - eps});
- // FIXME: better false?
- shelf = true;
+ *this = CurveMap{};
updateSpline();
}
-void Powermap::setFixed0(PowerPair new_value)
+void CurveMap::setFixed0(CurveValuePair new_value)
{
- if (fixed[0] != new_value)
+ auto prev = fixed[0];
+ fixed[0].in = clamp(new_value.in, eps, fixed[1].in - eps);
+ fixed[0].out = clamp(new_value.out, eps, fixed[1].out - eps);
+ if (fixed[0] != prev)
{
spline_needs_update = true;
- fixed[0].in = clamp(new_value.in, eps, fixed[1].in - eps);
- fixed[0].out = clamp(new_value.out, eps, fixed[1].out - eps);
}
}
-void Powermap::setFixed1(PowerPair new_value)
+void CurveMap::setFixed1(CurveValuePair new_value)
{
- if (fixed[1] != new_value)
+ auto prev = fixed[1];
+ fixed[1].in = clamp(new_value.in, fixed[0].in + eps, fixed[2].in - eps);
+ fixed[1].out = clamp(new_value.out, fixed[0].out + eps, fixed[2].out - eps);
+ if (fixed[1] != prev)
{
spline_needs_update = true;
- fixed[1].in = clamp(new_value.in, fixed[0].in + eps, fixed[2].in - eps);
- fixed[1].out = clamp(new_value.out, fixed[0].out + eps, fixed[2].out - eps);
}
}
-void Powermap::setFixed2(PowerPair new_value)
+void CurveMap::setFixed2(CurveValuePair new_value)
{
- if (fixed[2] != new_value)
+ auto prev = fixed[2];
+ fixed[2].in = clamp(new_value.in, fixed[1].in + eps, 1 - eps);
+ fixed[2].out = clamp(new_value.out, fixed[1].out + eps, 1 - eps);
+ if (fixed[2] != prev)
{
spline_needs_update = true;
- fixed[2].in = clamp(new_value.in, fixed[1].in + eps, 1 - eps);
- fixed[2].out = clamp(new_value.out, fixed[1].out + eps, 1 - eps);
}
}
-void Powermap::setShelf(bool enable)
+void CurveMap::setInvert(bool enable)
+{
+ if (invert != enable)
+ {
+ spline_needs_update = true;
+ invert = enable;
+ }
+}
+
+void CurveMap::setShelf(bool enable)
{
if (shelf != enable)
{
spline_needs_update = true;
- this->shelf = enable;
+ shelf = enable;
}
}
-PowerPair Powermap::getFixed0() const
+CurveValuePair CurveMap::getFixed0() const
{
return fixed[0];
}
-PowerPair Powermap::getFixed1() const
+CurveValuePair CurveMap::getFixed1() const
{
return fixed[1];
}
-PowerPair Powermap::getFixed2() const
+CurveValuePair CurveMap::getFixed2() const
{
return fixed[2];
}
+bool CurveMap::getInvert() const {
+ return invert;
+}
+
+bool CurveMap::getShelf() const {
+ return shelf;
+}
+
// This mostly followes the wikipedia article for monotone cubic splines:
// https://en.wikipedia.org/wiki/Monotone_cubic_interpolation
-void Powermap::updateSpline()
+void CurveMap::updateSpline()
{
assert(0. <= fixed[0].in && fixed[0].in < fixed[1].in &&
fixed[1].in < fixed[2].in && fixed[2].in <= 1.);
assert(0. <= fixed[0].out && fixed[0].out <= fixed[1].out &&
fixed[1].out <= fixed[2].out && fixed[2].out <= 1.);
- Powers X = shelf ? Powers{fixed[0].in, fixed[1].in, fixed[2].in}
- : Powers{0., fixed[0].in, fixed[1].in, fixed[2].in, 1.};
- Powers Y = shelf ? Powers{fixed[0].out, fixed[1].out, fixed[2].out}
- : Powers{0., fixed[0].out, fixed[1].out, fixed[2].out, 1.};
+ CurveValues X = shelf ? CurveValues{fixed[0].in, fixed[1].in, fixed[2].in}
+ : CurveValues{0., fixed[0].in, fixed[1].in, fixed[2].in, 1.};
+ CurveValues Y = shelf ? CurveValues{fixed[0].out, fixed[1].out, fixed[2].out}
+ : CurveValues{0., fixed[0].out, fixed[1].out, fixed[2].out, 1.};
auto slopes = calcSlopes(X, Y);
@@ -215,12 +232,12 @@ void Powermap::updateSpline()
// This follows the monotone cubic spline algorithm of Steffen, from:
// "A Simple Method for Monotonic Interpolation in One Dimension"
-std::vector<float> Powermap::calcSlopes(const Powers& X, const Powers& Y)
+std::vector<float> CurveMap::calcSlopes(const CurveValues& X, const CurveValues& Y)
{
- Powers m(X.size());
+ CurveValues m(X.size());
- Powers d(X.size() - 1);
- Powers h(X.size() - 1);
+ CurveValues d(X.size() - 1);
+ CurveValues h(X.size() - 1);
for (std::size_t i = 0; i < d.size(); ++i)
{
h[i] = X[i + 1] - X[i];
@@ -245,7 +262,16 @@ std::vector<float> Powermap::calcSlopes(const Powers& X, const Powers& Y)
return m;
}
-Power Powermap::clamp(Power in, Power min, Power max) const
+CurveValue CurveMap::clamp(CurveValue in, CurveValue min, CurveValue max) const
{
return std::max(min, std::min(in, max));
}
+
+bool CurveMap::operator==(const CurveMap& other) const
+{
+ return getFixed0() == other.getFixed0() &&
+ getFixed1() == other.getFixed1() &&
+ getFixed2() == other.getFixed2() &&
+ getShelf() == other.getShelf() &&
+ getInvert() == other.getInvert();
+}
diff --git a/src/curvemap.h b/src/curvemap.h
new file mode 100644
index 0000000..926543d
--- /dev/null
+++ b/src/curvemap.h
@@ -0,0 +1,94 @@
+/* -*- Mode: c++ -*- */
+/***************************************************************************
+ * curvemap.h
+ *
+ * Fri Apr 17 23:06:12 CEST 2020
+ * Copyright 2020 André Nusser
+ * andre.nusser@googlemail.com
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 <array>
+#include <vector>
+
+class CurveMap
+{
+public:
+ using CurveValue = float;
+ using CurveValues = std::vector<CurveValue>;
+
+ bool operator==(const CurveMap& other) const;
+
+ struct CurveValuePair
+ {
+ CurveValue in;
+ CurveValue out;
+
+ bool operator==(const CurveValuePair& other)
+ {
+ return in == other.in || out == other.out;
+ }
+ bool operator!=(const CurveValuePair& other)
+ {
+ return !(*this == other);
+ }
+ };
+
+ CurveValue map(CurveValue in);
+ void reset();
+
+ void setFixed0(CurveValuePair new_value);
+ void setFixed1(CurveValuePair new_value);
+ void setFixed2(CurveValuePair new_value);
+ void setShelf(bool enable);
+
+ //! If enabled, inversion inverts (1 - x) the input value before mapping
+ //! it through the curve.
+ void setInvert(bool enable);
+
+ CurveValuePair getFixed0() const;
+ CurveValuePair getFixed1() const;
+ CurveValuePair getFixed2() const;
+ bool getShelf() const;
+ bool getInvert() const;
+
+private:
+ static constexpr CurveValue eps = 1e-4;
+ static constexpr std::array<CurveValuePair, 3> default_fixed {
+ CurveValuePair {eps, eps},
+ CurveValuePair {.5, .5},
+ CurveValuePair {1 - eps, 1 - eps}
+ };
+
+ // input parameters (state of this class)
+ std::array<CurveValuePair, 3> fixed { default_fixed };
+ bool shelf { true };
+ bool invert { false };
+
+ // spline parameters (deterministically computed from the input parameters)
+ bool spline_needs_update { true };
+ std::array<float, 5> m { 0, 0, 0, 0, 0 };
+
+ void updateSpline();
+ std::vector<float> calcSlopes(const CurveValues& X, const CurveValues& P);
+
+ CurveValue clamp(CurveValue in, CurveValue min, CurveValue max) const;
+}; \ No newline at end of file
diff --git a/src/directory.cc b/src/directory.cc
index 596b045..27637a9 100644
--- a/src/directory.cc
+++ b/src/directory.cc
@@ -27,14 +27,14 @@
#include "directory.h"
#include <dirent.h>
-#include <stdio.h>
+#include <cstdio>
#include <string>
#include <algorithm>
#include <vector>
-#include <string.h>
+#include <cstring>
#include <unistd.h>
-#include <platform.h>
+#include "platform.h"
#if DG_PLATFORM == DG_PLATFORM_WINDOWS
#include <direct.h>
diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc
index abe57be..093b0bf 100644
--- a/src/drumgizmo.cc
+++ b/src/drumgizmo.cc
@@ -31,9 +31,10 @@
#include <cassert>
#include <cstring>
#include <mutex>
+#include <thread>
+#include <chrono>
-#include <event.h>
-#include <audiotypes.h>
+#include "audiotypes.h"
#include <config.h>
#include <hugin.hpp>
@@ -312,7 +313,7 @@ repeat:
assert(t >= 0);
assert(t < evt.buffer_size - evt.buffer_ptr);
- if(evt.rampdownInProgress() && evt.rampdown_offset < (evt.t + t) &&
+ if(evt.hasRampdown() && evt.rampdown_offset < (pos + t) &&
evt.rampdown_count > 0)
{
if(evt.ramp_length > 0)
@@ -362,6 +363,11 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz)
AudioFile& af = *sample_event.file;
+ while(freewheel && !af.isLoaded())
+ {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+
if(!af.isLoaded() || !af.isValid() || (s == nullptr))
{
// This event cannot be played - schedule for deletion and continue.
@@ -392,7 +398,7 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz)
{
// TODO: We should make all audiofiles reference counted and get rid of this lock.
- std::lock_guard<std::mutex> guard(af.mutex);
+ const std::lock_guard<std::mutex> guard(af.mutex);
renderSampleEvent(sample_event, pos, s, sz);
diff --git a/src/drumgizmo.h b/src/drumgizmo.h
index 89c2960..a47898b 100644
--- a/src/drumgizmo.h
+++ b/src/drumgizmo.h
@@ -46,8 +46,6 @@
#include "inputprocessor.h"
#include "zrwrapper.h"
-#define REFSFILE "refs.conf"
-
class DrumGizmo
{
public:
@@ -105,7 +103,7 @@ protected:
Random rand;
std::array<ZRWrapper, NUM_CHANNELS> zita;
- std::array<std::unique_ptr<sample_t>, NUM_CHANNELS> resampler_input_buffer;
+ std::array<std::unique_ptr<sample_t[]>, NUM_CHANNELS> resampler_input_buffer;
double ratio = 1.0;
std::vector<sample_t> scratch_buffer;
};
diff --git a/src/drumgizmoconf.h b/src/drumgizmoconf.h
index f031730..ee14ec6 100644
--- a/src/drumgizmoconf.h
+++ b/src/drumgizmoconf.h
@@ -26,7 +26,7 @@
*/
#pragma once
-#include <configfile.h>
+#include "configfile.h"
class DrumgizmoConfig
: public ConfigFile
diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc
index 9167201..b3a0e5b 100644
--- a/src/drumkitloader.cc
+++ b/src/drumkitloader.cc
@@ -38,8 +38,6 @@
#include "domloader.h"
#include "directory.h"
-#define REFSFILE "refs.conf"
-
DrumKitLoader::DrumKitLoader(Settings& settings, DrumKit& kit,
AudioInputEngine& ie,
Random& rand,
@@ -93,7 +91,7 @@ void DrumKitLoader::deinit()
framesize_semaphore.post();
{
- std::lock_guard<std::mutex> guard(mutex);
+ const std::lock_guard<std::mutex> guard(mutex);
load_queue.clear();
}
@@ -301,13 +299,13 @@ void DrumKitLoader::loadKitAudio(const DrumKit& kit)
void DrumKitLoader::skip()
{
- std::lock_guard<std::mutex> guard(mutex);
+ const std::lock_guard<std::mutex> guard(mutex);
load_queue.clear();
}
void DrumKitLoader::setFrameSize(std::size_t framesize)
{
- std::lock_guard<std::mutex> guard(mutex);
+ const std::lock_guard<std::mutex> guard(mutex);
this->framesize = framesize;
framesize_semaphore.post(); // Signal that the framesize has been set.
}
@@ -324,7 +322,7 @@ void DrumKitLoader::thread_main()
{
std::size_t size;
{
- std::lock_guard<std::mutex> guard(mutex);
+ const std::lock_guard<std::mutex> guard(mutex);
size = load_queue.size();
}
@@ -367,7 +365,7 @@ void DrumKitLoader::thread_main()
std::string filename;
{
- std::lock_guard<std::mutex> guard(mutex);
+ const std::lock_guard<std::mutex> guard(mutex);
if(load_queue.size() == 0)
{
diff --git a/src/event.h b/src/engineevent.h
index 737fb18..9c60a4a 100644
--- a/src/event.h
+++ b/src/engineevent.h
@@ -1,6 +1,6 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/***************************************************************************
- * event.h
+ * engineevent.h
*
* Fri Jun 3 12:10:50 CEST 2011
* Copyright 2011 Bent Bisballe Nyeng
diff --git a/src/events.h b/src/events.h
index 9e3cae1..538127b 100644
--- a/src/events.h
+++ b/src/events.h
@@ -84,11 +84,12 @@ public:
{
}
- bool rampdownInProgress() const
+ bool hasRampdown() const
{
return rampdown_count != -1;
}
+
cacheid_t cache_id;
sample_t* buffer;
std::size_t buffer_size;
diff --git a/src/inputfilter.h b/src/inputfilter.h
index 45dd01e..128dfb0 100644
--- a/src/inputfilter.h
+++ b/src/inputfilter.h
@@ -26,7 +26,7 @@
*/
#pragma once
-#include <event.h>
+#include "engineevent.h"
//! An abstract filter component for the InputProcessor class filter chain.
class InputFilter
diff --git a/src/inputprocessor.cc b/src/inputprocessor.cc
index 7d12bdd..c0c0e92 100644
--- a/src/inputprocessor.cc
+++ b/src/inputprocessor.cc
@@ -139,20 +139,18 @@ std::size_t InputProcessor::getLatency() const
return latency;
}
-//! Applies choke with rampdown time in ms to event starting at offset.
-static void applyChoke(Settings& settings, SampleEvent& event,
- double length_ms, timepos_t offset)
+void InputProcessor::applyChoke(Settings& settings, SampleEvent& event,
+ double length_ms, timepos_t offset, std::size_t pos)
{
std::size_t ramp_length = (length_ms / 1000.) * settings.samplerate.load();
event.rampdown_count = ramp_length;
- event.rampdown_offset = offset;
+ event.rampdown_offset = offset + pos;
event.ramp_length = ramp_length;
}
-//! Applies choke group actions to active events based on the input event
-static void applyChokeGroup(Settings& settings, DrumKit& kit,
- Instrument& instr, event_t& event,
- EventsDS& events_ds)
+void InputProcessor::applyChokeGroup(Settings& settings, DrumKit& kit,
+ Instrument& instr, event_t& event,
+ EventsDS& events_ds, std::size_t pos)
{
std::size_t instrument_id = event.instrument;
if(instr.getGroup() == "")
@@ -175,16 +173,15 @@ static void applyChokeGroup(Settings& settings, DrumKit& kit,
event_sample.rampdown_count == -1) // Only if not already ramping.
{
// Fixed group rampdown time of 68ms, independent of samplerate
- applyChoke(settings, event_sample, 68, event.offset);
+ applyChoke(settings, event_sample, 68, event.offset, pos);
}
}
}
}
-//! Applies directed choke actions to active events based on the input event
-static void applyDirectedChoke(Settings& settings, DrumKit& kit,
- Instrument& instr, event_t& event,
- EventsDS& events_ds)
+void InputProcessor::applyDirectedChoke(Settings& settings, DrumKit& kit,
+ Instrument& instr, event_t& event,
+ EventsDS& events_ds, std::size_t pos)
{
for(const auto& choke : instr.getChokes())
{
@@ -202,7 +199,7 @@ static void applyDirectedChoke(Settings& settings, DrumKit& kit,
event_sample.rampdown_count == -1) // Only if not already ramping.
{
// choke.choketime is in ms
- applyChoke(settings, event_sample, choke.choketime, event.offset);
+ applyChoke(settings, event_sample, choke.choketime, event.offset, pos);
}
}
}
@@ -245,10 +242,10 @@ bool InputProcessor::processOnset(event_t& event, std::size_t pos,
}
// Mute other instruments in the same instrument/choke group
- applyChokeGroup(settings, kit, *instr, event, events_ds);
+ applyChokeGroup(settings, kit, *instr, event, events_ds, pos);
// Apply directed chokes to mute other instruments if needed
- applyDirectedChoke(settings, kit, *instr, event, events_ds);
+ applyDirectedChoke(settings, kit, *instr, event, events_ds, pos);
auto const power_max = instr->getMaxPower();
auto const power_min = instr->getMinPower();
@@ -266,7 +263,7 @@ bool InputProcessor::processOnset(event_t& event, std::size_t pos,
{
limitVoices(instrument_id,
settings.voice_limit_max.load(),
- settings.voice_limit_rampdown.load());
+ settings.voice_limit_rampdown.load(), pos);
}
//Given that audio files could be invalid, maybe we must add the new
@@ -356,7 +353,7 @@ bool InputProcessor::processChoke(event_t& event,
event_sample.rampdown_count == -1) // Only if not already ramping.
{
// Fixed group rampdown time of 68ms, independent of samplerate
- applyChoke(settings, event_sample, 450, event.offset);
+ applyChoke(settings, event_sample, 450, event.offset, pos);
}
}
}
@@ -397,7 +394,7 @@ bool InputProcessor::processStop(event_t& event)
void InputProcessor::limitVoices(std::size_t instrument_id,
std::size_t max_voices,
- float rampdown_time)
+ float rampdown_time, std::size_t pos)
{
const auto& group_ids=events_ds.getSampleEventGroupIDsOf(instrument_id);
@@ -418,7 +415,7 @@ void InputProcessor::limitVoices(std::size_t instrument_id,
}
const auto& sample=events_ds.get<SampleEvent>(event_ids[0]);
- return !sample.rampdownInProgress();
+ return !sample.hasRampdown();
};
EventGroupIDs non_ramping;
@@ -432,7 +429,6 @@ void InputProcessor::limitVoices(std::size_t instrument_id,
}
//Let us get the eldest...
- //TODO: where is the playhead? Should we add it to the offset?
auto compare_event_offsets =
[this](EventGroupID a, EventGroupID b)
{
@@ -456,6 +452,6 @@ void InputProcessor::limitVoices(std::size_t instrument_id,
for(const auto& event_id : event_ids)
{
auto& sample=events_ds.get<SampleEvent>(event_id);
- applyChoke(settings, sample, rampdown_time, sample.offset);
+ applyChoke(settings, sample, rampdown_time, sample.offset, pos);
}
}
diff --git a/src/inputprocessor.h b/src/inputprocessor.h
index 971cc85..a8dc45b 100644
--- a/src/inputprocessor.h
+++ b/src/inputprocessor.h
@@ -30,13 +30,13 @@
#include <list>
#include <memory>
-#include <event.h>
#include "drumkit.h"
#include "events.h"
#include "events_ds.h"
#include "id.h"
#include "inputfilter.h"
+#include "engineevent.h"
struct Settings;
class Random;
@@ -64,10 +64,23 @@ private:
bool processChoke(event_t& event, std::size_t pos, double resample_ratio);
bool processStop(event_t& event);
+ //! Applies choke with rampdown time in ms to event starting at offset.
+ void applyChoke(Settings& settings, SampleEvent& event,
+ double length_ms, timepos_t offset, std::size_t pos);
+
+ //! Applies choke group actions to active events based on the input event
+ void applyChokeGroup(Settings& settings, DrumKit& kit,
+ Instrument& instr, event_t& event,
+ EventsDS& events_ds, std::size_t pos);
+ //! Applies directed choke actions to active events based on the input event
+ void applyDirectedChoke(Settings& settings, DrumKit& kit,
+ Instrument& instr, event_t& event,
+ EventsDS& events_ds, std::size_t pos);
+
//! Ramps down samples from events_ds is there are more groups playing than
//! max_voices for a given instrument.
void limitVoices(std::size_t instrument_id, std::size_t max_voices,
- float rampdown_time);
+ float rampdown_time, std::size_t pos);
std::vector<std::unique_ptr<InputFilter>> filters;
diff --git a/src/midimapper.cc b/src/midimapper.cc
index b9316c5..345ce2f 100644
--- a/src/midimapper.cc
+++ b/src/midimapper.cc
@@ -30,7 +30,7 @@ std::vector<int> MidiMapper::lookup(int note_id)
{
std::vector<int> instruments;
- std::lock_guard<std::mutex> guard(mutex);
+ const std::lock_guard<std::mutex> guard(mutex);
for(const auto& map_entry : midimap)
{
@@ -49,7 +49,7 @@ std::vector<int> MidiMapper::lookup(int note_id)
void MidiMapper::swap(instrmap_t& instrmap, midimap_t& midimap)
{
- std::lock_guard<std::mutex> guard(mutex);
+ const std::lock_guard<std::mutex> guard(mutex);
std::swap(this->instrmap, instrmap);
std::swap(this->midimap, midimap);
diff --git a/src/nolocale.h b/src/nolocale.h
index 430c38c..7a10a9c 100644
--- a/src/nolocale.h
+++ b/src/nolocale.h
@@ -27,7 +27,7 @@
#pragma once
#include <locale.h>
-#include <stdarg.h>
+#include <cstdarg>
#include <cstdlib>
static inline double atof_nol(const char* nptr)
diff --git a/src/owner.h b/src/owner.h
new file mode 100644
index 0000000..0c67ae5
--- /dev/null
+++ b/src/owner.h
@@ -0,0 +1,24 @@
+//! -*- c++ -*-
+#pragma once
+
+//#include <type_traits> // for enable_if_t, is_convertible, is_assignable
+
+// Taken from the GSL Core Guidelines Support Library
+namespace gsl
+{
+
+//
+// owner
+//
+// `gsl::owner<T>` is designed as a safety mechanism for code that must deal directly with raw pointers that own memory.
+// Ideally such code should be restricted to the implementation of low-level abstractions. `gsl::owner` can also be used
+// as a stepping point in converting legacy code to use more modern RAII constructs, such as smart pointers.
+//
+// T must be a pointer type
+// - disallow construction from any type other than pointer type
+//
+//template <class T, class = std::enable_if_t<std::is_pointer<T>::value>>
+template<typename T>
+using owner = T;
+
+}// gsl::
diff --git a/src/path.cc b/src/path.cc
index 993f9a6..eaa1e04 100644
--- a/src/path.cc
+++ b/src/path.cc
@@ -30,8 +30,8 @@
#include <libgen.h>
#endif/*__MINGW32__*/
-#include <string.h>
-#include <stdlib.h>
+#include <cstring>
+#include <cstdlib>
std::string getPath(const std::string& file)
{
diff --git a/src/powerlist.cc b/src/powerlist.cc
index 23d9795..f852ac9 100644
--- a/src/powerlist.cc
+++ b/src/powerlist.cc
@@ -27,8 +27,8 @@
#include "powerlist.h"
#include <algorithm>
-#include <stdlib.h>
-#include <string.h>
+#include <cstdlib>
+#include <cstring>
#include <hugin.hpp>
@@ -36,7 +36,7 @@
#ifdef __STRICT_ANSI__
#undef __STRICT_ANSI__
#endif
-#include <math.h>
+#include <cmath>
#include "random.h"
#include "settings.h"
@@ -84,6 +84,7 @@ const Channel* PowerList::getMasterChannel()
af->load(nullptr, LOAD_SIZE);
float silence{0.f};
+ (void)silence;
std::size_t silence_length{4u};
for (auto s = af->size; s > 0 && s > af->size - silence_length; --s)
{
diff --git a/src/powermap.h b/src/powermap.h
deleted file mode 100644
index 3a406cc..0000000
--- a/src/powermap.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*- Mode: c++ -*- */
-/***************************************************************************
- * powermap.h
- *
- * Fri Apr 17 23:06:12 CEST 2020
- * Copyright 2020 André Nusser
- * andre.nusser@googlemail.com
- ****************************************************************************/
-
-/*
- * This file is part of DrumGizmo.
- *
- * DrumGizmo is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 3 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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 <array>
-#include <vector>
-
-class Powermap
-{
-public:
- using Power = float;
- using Powers = std::vector<Power>;
- struct PowerPair
- {
- Power in;
- Power out;
-
- bool operator!=(const PowerPair& other)
- {
- return in != other.in || out != other.out;
- }
- };
-
- Powermap();
-
- Power map(Power in);
- void reset();
-
- void setFixed0(PowerPair new_value);
- void setFixed1(PowerPair new_value);
- void setFixed2(PowerPair new_value);
- void setShelf(bool enable);
-
- PowerPair getFixed0() const;
- PowerPair getFixed1() const;
- PowerPair getFixed2() const;
-
-private:
- // input parameters (state of this class)
- std::array<PowerPair, 3> fixed;
- bool shelf;
-
- // spline parameters (deterministically computed from the input parameters)
- bool spline_needs_update;
- std::array<float, 5> m;
- const Power eps = 1e-4;
-
- void updateSpline();
- std::vector<float> calcSlopes(const Powers& X, const Powers& P);
-
- Power clamp(Power in, Power min, Power max) const;
-};
diff --git a/src/powermapfilter.h b/src/powermapfilter.h
index 263f809..b9dfe5b 100644
--- a/src/powermapfilter.h
+++ b/src/powermapfilter.h
@@ -27,7 +27,7 @@
#pragma once
#include "inputfilter.h"
-#include "powermap.h"
+#include "curvemap.h"
struct Settings;
@@ -43,5 +43,5 @@ public:
private:
Settings& settings;
- Powermap powermap;
+ CurveMap powermap;
};
diff --git a/src/sem.cc b/src/sem.cc
index ad5266d..13cfca4 100644
--- a/src/sem.cc
+++ b/src/sem.cc
@@ -28,8 +28,8 @@
#include <hugin.hpp>
#include <limits>
-#include <assert.h>
-#include <string.h>
+#include <cassert>
+#include <cstring>
#include <chrono>
#include <thread>
@@ -37,8 +37,8 @@
#if DG_PLATFORM != DG_PLATFORM_WINDOWS
#include <semaphore.h>
-#include <errno.h>
-#include <stdio.h>
+#include <cerrno>
+#include <cstdio>
#include <sys/time.h>
#endif
diff --git a/src/syncedsettings.h b/src/syncedsettings.h
index 0fe5efd..d12277a 100644
--- a/src/syncedsettings.h
+++ b/src/syncedsettings.h
@@ -64,7 +64,7 @@ public:
: mutex{}
, data{}
{
- std::lock_guard<std::mutex> lock{other.mutex};
+ const std::lock_guard<std::mutex> lock{other.mutex};
data = other.data;
}
@@ -72,7 +72,7 @@ public:
: mutex{}
, data{}
{
- std::lock_guard<std::mutex> lock{other.mutex};
+ const std::lock_guard<std::mutex> lock{other.mutex};
std::swap(data, other.data);
}
@@ -80,19 +80,19 @@ public:
{
if (*this != &other)
{
- std::lock_guard<std::mutex> lock{mutex};
- std::lock_guard<std::mutex> lock2{other.mutex};
+ const std::lock_guard<std::mutex> lock{mutex};
+ const std::lock_guard<std::mutex> lock2{other.mutex};
data = other.data;
}
return *this;
}
-
+
Group<T>& operator=(Group<T>&& other)
{
if (*this != &other)
{
- std::lock_guard<std::mutex> lock{mutex};
- std::lock_guard<std::mutex> lock2{other.mutex};
+ const std::lock_guard<std::mutex> lock{mutex};
+ const std::lock_guard<std::mutex> lock2{other.mutex};
std::swap(data, other.data);
}
return *this;
@@ -100,7 +100,7 @@ public:
operator T() const
{
- std::lock_guard<std::mutex> lock{mutex};
+ const std::lock_guard<std::mutex> lock{mutex};
return data;
}
};
diff --git a/src/translation.cc b/src/translation.cc
index 18763e4..c71f6c0 100644
--- a/src/translation.cc
+++ b/src/translation.cc
@@ -62,13 +62,13 @@ bool comparator(const Text& a, const Text& b)
Translation::Translation()
{
- std::lock_guard<std::mutex>(singleton.mutex);
+ const std::lock_guard<std::mutex> lock(singleton.mutex);
++singleton.refcnt;
}
Translation::~Translation()
{
- std::lock_guard<std::mutex>(singleton.mutex);
+ const std::lock_guard<std::mutex> lock(singleton.mutex);
--singleton.refcnt;
@@ -219,7 +219,7 @@ bool Translation::load(const char* catalog, std::size_t size)
std::sort(texts.begin(), texts.end(), comparator);
{
- std::lock_guard<std::mutex>(singleton.mutex);
+ const std::lock_guard<std::mutex> lock(singleton.mutex);
std::swap(singleton.texts, texts);
}
@@ -228,7 +228,7 @@ bool Translation::load(const char* catalog, std::size_t size)
const char* Translation::gettext(std::uint64_t msgid, const char* original)
{
- std::lock_guard<std::mutex>(singleton.mutex);
+ const std::lock_guard<std::mutex> lock(singleton.mutex);
if(singleton.refcnt == 0)
{
return original;
diff --git a/src/versionstr.cc b/src/versionstr.cc
index 8c6c66f..ac16e41 100644
--- a/src/versionstr.cc
+++ b/src/versionstr.cc
@@ -26,9 +26,8 @@
*/
#include "versionstr.h"
-#include <memory.h>
-#include <stdlib.h>
-#include <stdio.h>
+#include <cstdlib>
+#include <cstdio>
#include <hugin.hpp>
diff --git a/test/Makefile.am b/test/Makefile.am
index 6441fd3..0827cae 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -8,7 +8,7 @@ TESTS = resource enginetest paintertest configfile audiocache \
randomtest atomictest syncedsettingstest imagecachetest \
semaphoretest drumkitcreatortest bytesizeparsertest notifiertest \
dgxmlparsertest domloadertest configparsertest midimapparsertest \
- eventsdstest powermaptest midimappertest
+ eventsdstest curvemaptest midimappertest
if WITH_NLS
TESTS += translationtest
@@ -51,7 +51,8 @@ audiocache_CXXFLAGS = \
-I$(top_srcdir)/src \
-I$(top_srcdir)/hugin -DDISABLE_HUGIN \
$(PTHREAD_CFLAGS) \
- $(SNDFILE_CFLAGS)
+ $(SNDFILE_CFLAGS) \
+ -Wno-deprecated-declarations
audiocache_LDFLAGS = $(PTHREAD_LIBS) $(SNDFILE_LIBS)
audiocache_SOURCES = \
$(top_srcdir)/src/audiocache.cc \
@@ -72,7 +73,8 @@ audiocachefile_CXXFLAGS = \
-I$(top_srcdir)/src \
-I$(top_srcdir)/hugin -DDISABLE_HUGIN \
$(PTHREAD_CFLAGS) \
- $(SNDFILE_CFLAGS)
+ $(SNDFILE_CFLAGS) \
+ -Wno-deprecated-declarations
audiocachefile_LDFLAGS = $(PTHREAD_LIBS) $(SNDFILE_LIBS)
audiocachefile_SOURCES = \
$(top_srcdir)/src/audiocachefile.cc \
@@ -102,7 +104,8 @@ audiocacheeventhandler_CXXFLAGS = \
-I$(top_srcdir)/src \
-I$(top_srcdir)/hugin -DDISABLE_HUGIN \
$(PTHREAD_CFLAGS) \
- $(SNDFILE_CFLAGS)
+ $(SNDFILE_CFLAGS) \
+ -Wno-deprecated-declarations
audiocacheeventhandler_LDFLAGS = $(PTHREAD_LIBS) $(SNDFILE_LIBS)
audiocacheeventhandler_SOURCES = \
$(top_srcdir)/src/audiocacheeventhandler.cc \
@@ -218,7 +221,8 @@ semaphoretest_CXXFLAGS = \
$(DEBUG_FLAGS) \
-I$(top_srcdir)/src \
-I$(top_srcdir)/hugin \
- $(PTHREAD_CFLAGS)
+ $(PTHREAD_CFLAGS) \
+ -Wno-deprecated-declarations
semaphoretest_LDFLAGS = $(PTHREAD_LIBS)
semaphoretest_SOURCES = \
$(top_srcdir)/hugin/hugin.c \
@@ -325,14 +329,14 @@ eventsdstest_SOURCES = \
eventsdstest.cc \
uunit/uunit.cc
-powermaptest_CXXFLAGS = \
- -I$(top_srcdir)/test/uunit -DOUTPUT=\"powermaptest\" \
+curvemaptest_CXXFLAGS = \
+ -I$(top_srcdir)/test/uunit -DOUTPUT=\"curvemaptest\" \
$(DEBUG_FLAGS) \
-I$(top_srcdir)/src
-powermaptest_LDFLAGS =
-powermaptest_SOURCES = \
- $(top_srcdir)/src/powermap.cc \
- powermaptest.cc \
+curvemaptest_LDFLAGS =
+curvemaptest_SOURCES = \
+ $(top_srcdir)/src/curvemap.cc \
+ curvemaptest.cc \
uunit/uunit.cc
midimappertest_CXXFLAGS = \
diff --git a/test/audiocacheidmanagertest.cc b/test/audiocacheidmanagertest.cc
index c84926b..9d8be25 100644
--- a/test/audiocacheidmanagertest.cc
+++ b/test/audiocacheidmanagertest.cc
@@ -52,39 +52,39 @@ public:
TestableAudioCacheIDManager manager;
manager.init(2);
- cache_t c1; c1.afile = (AudioCacheFile*)1;
+ CacheBuffer c1; c1.afile = (AudioCacheFile*)1;
auto id1 = manager.registerID(c1);
uUNIT_ASSERT(id1 != CACHE_DUMMYID);
uUNIT_ASSERT(id1 != CACHE_NOID);
uUNIT_ASSERT_EQUAL(1, manager.getAvailableIDs());
- cache_t c2; c2.afile = (AudioCacheFile*)2;
+ CacheBuffer c2; c2.afile = (AudioCacheFile*)2;
auto id2 = manager.registerID(c2);
uUNIT_ASSERT(id2 != CACHE_DUMMYID);
uUNIT_ASSERT(id2 != CACHE_NOID);
uUNIT_ASSERT_EQUAL(0, manager.getAvailableIDs());
- cache_t c3; c3.afile = (AudioCacheFile*)3;
+ CacheBuffer c3; c3.afile = (AudioCacheFile*)3;
auto id3 = manager.registerID(c3);
uUNIT_ASSERT(id3 == CACHE_DUMMYID);
uUNIT_ASSERT_EQUAL(0, manager.getAvailableIDs());
- cache_t& tc1 = manager.getCache(id1);
+ CacheBuffer& tc1 = manager.getCache(id1);
uUNIT_ASSERT_EQUAL(c1.afile, tc1.afile);
- cache_t& tc2 = manager.getCache(id2);
+ CacheBuffer& tc2 = manager.getCache(id2);
uUNIT_ASSERT_EQUAL(c2.afile, tc2.afile);
manager.releaseID(id1);
uUNIT_ASSERT_EQUAL(1, manager.getAvailableIDs());
- cache_t c4; c4.afile = (AudioCacheFile*)4;
+ CacheBuffer c4; c4.afile = (AudioCacheFile*)4;
auto id4 = manager.registerID(c4);
uUNIT_ASSERT(id4 != CACHE_DUMMYID);
uUNIT_ASSERT(id4 != CACHE_NOID);
uUNIT_ASSERT_EQUAL(0, manager.getAvailableIDs());
- cache_t& tc4 = manager.getCache(id4);
+ CacheBuffer& tc4 = manager.getCache(id4);
uUNIT_ASSERT_EQUAL(c4.afile, tc4.afile);
manager.releaseID(id2);
diff --git a/test/curvemaptest.cc b/test/curvemaptest.cc
new file mode 100644
index 0000000..cb90d1b
--- /dev/null
+++ b/test/curvemaptest.cc
@@ -0,0 +1,267 @@
+/* -*- Mode: c++ -*- */
+/***************************************************************************
+ * curvemaptest.cc
+ *
+ * Fri Jul 26 19:43:32 CEST 2024
+ * Copyright 2024 Sander Vocke
+ * sandervocke@gmail.com
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 <uunit.h>
+#include <map>
+
+#include "../src/curvemap.h"
+#include <iostream>
+#include <iomanip>
+
+class test_curvemaptest
+ : public uUnit
+{
+public:
+ test_curvemaptest()
+ {
+ uUNIT_TEST(test_curvemaptest::check_default);
+ uUNIT_TEST(test_curvemaptest::check_default_invert);
+ uUNIT_TEST(test_curvemaptest::check_default_disabled_shelf);
+ uUNIT_TEST(test_curvemaptest::check_default_disabled_shelf_invert);
+ uUNIT_TEST(test_curvemaptest::check_fixed1_075_025);
+ uUNIT_TEST(test_curvemaptest::check_fixed1_075_025_invert);
+ uUNIT_TEST(test_curvemaptest::check_shelf_060);
+ uUNIT_TEST(test_curvemaptest::check_shelf_060_invert);
+ uUNIT_TEST(test_curvemaptest::check_reset);
+ }
+
+ const std::map<double, double> default_map = {
+ {0.0, 1e-4},
+ {1e-4, 1e-4},
+ {0.1, 0.1},
+ {0.2, 0.2},
+ {0.3, 0.3},
+ {0.4, 0.4},
+ {0.5, 0.5},
+ {0.6, 0.6},
+ {0.7, 0.7},
+ {0.8, 0.8},
+ {0.9, 0.9},
+ {1.0 - 1e-4, 1.0 - 1e-4},
+ {1.0, 1.0 - 1e-4}
+ };
+
+ const std::map<double, double> identity_map = {
+ {0.0, 0.0},
+ {0.1, 0.1},
+ {0.2, 0.2},
+ {0.3, 0.3},
+ {0.4, 0.4},
+ {0.5, 0.5},
+ {0.6, 0.6},
+ {0.7, 0.7},
+ {0.8, 0.8},
+ {0.9, 0.9},
+ {1.0, 1.0}
+ };
+
+ const std::map<double, double> fixed1_075_025_map = {
+ {0.0, 1e-4},
+ {1e-4, 1e-4},
+ {0, 0.0001},
+ {0.1, 0.0295469705015421},
+ {0.2, 0.0536915548145771},
+ {0.3, 0.0760560110211372},
+ {0.4, 0.100195862352848},
+ {0.5, 0.129666686058044},
+ {0.6, 0.168024003505707},
+ {0.7, 0.218823373317719},
+ {0.8, 0.325357049703598},
+ {0.9, 0.64416378736496},
+ {1.0 - 1e-4, 1.0 - 1e-4},
+ {1.0, 1.0 - 1e-4}
+ };
+
+ const std::map<double, double> shelf_060_map = {
+ {0.0, 1e-4},
+ {1e-4, 1e-4},
+ {0.1, 0.1},
+ {0.2, 0.2},
+ {0.3, 0.3},
+ {0.4, 0.4},
+ {0.5, 0.5},
+ {0.6, 0.6},
+ {0.7, 0.6},
+ {0.8, 0.6},
+ {0.9, 0.6},
+ {1.0, 0.6}
+ };
+
+ void check_default()
+ {
+ auto dataset = this->default_map;
+
+ CurveMap map;
+
+ for (auto& entry : dataset) {
+ auto in = entry.first;
+ auto expect = entry.second;
+ uASSERT_EQUAL(expect, map.map(in));
+ }
+ }
+
+ void check_reset()
+ {
+ auto dataset = this->default_map;
+
+ CurveMap map;
+ map.setFixed0({0.1, 0.2});
+ map.setFixed1({0.2, 0.3});
+ map.setFixed2({0.3, 0.4});
+ map.setInvert(!map.getInvert());
+ map.setShelf(!map.getShelf());
+
+ bool any_difference = false;
+ for (auto& entry : dataset) {
+ auto in = entry.first;
+ auto expect = entry.second;
+ if (expect != map.map(in)) {
+ any_difference = true;
+ break;
+ }
+ }
+
+ uASSERT(any_difference);
+
+ map.reset();
+
+ for (auto& entry : dataset) {
+ auto in = entry.first;
+ auto expect = entry.second;
+ uASSERT_EQUAL(expect, map.map(in));
+ }
+ }
+
+ void check_default_invert()
+ {
+ auto dataset = this->default_map;
+
+ CurveMap map;
+ map.setInvert(true);
+
+ for (auto& entry : dataset) {
+ auto in = 1.0 - entry.first;
+ auto expect = entry.second;
+ uASSERT_EQUAL(expect, map.map(in));
+ }
+ }
+
+ void check_default_disabled_shelf()
+ {
+ auto dataset = this->identity_map;
+
+ CurveMap map;
+ map.setShelf(false);
+ map.setFixed2({0.6, 0.6});
+
+ for (auto& entry : dataset) {
+ auto in = entry.first;
+ auto expect = entry.second;
+ // std::cout << "{" << in << ", " << std::setprecision (15) << map.map(in) << "}," << std::endl; // FIXME
+ uASSERT_EQUAL(expect, map.map(in));
+ }
+ }
+
+ void check_default_disabled_shelf_invert()
+ {
+ auto dataset = this->identity_map;
+
+ CurveMap map;
+ map.setShelf(false);
+ map.setFixed2({0.6, 0.6});
+ map.setInvert(true);
+
+ for (auto& entry : dataset) {
+ auto in = 1.0 - entry.first;
+ auto expect = entry.second;
+ uASSERT_EQUAL(expect, map.map(in));
+ }
+ }
+
+ void check_fixed1_075_025()
+ {
+ auto dataset = this->fixed1_075_025_map;
+
+ CurveMap map;
+ map.setFixed1({0.75, 0.25});
+
+ for (auto& entry : dataset) {
+ auto in = entry.first;
+ auto expect = entry.second;
+ // std::cout << "{" << in << ", " << std::setprecision (15) << map.map(in) << "}," << std::endl; // FIXME
+ uASSERT_EQUAL(expect, map.map(in));
+ }
+ }
+
+ void check_fixed1_075_025_invert()
+ {
+ auto dataset = this->fixed1_075_025_map;
+
+ CurveMap map;
+ map.setFixed1({0.75, 0.25});
+ map.setInvert(true);
+
+ for (auto& entry : dataset) {
+ auto in = 1.0 - entry.first;
+ auto expect = entry.second;
+ uASSERT_EQUAL(expect, map.map(in));
+ }
+ }
+
+ void check_shelf_060()
+ {
+ auto dataset = this->shelf_060_map;
+
+ CurveMap map;
+ map.setFixed2({0.6, 0.6});
+ map.setShelf(true);
+
+ for (auto& entry : dataset) {
+ auto in = entry.first;
+ auto expect = entry.second;
+ uASSERT_EQUAL(expect, map.map(in));
+ }
+ }
+
+ void check_shelf_060_invert()
+ {
+ auto dataset = this->shelf_060_map;
+
+ CurveMap map;
+ map.setFixed2({0.6, 0.6});
+ map.setShelf(true);
+ map.setInvert(true);
+
+ for (auto& entry : dataset) {
+ auto in = 1.0 - entry.first;
+ auto expect = entry.second;
+ uASSERT_EQUAL(expect, map.map(in));
+ }
+ }
+};
+
+// Registers the fixture into the 'registry'
+static test_curvemaptest test;
diff --git a/test/dgreftest/midiinputengine.h b/test/dgreftest/midiinputengine.h
index ffd22f8..e76a182 100644
--- a/test/dgreftest/midiinputengine.h
+++ b/test/dgreftest/midiinputengine.h
@@ -26,15 +26,15 @@
*/
#pragma once
-#include <audioinputenginemidi.h>
-#include <midimapper.h>
-#include <midimapparser.h>
#include <string>
#include <vector>
-#include <event.h>
#include <smf.h>
+#include <audioinputenginemidi.h>
+#include <midimapper.h>
+#include <midimapparser.h>
+
class MidifileInputEngine
: public AudioInputEngineMidi
{
diff --git a/test/paintertest.cc b/test/paintertest.cc
index 5a1c44a..10b96dc 100644
--- a/test/paintertest.cc
+++ b/test/paintertest.cc
@@ -91,7 +91,7 @@ public:
has_alpha = alpha;
image_data.resize(_width * _height);
- image_data_raw.resize(_width * _height);
+ image_data_raw.resize(4 * _width * _height);
// Store x and y coordinates as red and green colour components
for(std::uint8_t x = 0; x < _width; ++x)
diff --git a/test/powermaptest.cc b/test/powermaptest.cc
deleted file mode 100644
index bef5bdc..0000000
--- a/test/powermaptest.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*- Mode: c++ -*- */
-/***************************************************************************
- * powermaptest.cc
- *
- * Sun Apr 19 23:23:37 CEST 2020
- * Copyright 2020 André Nusser
- * andre.nusser@googlemail.com
- ****************************************************************************/
-
-/*
- * This file is part of DrumGizmo.
- *
- * DrumGizmo is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 3 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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 <uunit.h>
-
-#include "../src/powermap.h"
-
-class test_powermaptest
- : public uUnit
-{
-public:
- test_powermaptest()
- {
- uUNIT_TEST(test_powermaptest::check_values);
- }
-
- void check_values()
- {
- Powermap powermap;
-
- // TODO
- // std::cout << powermap.map(.8) << std::endl;
- // uUNIT_ASSERT_EQUAL(powermap.map(.8), .8);
- }
-};
-
-// Registers the fixture into the 'registry'
-static test_powermaptest test;
diff --git a/tools/add_file b/tools/add_file
index a704029..51d50b4 100755
--- a/tools/add_file
+++ b/tools/add_file
@@ -26,6 +26,10 @@ function allfile() {
then
NAME="Goran Mekić"; EMAIL="meka@tilda.center"
fi
+ if [ "$USER" == "sander" ]
+ then
+ NAME="Sander Vocke"; EMAIL="sandervocke@gmail.com"
+ fi
echo "/* -*- Mode: c++ -*- */" > $1;
echo "/***************************************************************************" >> $1;
diff --git a/version.h b/version.h
index 311c449..a0ac531 100644
--- a/version.h
+++ b/version.h
@@ -1 +1 @@
-#define VERSION "0.9.19"
+#define VERSION "0.9.20"