diff options
| author | TheMarlboroMan <marlborometal@gmail.com> | 2020-01-27 18:37:01 +0100 | 
|---|---|---|
| committer | TheMarlboroMan <marlborometal@gmail.com> | 2020-01-27 18:37:01 +0100 | 
| commit | fde5c6661d296a79d6d6a8a1bcd888d2182deb8d (patch) | |
| tree | 48d9dc7dc143927c05a46f3edb7632745067cfe5 /src | |
| parent | c4e4a3f0faf756262e306984ddb56c262bfb087c (diff) | |
Small changes to source, added disposable logger, basic functionality, untestedthe-marlboro-man-experimental
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/drumgizmo.cc | 1 | ||||
| -rw-r--r-- | src/events.h | 9 | ||||
| -rw-r--r-- | src/inputprocessor.cc | 236 | ||||
| -rw-r--r-- | src/inputprocessor.h | 6 | ||||
| -rw-r--r-- | src/tracer.cc | 37 | ||||
| -rw-r--r-- | src/tracer.h | 84 | 
7 files changed, 305 insertions, 70 deletions
| diff --git a/src/Makefile.am b/src/Makefile.am index aad6cbf..44500e7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -63,6 +63,7 @@ libdg_la_SOURCES = \  	sem.cc \  	staminafilter.cc \  	thread.cc \ +	tracer.cc \  	velocityfilter.cc \  	versionstr.cc @@ -118,6 +119,7 @@ EXTRA_DIST = \  	staminafilter.h \  	syncedsettings.h \  	thread.h \ +	tracer.h \  	velocityfilter.h \  	versionstr.h \  	zrwrapper.h diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 65af878..591fcda 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -31,6 +31,7 @@  #include <cassert>  #include <cstring>  #include <mutex> +#include <fstream>  #include <event.h>  #include <audiotypes.h> diff --git a/src/events.h b/src/events.h index 18f9af3..f005566 100644 --- a/src/events.h +++ b/src/events.h @@ -65,7 +65,10 @@ class EventSample  {  public:  	EventSample(channel_t c, float g, AudioFile* af, -	            const std::string& grp, std::size_t instrument_id) +	            const std::string& grp,  +                std::size_t instrument_id, +                std::size_t insert_group_id +)  		: Event(c)  		, cache_id(CACHE_NOID)  		, gain(g) @@ -75,6 +78,7 @@ public:  		, rampdown_count(-1)  		, ramp_length(0)  		, instrument_id(instrument_id) +		, insert_group_id(insert_group_id)  	{  	} @@ -92,7 +96,7 @@ public:  	sample_t* buffer;  	std::size_t buffer_size;  	std::size_t buffer_ptr{0}; //< Internal pointer into the current buffer -	std::size_t sample_size{0}; //< Total number of audio samples in this sample. +	std::size_t sample_size{0}; //< Total number of audio samples in this sample.	  	float gain;  	unsigned int t; //< Internal sample position. @@ -103,6 +107,7 @@ public:  	std::size_t rampdown_offset{0};  	float scale{1.0f};  	std::size_t instrument_id; +	std::size_t insert_group_id; //< All EventSample instances created from the same event_t will share this value.  };  class EventQueue diff --git a/src/inputprocessor.cc b/src/inputprocessor.cc index 3530128..4514f38 100644 --- a/src/inputprocessor.cc +++ b/src/inputprocessor.cc @@ -3,7 +3,7 @@   *            inputprocessor.cc   *   *  Sat Apr 23 20:39:30 CEST 2016 - *  Copyright 2016 André Nusser + *  Copyright 2016 Andr� Nusser   *  andre.nusser@googlemail.com   ****************************************************************************/ @@ -29,6 +29,8 @@  #include <list>  #include <hugin.hpp> +#include <fstream> +#include <algorithm>  #include "instrument.h" @@ -38,63 +40,12 @@  #include "cpp11fix.h" -InputProcessor::InputProcessor(Settings& settings, -                               DrumKit& kit, -                               std::list<Event*>* activeevents, -                               Random& random) -	: kit(kit) -	, activeevents(activeevents) -	, is_stopping(false) -	, settings(settings) -{ -	// Build filter list -	filters.emplace_back(std::make_unique<StaminaFilter>(settings)); -	filters.emplace_back(std::make_unique<LatencyFilter>(settings, random)); -	filters.emplace_back(std::make_unique<VelocityFilter>(settings, random)); -} - -bool InputProcessor::process(std::vector<event_t>& events, -                             std::size_t pos, -                             double resample_ratio) -{ -	for(auto& event: events) -	{ -		if(event.type == EventType::OnSet) -		{ -			if(!processOnset(event, pos, resample_ratio)) -			{ -				continue; -			} -		} - -		if(event.type == EventType::Choke) -		{ -			if(!processChoke(event, pos, resample_ratio)) -			{ -				continue; -			} -		} - -		if(!processStop(event)) -		{ -			return false; -		} -	} - -	return true; -} +//TODO: This is just for development purposes. Remove when done. +#include "tracer.h" -std::size_t InputProcessor::getLatency() const +//Anonymous namespace for local functions. +namespace  { -	std::size_t latency = 0; - -	for(const auto& filter : filters) -	{ -		latency += filter->getLatency(); -	} - -	return latency; -}  //! Applies choke with rampdown time in ms to event starting at offset.  static void applyChoke(Settings& settings, EventSample& event, @@ -164,10 +115,74 @@ static void applyDirectedChoke(Settings& settings, DrumKit& kit,  	}  } +} //End of anonymous namespace. + +InputProcessor::InputProcessor(Settings& settings, +                               DrumKit& kit, +                               std::list<Event*>* activeevents, +                               Random& random) +	: kit(kit) +	, activeevents(activeevents) +	, is_stopping(false) +	, settings(settings) +	, insert_group_id(0) +{ +	tracer::trace("building InputProcessor", '\n'); + +	// Build filter list +	filters.emplace_back(std::make_unique<StaminaFilter>(settings)); +	filters.emplace_back(std::make_unique<LatencyFilter>(settings, random)); +	filters.emplace_back(std::make_unique<VelocityFilter>(settings, random)); +} + +bool InputProcessor::process(std::vector<event_t>& events, +                             std::size_t pos, +                             double resample_ratio) +{ +	for(auto& event: events) +	{ +		if(event.type == EventType::OnSet) +		{ +			if(!processOnset(event, pos, resample_ratio)) +			{ +				continue; +			} +		} + +		if(event.type == EventType::Choke) +		{ +			if(!processChoke(event, pos, resample_ratio)) +			{ +				continue; +			} +		} + +		if(!processStop(event)) +		{ +			return false; +		} +	} + +	return true; +} + +std::size_t InputProcessor::getLatency() const +{ +	std::size_t latency = 0; + +	for(const auto& filter : filters) +	{ +		latency += filter->getLatency(); +	} + +	return latency; +}  bool InputProcessor::processOnset(event_t& event, std::size_t pos,                                    double resample_ratio)  { +	tracer::trace("processOnset was called", '\n'); +  	if(!kit.isValid())  	{  		return false; @@ -198,6 +213,11 @@ bool InputProcessor::processOnset(event_t& event, std::size_t pos,  			return false; // Skip event completely  		}  	} +	 +	//TODO: A lookup map would be much better... +	const size_t max_voices=getMaxVoicesForInstrument(instrument_id); +	//TODO: Somehow this seems like a very specific case of a group. +	applyVoiceLimit(event, max_voices);  	// Mute other instruments in the same group  	applyChokeGroup(settings, kit, *instr, event, activeevents); @@ -220,26 +240,29 @@ bool InputProcessor::processOnset(event_t& event, std::size_t pos,  	auto const selected_level = (sample->getPower() - power_min)/power_span;  	settings.velocity_modifier_current.store(selected_level/original_level); +	++insert_group_id; //Insert group id 0 is not allowed.  	for(Channel& ch: kit.channels)  	{  		const auto af = sample->getAudioFile(ch);  		if(af == nullptr || !af->isValid())  		{  			//DEBUG(inputprocessor, "Missing AudioFile.\n"); +			continue;  		} -		else +		 +		//DEBUG(inputprocessor, "Adding event %d.\n", event.offset); +		auto evt = new EventSample(ch.num, 1.0, af, instr->getGroup(), +		                           instrument_id, +		                           insert_group_id); +		evt->offset = (event.offset + pos) * resample_ratio; +		if(settings.normalized_samples.load() && sample->getNormalized())  		{ -			//DEBUG(inputprocessor, "Adding event %d.\n", event.offset); -			auto evt = new EventSample(ch.num, 1.0, af, instr->getGroup(), -			                           instrument_id); -			evt->offset = (event.offset + pos) * resample_ratio; -			if(settings.normalized_samples.load() && sample->getNormalized()) -			{ -				evt->scale *= event.velocity; -			} - -			activeevents[ch.num].push_back(evt); +			evt->scale *= event.velocity;  		} + +		tracer::trace("event added to channel ", ch.num, " for instrument id ", instrument_id, '\n'); + +		activeevents[ch.num].push_back(evt);  	}  	return true; @@ -325,3 +348,82 @@ bool InputProcessor::processStop(event_t& event)  	return true;  } + +//TODO: Document. +void InputProcessor::applyVoiceLimit(const event_t& event, size_t max_voices) +{ +	//Find out how many voices for the instrument we are currently playing... +	const auto instrument_id = event.instrument; +	size_t current_count{0}; + +	tracer::trace("applyVoiceLimit will count for instrument id ", instrument_id, '\n'); + +	for(const auto& ch : kit.channels) +	{ +		current_count+=std::count_if(std::begin(activeevents[ch.num]), +		                             std::end(activeevents[ch.num]), +		                             [instrument_id](Event const * active_event) +									 { +										return active_event->getType() == Event::sample +											&& static_cast<EventSample const *>(active_event)->instrument_id == instrument_id; +									 }); +	} + +	//Early exit if the max number of voices has yet to be reached... +	tracer::trace("found ", current_count, " for instrument id ", instrument_id, '\n'); +	if(current_count <= max_voices)  +	{ +		return; +	} + +	//Locate the earliest sample group for this instrument that is not ramping. +	tracer::trace("locating earliest sample group\n"); +	std::size_t earliest_group{0}; + +	for(const auto& ch : kit.channels) +	{ +		for(const auto active_event : activeevents[ch.num]) +		{ +			if(active_event->getType() == Event::sample) +			{ +				auto& event_sample = *static_cast<EventSample*>(active_event); + +				//Same instrument, not ramping, with a lesser group. +				if(event_sample.instrument_id != instrument_id +				   && -1 == event_sample.rampdown_count +				   //TODO: Not proud of this, not proud of it at all. +				   && (event_sample.insert_group_id < earliest_group +				       || 0 == earliest_group)) +				{ +					earliest_group=event_sample.insert_group_id; +				} +			} +		} +	} + +	tracer::trace("earliest sample group was ", earliest_group, '\n'); + +	//Ramp down everyone belonging to that group... +	for(const auto& ch : kit.channels) +	{ +		for(auto active_event : activeevents[ch.num]) +		{ +			if(active_event->getType() == Event::sample) +			{ +				auto& event_sample = *static_cast<EventSample*>(active_event); +				if(event_sample.insert_group_id == earliest_group) +				{ +					tracer::trace("found and ramping in channel ", ch.num, '\n'); +					applyChoke(settings, event_sample, 68, event.offset); +				} +			} +		} +	} +} + +//TODO: Document. +size_t InputProcessor::getMaxVoicesForInstrument(size_t instrument_id) const  +{ +	//TODO: This would depend on the configuration set on the GUI. +	return 16; +}
\ No newline at end of file diff --git a/src/inputprocessor.h b/src/inputprocessor.h index 2101a25..5516146 100644 --- a/src/inputprocessor.h +++ b/src/inputprocessor.h @@ -3,7 +3,7 @@   *            inputprocessor.h   *   *  Sat Apr 23 20:39:30 CEST 2016 - *  Copyright 2016 André Nusser + *  Copyright 2016 Andr� Nusser   *  andre.nusser@googlemail.com   ****************************************************************************/ @@ -61,8 +61,12 @@ private:  	bool processOnset(event_t& event, std::size_t pos, double resample_ratio);  	bool processChoke(event_t& event, std::size_t pos, double resample_ratio);  	bool processStop(event_t& event); +	void applyVoiceLimit(const event_t& event, size_t max_voices); +	size_t getMaxVoicesForInstrument(size_t instrument_id) const;  	std::vector<std::unique_ptr<InputFilter>> filters;  	Settings& settings; + +	size_t insert_group_id; ///< Identifier for all Events added in all different channels from the same event_t.  }; diff --git a/src/tracer.cc b/src/tracer.cc new file mode 100644 index 0000000..adc621f --- /dev/null +++ b/src/tracer.cc @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            tracer.cc + * + *  Sun Dec 29 18:04:28 CET 2019 + *  Copyright 2019 Daniel Pastor + *  marlborometal@gmail.com + ****************************************************************************/ + +/* + *  This file is part of DrumGizmo. + * + *  DrumGizmo is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Lesser General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  DrumGizmo is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU Lesser General Public License for more details. + * + *  You should have received a copy of the GNU Lesser General Public License + *  along with DrumGizmo; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ + +#include "tracer.h" + +//Instantiation of the static file stream. +std::unique_ptr<std::ofstream> tracer::tracer_manager::outfile=nullptr; + +void tracer::trace() +{ +	std::flush(tracer_manager::get()); +	return; +}
\ No newline at end of file diff --git a/src/tracer.h b/src/tracer.h new file mode 100644 index 0000000..e42c29e --- /dev/null +++ b/src/tracer.h @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            tracer.h + * + *  Sun Dec 29 18:04:28 CET 2019 + *  Copyright 2019 Daniel Pastor + *  marlborometal@gmail.com + ****************************************************************************/ + +/* + *  This file is part of DrumGizmo. + * + *  DrumGizmo is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Lesser General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  DrumGizmo is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU Lesser General Public License for more details. + * + *  You should have received a copy of the GNU Lesser General Public License + *  along with DrumGizmo; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#pragma once + +#include <fstream> +#include <memory> +#include <stdexcept> + +//! This file contains the trace tool for developmnent purposes. The trace tool +//! just prints messages to a given file. +namespace tracer  +{ + +//! This class takes care of the output stream where trace messages will be +//! printed. Its methods are not supposed to be called by anyone else than the +//! "trace" functions. +class tracer_manager  +{ +	public: + +	//! Returns a reference to the file stream. +	static std::ofstream& get() +	{ +		if(nullptr==outfile.get())  +		{ +//TODO: This should not be fixed, but either depend on the OS or be able to +//specified somehow. +			outfile.reset(new std::ofstream("/tmp/drumgizmo.trace",  +								std::ios::app)); +		} + +		if(nullptr==outfile.get()) +		{ +			throw std::runtime_error("the tracer file could not be initialized"); +		} + +		return *(outfile.get()); +	} + +	private: + +	//! Single output file. Will be initialized to nullptr when the program +	//! starts and freed when the program ends. +	static std::unique_ptr<std::ofstream> outfile;	 +}; + +//! Trace function without parameters, used on the last call to the variadic +//! templace "trace". +void trace(); + +//! Variadic trace function. Obtains a reference to the file stream and prints +//! its arguments there. +template<typename T, typename... Args>  +void trace(T val, Args... args) +{ +	tracer_manager::get()<<val; +	trace(args...); +} + +}//End of tracer namespace.
\ No newline at end of file | 
