summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/DGDOM.h2
-rw-r--r--src/Makefile.am90
-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.cc50
-rw-r--r--src/audiofile.h12
-rw-r--r--src/audioinputengine.h2
-rw-r--r--src/audioinputenginemidi.cc55
-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/dgxmlparser.cc4
-rw-r--r--src/directory.cc6
-rw-r--r--src/drumgizmo.cc7
-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.cc57
-rw-r--r--src/inputprocessor.h17
-rw-r--r--src/instrument.cc39
-rw-r--r--src/instrument.h14
-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/position_power.cc99
-rw-r--r--src/position_power.h87
-rw-r--r--src/powerlist.cc7
-rw-r--r--src/sample_selection.cc65
-rw-r--r--src/sample_selection.h3
-rw-r--r--src/sem.cc8
-rw-r--r--src/settings.h4
-rw-r--r--src/syncedsettings.h16
-rw-r--r--src/translation.cc8
-rw-r--r--src/versionstr.cc5
48 files changed, 766 insertions, 446 deletions
diff --git a/src/DGDOM.h b/src/DGDOM.h
index a03f0ef..b4e861f 100644
--- a/src/DGDOM.h
+++ b/src/DGDOM.h
@@ -59,7 +59,7 @@ struct SampleDOM
{
std::string name;
double power; // >= v2.0 only
- double position; // >=v2.0 only
+ double position; // >= v2.0 only
bool normalized; // >= v2.0 only
std::vector<AudioFileDOM> audiofiles;
};
diff --git a/src/Makefile.am b/src/Makefile.am
index cecb49b..eb6f214 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,50 +33,52 @@ 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 \
- positionfilter.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/powermap.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/positionfilter.cc \
+ $(top_srcdir)/src/position_power.cc \
+ $(top_srcdir)/src/versionstr.cc
EXTRA_DIST = \
$(libzr_la_SOURCES) \
@@ -107,7 +109,7 @@ EXTRA_DIST = \
drumgizmoconf.h \
drumkit.h \
drumkitloader.h \
- event.h \
+ engineevent.h \
events.h \
events_ds.h \
grid.h \
@@ -122,6 +124,7 @@ EXTRA_DIST = \
midimapper.h \
nolocale.h \
notifier.h \
+ owner.h \
path.h \
platform.h \
powerlist.h \
@@ -142,3 +145,10 @@ EXTRA_DIST = \
positionfilter.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..6fcdcb5 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,7 +62,7 @@ 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;
@@ -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,7 +163,7 @@ 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;
diff --git a/src/audiofile.h b/src/audiofile.h
index 504d0ae..9fdd8c5 100644
--- a/src/audiofile.h
+++ b/src/audiofile.h
@@ -35,24 +35,26 @@
#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 +72,7 @@ private:
friend class DOMLoaderTest;
friend class InstrumentParserTest;
- void* magic{nullptr};
+ void* magic{};
volatile bool is_loaded{false};
- InstrumentChannel* instrument_channel;
+ 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 0dee346..240acc3 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,16 +91,13 @@ 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;
-static const std::uint8_t ControlChange = 0xB0;
+constexpr std::uint8_t NoteOff{0x80};
+constexpr std::uint8_t NoteOn{0x90};
+constexpr std::uint8_t NoteAftertouch{0xA0};
+constexpr std::uint8_t ControlChange{0xB0};
// Note type mask:
-static const std::uint8_t TypeMask = 0xF0;
-
-// See:
-// https://www.midi.org/specifications-old/item/table-1-summary-of-midi-message
+constexpr std::uint8_t NoteMask{0xF0};
void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer,
std::size_t midi_buffer_length,
@@ -118,7 +109,7 @@ void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer,
return;
}
- switch(midi_buffer[0] & TypeMask)
+ switch(midi_buffer[0] & NoteMask) // NOLINT - span
{
case NoteOff:
// Ignore for now
@@ -126,15 +117,19 @@ void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer,
case NoteOn:
{
- 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 instruments = mmap.lookup(key);
for(const auto& instrument_idx : instruments)
{
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, positional_information});
}
@@ -144,8 +139,8 @@ void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer,
case NoteAftertouch:
{
- 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 instruments = mmap.lookup(key);
for(const auto& instrument_idx : instruments)
{
@@ -160,8 +155,8 @@ void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer,
case ControlChange:
{
- auto controller_number = midi_buffer[1];
- auto value = midi_buffer[2];
+ auto controller_number = midi_buffer[1]; // NOLINT - span
+ auto value = midi_buffer[2]; // NOLINT - span
if(controller_number == 16) // positional information
{
// Store value for use in next NoteOn event.
diff --git a/src/audioinputenginemidi.h b/src/audioinputenginemidi.h
index 12efd66..28da538 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,9 +68,9 @@ protected:
private:
std::string midimap;
- bool is_valid;
+ bool is_valid{false};
- ConfigFile refs;
+ ConfigFile refs{REFSFILE};
float positional_information{0.0f};
};
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/dgxmlparser.cc b/src/dgxmlparser.cc
index bd9af66..837cc4e 100644
--- a/src/dgxmlparser.cc
+++ b/src/dgxmlparser.cc
@@ -365,8 +365,8 @@ bool parseInstrumentFile(const std::string& filename, InstrumentDOM& dom, LogFun
res &= attrcpy(dom.samples.back().position, sample, "position",
logger, filename, true);
// Clamp to [0; 1] range.
- dom.samples.back().position =
- std::min(1.0, std::max(dom.samples.back().position, 0.0));
+ //dom.samples.back().position =
+ // std::min(1.0, std::max(dom.samples.back().position, 0.0));
dom.samples.back().normalized = false; // optional - defaults to false
res &= attrcpy(dom.samples.back().normalized, sample, "normalized",
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..85624ca 100644
--- a/src/drumgizmo.cc
+++ b/src/drumgizmo.cc
@@ -32,8 +32,7 @@
#include <cstring>
#include <mutex>
-#include <event.h>
-#include <audiotypes.h>
+#include "audiotypes.h"
#include <config.h>
#include <hugin.hpp>
@@ -312,7 +311,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)
@@ -392,7 +391,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 5780cc9..bf2b712 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 00374d4..29c4ac5 100644
--- a/src/inputprocessor.cc
+++ b/src/inputprocessor.cc
@@ -37,7 +37,7 @@
#include "staminafilter.h"
#include "velocityfilter.h"
#include "positionfilter.h"
-
+#include <iostream>
#include "cpp11fix.h"
class VelocityStorer
@@ -141,20 +141,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() == "")
@@ -177,16 +175,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())
{
@@ -204,7 +201,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);
}
}
}
@@ -247,17 +244,20 @@ 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);
+
+ const auto power_range = instr->getPowers(event.position);
+ const auto power_span = power_range.max - power_range.min;
+ const auto note_power = power_range.min + event.velocity * power_span;
+
+ const auto position_range = instr->getPositionRange();
+ const auto position_span = position_range.max - position_range.min;
+ const auto note_position = position_range.min + event.position * position_span;
- auto const power_max = instr->getMaxPower();
- auto const power_min = instr->getMinPower();
- float const power_span = power_max - power_min;
- float const instrument_level = power_min + event.velocity*power_span;
- // FIXME: bad variable naming of parameters
- const auto sample = instr->sample(instrument_level, event.position, event.offset + pos);
+ const auto sample = instr->sample(note_power, power_span, note_position, position_span, event.offset + pos);
if(sample == nullptr)
{
@@ -269,7 +269,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
@@ -359,7 +359,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);
}
}
}
@@ -400,7 +400,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);
@@ -421,7 +421,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;
@@ -435,7 +435,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)
{
@@ -459,6 +458,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/instrument.cc b/src/instrument.cc
index ac6aa28..af96ab6 100644
--- a/src/instrument.cc
+++ b/src/instrument.cc
@@ -29,6 +29,7 @@
#include <hugin.hpp>
#include "sample.h"
+#include "position_power.h"
Instrument::Instrument(Settings& settings, Random& rand)
: settings(settings)
@@ -36,7 +37,6 @@ Instrument::Instrument(Settings& settings, Random& rand)
, sample_selection(settings, rand, powerlist)
{
DEBUG(instrument, "new %p\n", this);
- mod = 1.0;
lastpos = 0;
magic = this;
@@ -55,17 +55,19 @@ bool Instrument::isValid() const
}
// FIXME: very bad variable naming of parameters
-const Sample* Instrument::sample(level_t level, float position , std::size_t pos)
+const Sample* Instrument::sample(float power, float instrument_power_range, float position,
+ float instrument_position_range, std::size_t pos)
{
if(version >= VersionStr("2.0"))
{
// Version 2.0
- return sample_selection.get(level * mod, position, pos);
+ return sample_selection.get(power, instrument_power_range,
+ position, instrument_position_range, pos);
}
else
{
// Version 1.0
- auto s = samples.get(level * mod);
+ auto s = samples.get(power);
if(s.size() == 0)
{
return nullptr;
@@ -93,6 +95,18 @@ void Instrument::finalise()
powerlist.finalise();
sample_selection.finalise();
+
+ position_range.min = std::numeric_limits<double>::max();
+ position_range.max = std::numeric_limits<double>::min();
+ if(samplelist.empty())
+ {
+ position_range = {0,1};
+ }
+ for(const auto& sample : samplelist)
+ {
+ position_range.min = std::min(sample->getPosition(), position_range.min);
+ position_range.max = std::max(sample->getPosition(), position_range.max);
+ }
}
}
@@ -130,28 +144,21 @@ std::size_t Instrument::getNumberOfFiles() const
return audiofiles.size();
}
-float Instrument::getMaxPower() const
+Instrument::PowerRange Instrument::getPowers(float position) const
{
if(version >= VersionStr("2.0"))
{
- return powerlist.getMaxPower();
+ return positionPower(samplelist, position);
}
else
{
- return 1.0f;
+ return { 0.0f, 1.0f };
}
}
-float Instrument::getMinPower() const
+Instrument::PowerRange Instrument::getPositionRange() const
{
- if(version >= VersionStr("2.0"))
- {
- return powerlist.getMinPower();
- }
- else
- {
- return 0.0f;
- }
+ return position_range;
}
const std::vector<Choke>& Instrument::getChokes()
diff --git a/src/instrument.h b/src/instrument.h
index 89918de..35f4e5b 100644
--- a/src/instrument.h
+++ b/src/instrument.h
@@ -50,7 +50,8 @@ public:
~Instrument();
// FIXME: variable naming
- const Sample* sample(level_t level, float position, std::size_t pos);
+ const Sample* sample(float power, float instrument_power_range, float position,
+ float instrument_position_range, std::size_t pos);
std::size_t getID() const;
const std::string& getName() const;
@@ -68,8 +69,13 @@ public:
//! Get the number of audio files (as in single channel) in this instrument.
std::size_t getNumberOfFiles() const;
- float getMaxPower() const;
- float getMinPower() const;
+ struct PowerRange
+ {
+ double min;
+ double max;
+ };
+ PowerRange getPowers(float position) const;
+ PowerRange getPositionRange() const;
const std::vector<Choke>& getChokes();
@@ -98,12 +104,12 @@ private:
std::deque<InstrumentChannel> instrument_channels;
size_t lastpos;
- float mod;
Settings& settings;
Random& rand;
PowerList powerlist;
std::vector<Choke> chokes;
SampleSelection sample_selection;
+ PowerRange position_range{};
};
using Instruments = std::vector<std::unique_ptr<Instrument>>;
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/position_power.cc b/src/position_power.cc
new file mode 100644
index 0000000..0dc369b
--- /dev/null
+++ b/src/position_power.cc
@@ -0,0 +1,99 @@
+/* -*- Mode: c++ -*- */
+/***************************************************************************
+ * position_power.cc
+ *
+ * Wed Jul 24 15:05:27 CEST 2024
+ * Copyright 2024 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 "position_power.h"
+
+#include "sample.h"
+#include "instrument.h"
+
+#include <set>
+#include <algorithm>
+
+Instrument::PowerRange positionPower(const std::vector<Sample*>& samplelist, double position)
+{
+ if(samplelist.empty())
+ {
+ return {0.0, 1.0};
+ }
+
+ struct PosPower
+ {
+ double position;
+ double power;
+ Sample* sample;
+ };
+ auto dist_cmp =
+ [position](const PosPower& a, const PosPower& b)
+ {
+ auto position_delta =
+ std::abs(a.position - position) - std::abs(b.position - position);
+ if(position_delta != 0)
+ {
+ return position_delta < 0.0;
+ }
+ return a.sample < b.sample;
+ };
+ std::set<PosPower, decltype(dist_cmp)> sorted_samples(dist_cmp);
+
+ std::for_each(samplelist.begin(), samplelist.end(),
+ [&](Sample* s)
+ {
+ sorted_samples.insert({s->getPosition(), s->getPower(), s});
+ });
+
+ // Find the smallest, closest set in terms of delta-position against the note position
+ // and find the contained power range.
+ double power_min{std::numeric_limits<double>::max()};
+ double power_max{std::numeric_limits<double>::min()};
+ auto sample_iter = sorted_samples.begin();
+ auto final_position_boundary = sample_iter->position;
+ for(std::size_t i = 0; i < std::max(sorted_samples.size() / 4, std::size_t(1)); ++i)
+ {
+ auto power = sample_iter->power;
+ final_position_boundary = sample_iter->position;
+ power_min = std::min(power_min, power);
+ power_max = std::max(power_max, power);
+ ++sample_iter;
+ }
+
+ // Include upcoming samples from the list as long as their distances are contained in
+ // the final position range.
+ while(sample_iter != sorted_samples.end())
+ {
+ if(sample_iter->position != final_position_boundary)
+ {
+ // Position has left the range - and since the list is sorted; stop.
+ break;
+ }
+
+ auto power = sample_iter->power;
+ power_min = std::min(power_min, power);
+ power_max = std::max(power_max, power);
+ ++sample_iter;
+ }
+
+ return {power_min, power_max};
+}
diff --git a/src/position_power.h b/src/position_power.h
new file mode 100644
index 0000000..9b92a4f
--- /dev/null
+++ b/src/position_power.h
@@ -0,0 +1,87 @@
+/* -*- Mode: c++ -*- */
+/***************************************************************************
+ * position_power.h
+ *
+ * Wed Jul 24 15:05:26 CEST 2024
+ * Copyright 2024 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 "instrument.h"
+
+#include <vector>
+
+class Sample;
+
+//!
+//! Consider samples in the samplelist as a two dimensional "point cloud" - each
+//! also pointing to sample data (which is not used here):
+//!
+//! (vel)
+//! S_v
+//! max ^
+//! |x x
+//! | x x x
+//! | x x
+//! | x x
+//! | x x x
+//! min |________________> S_p (pos)
+//! center rim
+//!
+//! N: is the total number of samples
+//!
+//! S, is a specific sample
+//! S_v, is the sample's velocity
+//! S_p, is the sample's position
+//!
+//! I_v, is the input note velocity
+//! I_p, is the input note position
+//!
+//! -----
+//!
+//! Define the range R with width R_w around I_p, such that at least N/4 samples are
+//! included (note the count N/4 probably needs narrowing):
+//!
+//! (vel)
+//! S_v
+//! max ^
+//! |x x
+//! | x . +. x
+//! | . + . x
+//! | x. . x
+//! | x . +.x
+//! min |____._____._____> S_p (pos)
+//! center . ^ . rim
+//! . I_p .
+//! { R }
+//! x is a sample that is not included in the set, + is a sample that is.
+//!
+//! Now for the range R, find the R_max velocity and the R_min velocity.
+//! Use these as the boundaries for the velocity [0; 1] range.
+//!
+//! If no position information is available, the range will include all samples in
+//! the range, because all have the default value 0.
+//! This mimics perfectly the behaviour we have today.
+//!
+//! \param samplelist is the search space, \param position is the search origo (S_p)
+//! \returns a tuple {R_min, R_max}, which defaults to {0, 1} if the samplelist is empty
+Instrument::PowerRange positionPower(const std::vector<Sample*>& samplelist, double position);
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/sample_selection.cc b/src/sample_selection.cc
index eb13e55..5c19ae1 100644
--- a/src/sample_selection.cc
+++ b/src/sample_selection.cc
@@ -33,6 +33,7 @@
#include "settings.h"
#include <algorithm>
+#include <iostream>
namespace
{
@@ -45,7 +46,9 @@ float pow2(float f)
} // end anonymous namespace
SampleSelection::SampleSelection(Settings& settings, Random& rand, const PowerList& powerlist)
- : settings(settings), rand(rand), powerlist(powerlist)
+ : settings(settings)
+ , rand(rand)
+ , powerlist(powerlist)
{
}
@@ -56,7 +59,8 @@ void SampleSelection::finalise()
// FIXME: For the position, weird hacks via the powerlist are necessary. Refactor!
// FIXME: bad variable naming
-const Sample* SampleSelection::get(level_t level, float position, std::size_t pos)
+const Sample* SampleSelection::get(float power, float instrument_power_span,
+ float position, float instrument_positon_span, std::size_t pos)
{
const auto& samples = powerlist.getPowerListItems();
if(!samples.size())
@@ -73,34 +77,39 @@ const Sample* SampleSelection::get(level_t level, float position, std::size_t po
float closepos_opt = 0.;
float random_opt = 0.;
float diverse_opt = 0.;
-
+ std::cout << "Input position: " << position << " power: " << power << "\n";
// Note the magic values in front of the settings factors.
const float f_close = 4.*settings.sample_selection_f_close.load();
- const float f_position = 1000.*settings.sample_selection_f_position.load(); // FIXME: huge factor for now
+ const float f_position = 4.*settings.sample_selection_f_position.load();
const float f_diverse = (1./2.)*settings.sample_selection_f_diverse.load();
const float f_random = (1./3.)*settings.sample_selection_f_random.load();
- float power_range = powerlist.getMaxPower() - powerlist.getMinPower();
- // If all power values are the same then power_range is invalid but we want
+ // If all power values are the same then instrument_power_span is invalid but we want
// to avoid division by zero.
- if (power_range == 0.) { power_range = 1.0; }
+ if (instrument_power_span == 0.)
+ {
+ instrument_power_span = 1.0;
+ }
+#if 0
// start with most promising power value and then stop when reaching far values
// which cannot become opt anymore
- auto closest_it = std::lower_bound(samples.begin(), samples.end(), level);
+ auto closest_it = std::lower_bound(samples.begin(), samples.end(), power);
std::size_t up_index = std::distance(samples.begin(), closest_it);
std::size_t down_index = (up_index == 0 ? 0 : up_index - 1);
float up_value_lb;
- if (up_index < samples.size()) {
- auto const close_up = (samples[up_index].power-level)/power_range;
+ if (up_index < samples.size())
+ {
+ auto const close_up = (samples[up_index].power-power)/instrument_power_span;
up_value_lb = f_close*pow2(close_up);
}
- else {
+ else
+ {
--up_index;
up_value_lb = std::numeric_limits<float>::max();
}
- auto const close_down = (samples[down_index].power-level)/power_range;
+ auto const close_down = (samples[down_index].power-power)/instrument_power_span;
float down_value_lb = (up_index != 0 ? f_close*pow2(close_down) : std::numeric_limits<float>::max());
std::size_t count = 0;
@@ -117,7 +126,7 @@ const Sample* SampleSelection::get(level_t level, float position, std::size_t po
if (up_index != samples.size()-1)
{
++up_index;
- up_value_lb = f_close*pow2((samples[up_index].power-level)/power_range);
+ up_value_lb = f_close*pow2((samples[up_index].power-power)/instrument_power_span);
}
else
{
@@ -130,7 +139,7 @@ const Sample* SampleSelection::get(level_t level, float position, std::size_t po
if (down_index != 0)
{
--down_index;
- down_value_lb = f_close*pow2((samples[down_index].power-level)/power_range);
+ down_value_lb = f_close*pow2((samples[down_index].power-power)/instrument_power_span);
}
else
{
@@ -139,9 +148,9 @@ const Sample* SampleSelection::get(level_t level, float position, std::size_t po
}
auto random = rand.floatInRange(0.,1.);
- auto close = (samples[current_index].power - level)/power_range;
+ auto close = (samples[current_index].power - power)/instrument_power_span;
auto diverse = 1./(1. + (float)(pos - last[current_index])/settings.samplerate);
- auto closepos = samples[current_index].sample->getPosition() - position;
+ auto closepos = (samples[current_index].sample->getPosition() - position) / instrument_positon_span;
// note that the value below for close and closepos is actually the weighted squared l2 distance in 2d
auto value = f_close*pow2(close) + f_position*pow2(closepos) + f_diverse*diverse + f_random*random;
@@ -159,6 +168,30 @@ const Sample* SampleSelection::get(level_t level, float position, std::size_t po
++count;
}
while (up_value_lb <= value_opt || down_value_lb <= value_opt);
+#else
+ for(std::size_t current_index = 0; current_index < samples.size(); ++current_index)
+ {
+ auto random = rand.floatInRange(0.,1.);
+ auto close = (samples[current_index].power - power)/instrument_power_span;
+ auto diverse = 1./(1. + (float)(pos - last[current_index])/settings.samplerate);
+ auto closepos = (samples[current_index].sample->getPosition() - position) / instrument_positon_span;
+ // note that the value below for close and closepos is actually the weighted squared l2 distance in 2d
+ auto value = f_close*pow2(close) + f_position*pow2(closepos) + f_diverse*diverse + f_random*random;
+
+ if (value < value_opt)
+ {
+ index_opt = current_index;
+ power_opt = samples[current_index].power;
+ pos_opt = samples[current_index].sample->getPosition();
+ value_opt = value;
+ random_opt = random;
+ close_opt = close;
+ diverse_opt = diverse;
+ closepos_opt = closepos;
+ }
+ }
+ int count{}; // not used
+#endif
DEBUG(rand, "Chose sample with index: %d, value: %f, power: %f, position: %f, random: %f, close: %f, diverse: %f, closepos: %f, count: %d", (int)index_opt, value_opt, power_opt, pos_opt, random_opt, close_opt, diverse_opt, closepos_opt, (int)count);
diff --git a/src/sample_selection.h b/src/sample_selection.h
index 1f6b290..be93bd8 100644
--- a/src/sample_selection.h
+++ b/src/sample_selection.h
@@ -40,7 +40,8 @@ public:
SampleSelection(Settings& settings, Random& rand, const PowerList& powerlist);
void finalise();
- const Sample* get(level_t level, float position, std::size_t pos);
+ const Sample* get(float power, float instrument_power_span, float position,
+ float instrument_position_span, std::size_t pos);
private:
Settings& settings;
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/settings.h b/src/settings.h
index 5c2e4ee..074c7bc 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -76,9 +76,9 @@ struct Settings
static float constexpr velocity_modifier_falloff_default = 0.5f;
static float constexpr velocity_modifier_weight_default = 0.25f;
static float constexpr velocity_stddev_default = .45f;
- static float constexpr position_stddev_default = 0.f; // FIXME: set to something sensible
+ static float constexpr position_stddev_default = .45f;
static float constexpr sample_selection_f_close_default = .85f;
- static float constexpr sample_selection_f_position_default = 1.f;
+ static float constexpr sample_selection_f_position_default = .85f;
static float constexpr sample_selection_f_diverse_default = .16f;
static float constexpr sample_selection_f_random_default = .07f;
Atomic<float> velocity_modifier_falloff{velocity_modifier_falloff_default};
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>