diff options
37 files changed, 563 insertions, 106 deletions
@@ -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 @@ -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..62b527e 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 @@ -139,6 +137,8 @@ static std::string arguments() "Sample selection parameters:\n" " close: The importance given to choosing a sample close to\n" " the actual velocity value (after humanization). [0,1]\n" + " position: The importance given to choosing a sample close to\n" + " the actual position value (after humanization). [0,1]\n" " diverse: The importance given to choosing samples\n" " which haven't been played recently. [0,1]\n" " random: The amount of randomness added. [0,1]\n" @@ -617,6 +617,16 @@ int main(int argc, char* argv[]) } settings.sample_selection_f_close.store(val); } + else if(token.key == "position") + { + auto val = atof_nol(token.value.data()); + if(val < 0 || val > 1) + { + std::cerr << "position range is [0, 1].\n"; + return 1; + } + settings.sample_selection_f_position.store(val); + } else if(token.key == "diverse") { auto val = atof_nol(token.value.data()); 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/drumgizmo/jackclient.cc b/drumgizmo/jackclient.cc index 8bf0939..0b05358 100644 --- a/drumgizmo/jackclient.cc +++ b/drumgizmo/jackclient.cc @@ -28,12 +28,6 @@ #include "jackclient.h" -JackProcess::~JackProcess() -{ -} - -// -------------------------------------------------------------------- - JackPort::JackPort(JackClient& client, const std::string& name, const char* type, JackPortFlags flags) : client{client.client} // register jack port for given client @@ -57,8 +51,7 @@ int JackClient::wrapJackProcess(jack_nframes_t nframes, void* arg) return static_cast<JackClient*>(arg)->process(nframes); } -void JackClient::latencyCallback(jack_latency_callback_mode_t mode, - void* arg) +void JackClient::latencyCallback(jack_latency_callback_mode_t mode, void* arg) { static_cast<JackClient*>(arg)->jackLatencyCallback(mode); } @@ -92,12 +85,23 @@ JackClient::~JackClient() void JackClient::add(JackProcess& process) { - processes.insert(&process); + JackProcessContainer c; + c.process = &process; + processes.push_back(std::move(c)); } void JackClient::remove(JackProcess& process) { - processes.erase(&process); + // Do not erase here. Instead mark as disabled - it will be erased at next + // JackClient::process call. + for(auto& ptr : processes) + { + if(ptr.process == &process) + { + ptr.active = false; + } + } + dirty = true; } void JackClient::activate() @@ -111,10 +115,30 @@ void JackClient::activate() int JackClient::process(jack_nframes_t num_frames) { + // Clear out any inactive processes before iterating + if(dirty) + { + auto it = processes.begin(); + while(it != processes.end()) + { + if(it->active == false) + { + it = processes.erase(it); + } + else + { + it++; + } + } + + dirty = false; + } + for(auto& ptr : processes) { - ptr->process(num_frames); + ptr.process->process(num_frames); } + return 0; } @@ -122,7 +146,7 @@ void JackClient::jackLatencyCallback(jack_latency_callback_mode_t mode) { for(auto& ptr : processes) { - ptr->jackLatencyCallback(mode); + ptr.process->jackLatencyCallback(mode); } } diff --git a/drumgizmo/jackclient.h b/drumgizmo/jackclient.h index f769ab4..04d6654 100644 --- a/drumgizmo/jackclient.h +++ b/drumgizmo/jackclient.h @@ -27,7 +27,7 @@ #pragma once #include <vector> #include <string> -#include <set> +#include <list> #include <jack/jack.h> @@ -38,7 +38,7 @@ class JackClient; class JackProcess { public: - virtual ~JackProcess(); + virtual ~JackProcess() = default; virtual void process(jack_nframes_t num_frames) = 0; virtual void jackLatencyCallback(jack_latency_callback_mode_t mode) {} }; @@ -76,7 +76,13 @@ public: private: jack_client_t* client; - std::set<JackProcess*> processes; + bool dirty{false}; + struct JackProcessContainer + { + JackProcess *process; + bool active{true}; + }; + std::list<JackProcessContainer> processes; bool is_active; bool is_freewheeling; diff --git a/man/drumgizmo.fr.1 b/man/drumgizmo.fr.1 index 1d7f891..794d762 100644 --- a/man/drumgizmo.fr.1 +++ b/man/drumgizmo.fr.1 @@ -155,21 +155,55 @@ Options du timing de l'humaniseur. \fBregain\fR=<val> (Contrôle la rapidité avec laquelle le batteur se rattrape au tempo. [0; 1]) .RE +\fB-t, --velocity-humanizer\fR +.RS 7 +Permet d'adapter les vitesses d'entrée pour obtenir un son plus réaliste. + +.RE +\fB-T, --velocity-humanizerparms parmlist\fR +.RS 7 +Options de l'humaniseur de vélocité. + +.P +\fBattack\fR=<val> (La vitesse à laquelle la vélocité est réduite lorsque vous jouez des notes rapides. +Des valeurs plus faibles entraînent une réduction plus rapide de la vitesse. [0,1]) +.P +\fBrelease\fR=<val> (La vitesse à laquelle le batteur retrouve la vélocité +lorsqu'il y a des espaces entre les notes. Des valeurs plus faibles entraînent une reprise plus rapide. [0,1]) +.P +\fBstddev\fR=<val> (L'écart-type pour l'humaniseur de vitesse. +Une valeur plus élevée rend plus probable qu'un échantillon +plus éloigné de la vélocité d'entrée soit joué. [0,4.5]) + +.RE +\fB-l, --voice-limit\fR +.RS 7 +Activer la limite vocale. + +.RE +\fB-L, --voice-limitparms parmlist\fR +.RS 7 +Options de limite de voix. + +.P +\fBmax\fR=<val> (Nombre maximum de voix pour chaque instrument avant +que les anciens échantillons ne soient réduits. [1,30]) +.P +\fBrampdown\fR=<val> (Temps qu'il faut à un ancien échantillon pour +devenir complètement silencieux. [0.01,2.0]) + +.RE \fB-p, --parameters parmlist\fR .RS 7 Paramètres de l'algorithme de sélection des échantillons. .P \fBclose\fR=<val> (L'importance accordée au choix d'un échantillon proche de -la valeur réelle de la vitesse (après humanisation) [0; 16]) +la valeur réelle de la vitesse (après humanisation) [0,1]) .P \fBdiverse\fR=<val> (L'importance accordée au choix d'échantillons qui -n'ont pas été joués récemment [0; 0.5]) -.P -\fBrandom\fR=<val> (La quantité d'aléatoire ajoutée [0; 0.5]) +n'ont pas été joués récemment [0,1]) .P -\fBstddev\fR=<val> (L'écart type pour la sélection de l'échantillon. -Plus la valeur est élevée, plus il est probable qu'un échantillon -plus éloigné de la vitesse d'entrée sera joué [0; 4.5]) +\fBrandom\fR=<val> (La quantité d'aléatoire ajoutée [0,1]) .RE \fB-v, --version\fR 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/maintab.cc b/plugingui/maintab.cc index 5c5fd02..d95885e 100644 --- a/plugingui/maintab.cc +++ b/plugingui/maintab.cc @@ -131,7 +131,7 @@ MainTab::MainTab(dggui::Widget* parent, layout.setResizeChildren(true); //Left column... - add(_("Drumkit"), drumkit_frame, drumkitframe_content, 14, 0); + add(_("Drumkit"), drumkit_frame, drumkitframe_content, 15, 0); add(_("Status"), status_frame, statusframe_content, 12, 0); add(_("Resampling"), resampling_frame, resamplingframe_content, 10, 0); add(_("Voice Limit"), voicelimit_frame, voicelimit_content, 10, 0); @@ -153,7 +153,7 @@ MainTab::MainTab(dggui::Widget* parent, add(_("Visualizer"), visualizer_frame, visualizerframe_content, 14, 1); visualizer_frame.setHelpText(visualizer_tip); - add(_("Velocity Curve"), power_frame, powerframe_content, 20, 1); + add(_("Velocity Curve"), power_frame, powerframe_content, 21, 1); power_frame.setHelpText(power_tip); humanizer_frame.setOnSwitch(settings.enable_velocity_modifier); diff --git a/plugingui/mainwindow.h b/plugingui/mainwindow.h index ae0da8b..e517a0d 100644 --- a/plugingui/mainwindow.h +++ b/plugingui/mainwindow.h @@ -47,7 +47,7 @@ class MainWindow public: static constexpr std::size_t main_width{750}; - static constexpr std::size_t main_height{800}; + static constexpr std::size_t main_height{740}; MainWindow(Settings& settings, void* native_window); ~MainWindow(); diff --git a/src/Makefile.am b/src/Makefile.am index 3e691b1..770c436 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -32,8 +32,9 @@ libpugi_la_SOURCES = \ 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) + $(SSEFLAGS) -I$(top_srcdir)/zita-resampler/libs \ + $(SNDFILE_CFLAGS) $(PTHREAD_CFLAGS) \ + -Wno-deprecated-declarations libdg_la_LIBADD = \ $(SNDFILE_LIBS) $(PTHREAD_LIBS) libzr.la libpugi.la @@ -107,7 +108,7 @@ EXTRA_DIST = \ drumgizmoconf.h \ drumkit.h \ drumkitloader.h \ - event.h \ + engineevent.h \ events.h \ events_ds.h \ grid.h \ diff --git a/src/audiofile.h b/src/audiofile.h index e20d91f..504d0ae 100644 --- a/src/audiofile.h +++ b/src/audiofile.h @@ -32,8 +32,6 @@ #include <limits> #include <mutex> -#include <sndfile.h> - #include "audio.h" #include "channel.h" #include "logger.h" 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/drumgizmo.cc b/src/drumgizmo.cc index abe57be..b67e91a 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -32,7 +32,6 @@ #include <cstring> #include <mutex> -#include <event.h> #include <audiotypes.h> #include <config.h> @@ -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) 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..7679e82 100644 --- a/src/inputprocessor.cc +++ b/src/inputprocessor.cc @@ -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,15 +244,14 @@ 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(); - float const power_span = power_max - power_min; - float const instrument_level = power_min + event.velocity*power_span; + auto power = instr->getPowers(event.position); + const float power_span = power.max - power.min; + const float 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); @@ -269,7 +265,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 +355,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 +396,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 +417,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 +431,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 +454,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..30f3423 100644 --- a/src/instrument.cc +++ b/src/instrument.cc @@ -130,27 +130,15 @@ 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 { powerlist.getMaxPower(), powerlist.getMaxPower() }; } else { - return 1.0f; - } -} - -float Instrument::getMinPower() const -{ - if(version >= VersionStr("2.0")) - { - return powerlist.getMinPower(); - } - else - { - return 0.0f; + return { 0.0f, 1.0f }; } } diff --git a/src/instrument.h b/src/instrument.h index 89918de..49a9a74 100644 --- a/src/instrument.h +++ b/src/instrument.h @@ -68,8 +68,15 @@ 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 + { + float min; + float max; + }; + PowerRange getPowers(float position) const; + + //float getMaxPower() const; + //float getMinPower() const; const std::vector<Choke>& getChokes(); diff --git a/src/powerlist.cc b/src/powerlist.cc index 23d9795..8dd0b24 100644 --- a/src/powerlist.cc +++ b/src/powerlist.cc @@ -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/powerlist.h b/src/powerlist.h index ffbd6ba..b1fd1fd 100644 --- a/src/powerlist.h +++ b/src/powerlist.h @@ -44,7 +44,13 @@ struct PowerListItem return this->power < power; } }; -using PowerListItems = std::vector<PowerListItem>; +class PowerListItems + : public std::vector<PowerListItem> +{ +public: + float getMaxPower() const; + float getMinPower() const; +}; class PowerList { @@ -54,7 +60,7 @@ public: void add(Sample* s); void finalise(); ///< Call this when no more samples will be added. - const PowerListItems& getPowerListItems() const; + const PowerListItems& getPowerListItems(float position) const; float getMaxPower() const; float getMinPower() const; diff --git a/src/sample_selection.cc b/src/sample_selection.cc index eb13e55..c6d8eea 100644 --- a/src/sample_selection.cc +++ b/src/sample_selection.cc @@ -58,7 +58,7 @@ void SampleSelection::finalise() // FIXME: bad variable naming const Sample* SampleSelection::get(level_t level, float position, std::size_t pos) { - const auto& samples = powerlist.getPowerListItems(); + const auto& samples = powerlist.getPowerListItems(position); if(!samples.size()) { return nullptr; // No samples to choose from. @@ -80,7 +80,7 @@ const Sample* SampleSelection::get(level_t level, float position, std::size_t po 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(); + float power_range = samples.getMaxPower() - samples.getMinPower(); // If all power values are the same then power_range is invalid but we want // to avoid division by zero. if (power_range == 0.) { power_range = 1.0; } diff --git a/test/Makefile.am b/test/Makefile.am index 6441fd3..15ceb7d 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -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 \ 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/tools/macos/build-dg.sh b/tools/macos/build-dg.sh new file mode 100755 index 0000000..84585d4 --- /dev/null +++ b/tools/macos/build-dg.sh @@ -0,0 +1,264 @@ +#!/bin/bash + +# --------------------------------------------------------------------------------------------------------------------- +# stop on error + +set -e + +# --------------------------------------------------------------------------------------------------------------------- +# stop on error + +TARGETDIR=$PWD/builds/drumgizmo + +DOWNLOADS=$PWD/downloads + +PKG_CONFIG_VERSION=0.28 +LIBOGG_VERSION=1.3.3 +LIBVORBIS_VERSION=1.3.6 +FLAC_VERSION=1.3.2 +LIBSNDFILE_VERSION=1.0.28 +ZITA_RESAMPLER_VERSION=1.6.2 + +DRUMGIZMO_VERSION=0.9.20 + +# --------------------------------------------------------------------------------------------------------------------- +# function to remove old stuff + +cleanup() +{ + +rm -rf $TARGETDIR +rm -rf flac-* +rm -rf libogg-* +rm -rf libsndfile-* +rm -rf libvorbis-* +rm -rf pkg-config-* +exit 0 + +} + +# --------------------------------------------------------------------------------------------------------------------- +# setup build vars + +export CC=clang +export CXX=clang++ + +export PREFIX=${TARGETDIR} +export PATH=${PREFIX}/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin +export PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig + +export CFLAGS="-O3 -mtune=generic -msse -msse2 -fvisibility=hidden" +export CFLAGS="${CFLAGS} -fPIC -DPIC -DNDEBUG -I${PREFIX}/include" +export CXXFLAGS="${CFLAGS} -fvisibility-inlines-hidden -stdlib=libc++" + +export LDFLAGS="-Wl,-dead_strip -Wl,-dead_strip_dylibs" +export LDFLAGS="${LDFLAGS} -L${PREFIX}/lib" + +# --------------------------------------------------------------------------------------------------------------------- +echo ==== Package pkgconfig ==== + +if [ ! -f ${DOWNLOADS}/pkg-config-${PKG_CONFIG_VERSION}.tar.gz ]; then + pushd ${DOWNLOADS} + curl -O https://pkg-config.freedesktop.org/releases/pkg-config-${PKG_CONFIG_VERSION}.tar.gz || \ + curl -k -O https://drumgizmo.org/mirror/pkg-config-${PKG_CONFIG_VERSION}.tar.gz + popd +fi + +if [ ! -d pkg-config-${PKG_CONFIG_VERSION} ]; then + tar -xf ${DOWNLOADS}/pkg-config-${PKG_CONFIG_VERSION}.tar.gz +fi + +if [ ! -f pkg-config-${PKG_CONFIG_VERSION}/build-done ]; then + cd pkg-config-${PKG_CONFIG_VERSION} + ./configure --enable-indirect-deps --with-internal-glib --with-pc-path=$PKG_CONFIG_PATH --prefix=${PREFIX} + make ${MAKE_ARGS} + make install + touch build-done + cd .. +fi + +# --------------------------------------------------------------------------------------------------------------------- +echo ==== Package libogg ==== + +if [ ! -f ${DOWNLOADS}/libogg-${LIBOGG_VERSION}.tar.gz ]; then + pushd ${DOWNLOADS} + curl -O http://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-${LIBOGG_VERSION}.tar.gz || \ + curl -k -O https://drumgizmo.org/mirror/libogg-${LIBOGG_VERSION}.tar.gz + popd +fi + +if [ ! -d libogg-${LIBOGG_VERSION} ]; then + tar -xf ${DOWNLOADS}/libogg-${LIBOGG_VERSION}.tar.gz +fi + +if [ ! -f libogg-${LIBOGG_VERSION}/build-done ]; then + cd libogg-${LIBOGG_VERSION} + ./configure --enable-static --disable-shared --prefix=${PREFIX} + make ${MAKE_ARGS} + make install + touch build-done + cd .. +fi + +# --------------------------------------------------------------------------------------------------------------------- +echo ==== Package libvorbis ==== + +if [ ! -f ${DOWNLOADS}/libvorbis-${LIBVORBIS_VERSION}.tar.gz ]; then + pushd ${DOWNLOADS} + curl -O http://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-${LIBVORBIS_VERSION}.tar.gz || \ + curl -k -O https://drumgizmo.org/mirror/libvorbis-${LIBVORBIS_VERSION}.tar.gz + popd +fi + +if [ ! -d libvorbis-${LIBVORBIS_VERSION} ]; then + tar -xf ${DOWNLOADS}/libvorbis-${LIBVORBIS_VERSION}.tar.gz +fi + +if [ ! -f libvorbis-${LIBVORBIS_VERSION}/build-done ]; then + cd libvorbis-${LIBVORBIS_VERSION} + ./configure --enable-static --disable-shared --prefix=${PREFIX} + make ${MAKE_ARGS} + make install + touch build-done + cd .. +fi + +# --------------------------------------------------------------------------------------------------------------------- +echo ==== Package flac ==== + +if [ ! -f ${DOWNLOADS}/flac-${FLAC_VERSION}.tar.xz ]; then + pushd ${DOWNLOADS} + curl -O http://ftp.osuosl.org/pub/xiph/releases/flac/flac-${FLAC_VERSION}.tar.xz || \ + curl -k -O https://drumgizmo.org/mirror/flac-${FLAC_VERSION}.tar.xz + popd +fi +if [ ! -d flac-${FLAC_VERSION} ]; then + tar -xf ${DOWNLOADS}/flac-${FLAC_VERSION}.tar.xz +fi + +if [ ! -f flac-${FLAC_VERSION}/build-done ]; then + cd flac-${FLAC_VERSION} + sed -i -e "s/HAVE_CPUID_H/HAVE_CPUID_H_NOT/" src/libFLAC/cpu.c + chmod +x configure install-sh + ./configure --enable-static --disable-shared --prefix=${PREFIX} \ + --disable-cpplibs + echo "exit 0" > missing + make ${MAKE_ARGS} + make install + touch build-done + cd .. +fi + +# --------------------------------------------------------------------------------------------------------------------- +echo ==== Package libsndfile ==== + +if [ ! -f ${DOWNLOADS}/libsndfile-${LIBSNDFILE_VERSION}.tar.gz ]; then + pushd ${DOWNLOADS} + curl -O http://www.mega-nerd.com/libsndfile/files/libsndfile-${LIBSNDFILE_VERSION}.tar.gz || \ + curl -k -O https://drumgizmo.org/mirror/libsndfile-${LIBSNDFILE_VERSION}.tar.gz + popd +fi + +if [ ! -d libsndfile-${LIBSNDFILE_VERSION} ]; then + tar -xf ${DOWNLOADS}/libsndfile-${LIBSNDFILE_VERSION}.tar.gz +fi + +if [ ! -f libsndfile-${LIBSNDFILE_VERSION}/build-done ]; then + cd libsndfile-${LIBSNDFILE_VERSION} + ./configure --enable-static --disable-shared --prefix=${PREFIX} \ + --disable-full-suite --disable-sqlite + make ${MAKE_ARGS} + make install + sed -i -e "s|-lsndfile|-lsndfile -lFLAC -lvorbisenc -lvorbis -logg -lm|" ${PREFIX}/lib/pkgconfig/sndfile.pc + touch build-done + cd .. +fi + +# --------------------------------------------------------------------------------------------------------------------- +echo ==== Package zita-resampler ==== + +if [ ! -f ${DOWNLOADS}/zita-resampler-${ZITA_RESAMPLER_VERSION}.tar.bz2 ]; then + pushd ${DOWNLOADS} + curl -O http://kokkinizita.linuxaudio.org/linuxaudio/downloads/zita-resampler-${ZITA_RESAMPLER_VERSION}.tar.bz2 || \ + curl -k -O https://drumgizmo.org/mirror/zita-resampler-${ZITA_RESAMPLER_VERSION}.tar.bz2 + popd +fi + +if [ ! -d zita-resampler-${ZITA_RESAMPLER_VERSION} ]; then + tar -xf ${DOWNLOADS}/zita-resampler-${ZITA_RESAMPLER_VERSION}.tar.bz2 +fi + +if [ ! -f zita-resampler-${ZITA_RESAMPLER_VERSION}/build-done ]; then + cd zita-resampler-${ZITA_RESAMPLER_VERSION} + if [ ! -f patched ]; then + patch -p1 -i ../zita-resampler-static-build.patch + touch patched + fi + make ${MAKE_ARGS} -C source + mkdir ${PREFIX}/include/zita-resampler + cp source/*.a ${PREFIX}/lib/ + cp source/zita-resampler/*.h ${PREFIX}/include/zita-resampler/ + touch build-done + cd .. +fi + +# --------------------------------------------------------------------------------------------------------------------- +echo ==== Package drumgizmo ==== + +if [ ! -f ${DOWNLOADS}/drumgizmo-${DRUMGIZMO_VERSION}.tar.gz ]; then + pushd ${DOWNLOADS} + curl -O https://www.drumgizmo.org/releases/drumgizmo-${DRUMGIZMO_VERSION}/drumgizmo-${DRUMGIZMO_VERSION}.tar.gz + popd +fi + +if [ ! -d drumgizmo-${DRUMGIZMO_VERSION} ]; then + tar -xf ${DOWNLOADS}/drumgizmo-${DRUMGIZMO_VERSION}.tar.gz +fi + +if [ ! -f drumgizmo-${DRUMGIZMO_VERSION}/build-done ]; then + PATH=/usr/local/opt/gettext/bin:$PATH + cd drumgizmo-${DRUMGIZMO_VERSION} + ./configure --prefix=${PREFIX} \ + --disable-input-midifile \ + --disable-input-jackmidi \ + --disable-output-jackaudio \ + --disable-input-alsamidi \ + --disable-output-alsa \ + --enable-cli \ + --without-debug \ + --with-test \ + --disable-lv2 \ + --enable-vst \ + --with-vst-sources=$HOME/VST3_SDK + make ${MAKE_ARGS} + make install + touch build-done + cd .. +fi + +# --------------------------------------------------------------------------------------------------------------------- + +echo Make macOS package: + +otool -L ${PREFIX}/lib/vst/drumgizmo_vst.so + +if [ ! -f drumgizmo.vst.tar.gz ]; then + exit "Missing VST package template: drumgizmo.vst.tar.gz " +fi + +if [ ! -d ${DRUMGIZMO_VERSION}/drumgizmo.vst ]; then + mkdir -p ${DRUMGIZMO_VERSION} + pushd ${DRUMGIZMO_VERSION} + tar -xvzf ../drumgizmo.vst.tar.gz + popd +fi + +cp -a ${PREFIX}/lib/vst/drumgizmo_vst.so ${DRUMGIZMO_VERSION}/drumgizmo.vst/Contents/MacOS/drumgizmo +sed -e "s/@VERSION@/${DRUMGIZMO_VERSION}/g" -i .bak ${DRUMGIZMO_VERSION}/drumgizmo.vst/Contents/Info.plist +rm -f ${DRUMGIZMO_VERSION}/drumgizmo.vst/Contents/Info.plist.bak + +pushd ${DRUMGIZMO_VERSION} +tar cvzf ../drumgizmo_vst-osx-${DRUMGIZMO_VERSION}.tar.gz drumgizmo.vst/ +popd + +echo Package is now ready in drumgizmo_vst-osx-${DRUMGIZMO_VERSION}.tar.gz diff --git a/tools/macos/drumgizmo.vst.tar.gz b/tools/macos/drumgizmo.vst.tar.gz Binary files differnew file mode 100644 index 0000000..0db45db --- /dev/null +++ b/tools/macos/drumgizmo.vst.tar.gz diff --git a/tools/macos/zita-resampler-static-build.patch b/tools/macos/zita-resampler-static-build.patch new file mode 100644 index 0000000..5b894e1 --- /dev/null +++ b/tools/macos/zita-resampler-static-build.patch @@ -0,0 +1,28 @@ +--- zita-resampler-static-1.6.2.orig/source/Makefile ++++ zita-resampler-static-1.6.2/source/Makefile +@@ -32,12 +32,12 @@ DISTDIR = zita-resampler-$(VERSION) + + + CPPFLAGS += -I. -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS +-CXXFLAGS += -Wall -fPIC -O2 -ffast-math +-CXXFLAGS += -march=native ++CXXFLAGS += -Wall -fPIC -O3 -ffast-math + LDFLAGS += + LDLIBS += + + ++ZITA-RESAMPLER_A = libzita-resampler.a + ZITA-RESAMPLER_SO = libzita-resampler.so + ZITA-RESAMPLER_MAJ = $(ZITA-RESAMPLER_SO).$(MAJVERS) + ZITA-RESAMPLER_MIN = $(ZITA-RESAMPLER_MAJ).$(MINVERS) +@@ -47,6 +47,10 @@ ZITA-RESAMPLER_H = zita-resampler/resamp + zita-resampler/vresampler.h zita-resampler/cresampler.h + + ++$(ZITA-RESAMPLER_A): $(ZITA-RESAMPLER_O) ++ rm -f $@ ++ ar cr $@ $^ ++ + $(ZITA-RESAMPLER_MIN): $(ZITA-RESAMPLER_O) + $(CXX) -shared $(LDFLAGS) -Wl,-soname,$(ZITA-RESAMPLER_MAJ) -o $(ZITA-RESAMPLER_MIN) $(ZITA-RESAMPLER_O) $(ZITA-RESAMPLER_DEP) + @@ -1 +1 @@ -#define VERSION "0.9.19" +#define VERSION "0.9.20" |