diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/DGDOM.h | 1 | ||||
| -rw-r--r-- | src/audioinputenginemidi.cc | 40 | ||||
| -rw-r--r-- | src/audioinputenginemidi.h | 1 | ||||
| -rw-r--r-- | src/dgxmlparser.cc | 2 | ||||
| -rw-r--r-- | src/domloader.cc | 1 | ||||
| -rw-r--r-- | src/drumkit.cc | 5 | ||||
| -rw-r--r-- | src/drumkit.h | 2 | ||||
| -rw-r--r-- | src/drumkitloader.cc | 2 | ||||
| -rw-r--r-- | src/inputprocessor.cc | 34 | ||||
| -rw-r--r-- | src/midimapparser.cc | 6 | ||||
| -rw-r--r-- | src/midimapparser.h | 1 | ||||
| -rw-r--r-- | src/midimapper.cc | 42 | ||||
| -rw-r--r-- | src/midimapper.h | 15 | ||||
| -rw-r--r-- | src/settings.h | 3 | 
14 files changed, 115 insertions, 40 deletions
diff --git a/src/DGDOM.h b/src/DGDOM.h index a03f0ef..e39f445 100644 --- a/src/DGDOM.h +++ b/src/DGDOM.h @@ -139,6 +139,7 @@ struct DrumkitDOM  {  	std::string version;  	double samplerate; +	bool islogpower;  	MetadataDOM metadata; diff --git a/src/audioinputenginemidi.cc b/src/audioinputenginemidi.cc index 503a5c3..564a5d6 100644 --- a/src/audioinputenginemidi.cc +++ b/src/audioinputenginemidi.cc @@ -78,7 +78,7 @@ bool AudioInputEngineMidi::loadMidiMap(const std::string& file,  		instrmap[instruments[i]->getName()] = i;  	} -	mmap.swap(instrmap, midimap_parser.midimap); +	mmap.swap(instrmap, midimap_parser.midimap, midimap_parser.controlthreshmap);  	midimap = file;  	is_valid = true; @@ -108,11 +108,6 @@ static const std::uint8_t TypeMask = 0xF0;  // See:  // https://www.midi.org/specifications-old/item/table-1-summary-of-midi-message - -// TODO better implementation: use member variable for controller value, set MIDI key on command line -int hihat_controller = 0; // open hi-hat -int hihat_midi_key   = 26; -  void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer,                                         std::size_t midi_buffer_length,                                         std::size_t offset, @@ -133,7 +128,7 @@ void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer,  		{  			auto key = midi_buffer[1];  			auto velocity = midi_buffer[2]; -			auto instrument_idx = mmap.lookup(key); +			auto instrument_idx = mmap.lookup(key, controller4_value);  			if(velocity != 0 && instrument_idx != -1)  			{  				// maps velocities to [.5/127, 126.5/127] @@ -141,16 +136,21 @@ void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer,  				events.push_back({ EventType::OnSet, (std::size_t)instrument_idx,  				                   offset, centered_velocity, positional_information }); + +/* +// TODO better implementation: use member variable for controller value, set MIDI key on command line +int hihat_midi_key = 26;  // quick hack, add 1000000 to offset to transport hi-hat controller value  auto instrument_idx1 = mmap.lookup(hihat_midi_key);  if(instrument_idx == instrument_idx1)  { -  if(hihat_controller < 100) // quick hack: hard-coded value +  if(controller4_value < 100) // quick hack: hard-coded value    {      events.push_back({ EventType::Choke, (std::size_t)instrument_idx, -                       1000000 + hihat_controller, .0f, .0f }); +                       1000000 + controller4_value, .0f, .0f });    }  } +*/  			}  		} @@ -182,18 +182,20 @@ if(instrument_idx == instrument_idx1)  				return;  			} -			if(controller_number == 4) // hi-hat pedal +			if(controller_number == 4) // usually, controller 4 is the hi-hat controller  			{ +				// in case the hi-hat was just closed, choke current hi-hat samples +				if(controller4_value < mmap.getMaxControlthresh() && value >= mmap.getMaxControlthresh()) +				{ +					for(auto instrument_idx : mmap.getInstWithControlthresh()) +					{ +						events.push_back({ EventType::Choke, (std::size_t)instrument_idx, +								               offset, .0f, .0f }); +					} +				} -// quick hack: if hi-hat control pedal is down, choke hi-hat instrument -auto instrument_idx = mmap.lookup(hihat_midi_key); -hihat_controller = value; -if(value > 100 && instrument_idx != -1) // quick hack: hard-coded value -{ -  events.push_back({ EventType::Choke, (std::size_t)instrument_idx, -                     offset, .0f, .0f }); -} - +				// Store value for use in next NoteOn event. +				controller4_value = value;  			}  		}  		break; diff --git a/src/audioinputenginemidi.h b/src/audioinputenginemidi.h index 12efd66..7656f8d 100644 --- a/src/audioinputenginemidi.h +++ b/src/audioinputenginemidi.h @@ -72,4 +72,5 @@ private:  	ConfigFile refs;  	float positional_information{0.0f}; +	int controller4_value{0};  }; diff --git a/src/dgxmlparser.cc b/src/dgxmlparser.cc index bd9af66..b3aba75 100644 --- a/src/dgxmlparser.cc +++ b/src/dgxmlparser.cc @@ -209,6 +209,8 @@ bool parseDrumkitFile(const std::string& filename, DrumkitDOM& dom, LogFunction  	res &= attrcpy(dom.version, drumkit, "version", logger, filename, true);  	dom.samplerate = 44100.0;  	res &= attrcpy(dom.samplerate, drumkit, "samplerate", logger, filename, true); +	dom.islogpower = false; +	res &= attrcpy(dom.islogpower, drumkit, "islogpower", logger, filename, true);  	// Use the old name and description attributes on the drumkit node as fallback  	res &= attrcpy(dom.metadata.title, drumkit, "name", logger, filename, true); diff --git a/src/domloader.cc b/src/domloader.cc index 5d411bd..d422c9a 100644 --- a/src/domloader.cc +++ b/src/domloader.cc @@ -60,6 +60,7 @@ bool DOMLoader::loadDom(const std::string& basepath,  	drumkit.metadata._version = dom.version;  	drumkit.metadata._description = dom.metadata.description;  	drumkit.metadata._samplerate = dom.samplerate; +	drumkit.metadata._islogpower = dom.islogpower;  	for(const auto& channel: dom.channels)  	{ diff --git a/src/drumkit.cc b/src/drumkit.cc index 9df9a33..2fc16db 100644 --- a/src/drumkit.cc +++ b/src/drumkit.cc @@ -55,6 +55,11 @@ bool DrumKit::isValid() const  	return this == magic;  } +bool DrumKit::isLogPower() const +{ +  return metadata._islogpower; +} +  std::string DrumKit::getFile() const  {  	return _file; diff --git a/src/drumkit.h b/src/drumkit.h index aee5d19..3f2677f 100644 --- a/src/drumkit.h +++ b/src/drumkit.h @@ -51,6 +51,7 @@ public:  	void clear();  	bool isValid() const; +	bool isLogPower() const;  	float getSamplerate() const; @@ -74,5 +75,6 @@ private:  		std::string _description;  		float _samplerate{44100.0f};  		VersionStr _version; +		bool _islogpower{false};  	} metadata;  }; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index 9167201..91a235f 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -136,6 +136,7 @@ bool DrumKitLoader::loadkit(const std::string& file)  	settings.drumkit_description.store("");  	settings.drumkit_version.store("");  	settings.drumkit_samplerate.store(44100); +	settings.drumkit_is_log_power.store(false);  	settings.load_status_text.store("");  	settings.drumkit_load_status.store(LoadStatus::Parsing); @@ -219,6 +220,7 @@ bool DrumKitLoader::loadkit(const std::string& file)  	settings.drumkit_description = kit.getDescription();  	settings.drumkit_version = kit.getVersion();  	settings.drumkit_samplerate = kit.getSamplerate(); +	settings.drumkit_is_log_power = kit.isLogPower();  	// only load the default midi map if there is one and no midimap is selected yet  	if (drumkitdom.metadata.default_midimap_file != "" && settings.midimap_file == "")  	{ diff --git a/src/inputprocessor.cc b/src/inputprocessor.cc index a16115c..6d50c68 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   ****************************************************************************/ @@ -210,6 +210,16 @@ bool InputProcessor::processOnset(event_t& event, std::size_t pos,  		return false;  	} +	// In case log-power and dynamic expander is used, apply a special velocity curve +	if(settings.drumkit_is_log_power) +	{ +		auto a = 0.981; // compatible to Roland sound modules +		event.velocity = (126.0f / (pow(a, 126.0f) - 1.0f) * (pow(a, event.velocity * 127.0f - 1.0f) - 1.0f) + 1.0f) / 127.0f; +	} + +// TODO velocity 1 does not select thehighest amplitude samples... -> maybe bug in sample selection +//event.velocity=1.0; +  	std::size_t instrument_id = event.instrument;  	Instrument* instr = nullptr; @@ -291,20 +301,12 @@ bool InputProcessor::processOnset(event_t& event, std::size_t pos,  				event_sample.scale *= event.velocity;  			} -// TEST dynamic expander -//printf("event_sample.scale: %f, event.velocity: %f, sample->getPower(): %f, instr->getMinPower(): %f, instr->getMaxPower(): %f\n", event_sample.scale, event.velocity, sample->getPower(), instr->getMinPower(), instr->getMaxPower()); - -auto target_max_power_db = 10 * log10(instr->getMaxPower()); -auto target_min_power_db = 10 * log10(instr->getMinPower()); -auto sel_power_db        = 10 * log10(sample->getPower()); -auto target_dynamic_db   = 35.0; // dB - -auto target_power_db = sqrt(event.velocity) * target_dynamic_db + target_max_power_db - target_dynamic_db; -auto diff_power_db   = target_power_db - sel_power_db; -event_sample.scale   = pow(10.0, diff_power_db / 20); - -//printf("event_sample.scale: %f, diff_power_db: %f, target_power_db: %f, sel_power_db: %f\n", event_sample.scale, diff_power_db, target_power_db, sel_power_db); - +			// Dynamic expander (only enabled if log-power is configured) +			if(settings.drumkit_is_log_power) +			{ +				auto target_dynamic_db = 50.0; // dB, defined maximum dynamic after expander +				event_sample.scale = pow(10.0, (event.velocity * target_dynamic_db + instr->getMaxPower() - target_dynamic_db - sample->getPower()) / 20); +			}  		}  	} @@ -359,7 +361,7 @@ bool InputProcessor::processChoke(event_t& event,  if(event.offset >= 1000000) // quick hack: added 1000000 to offset to transport hi-hat controller value  {    int hihat_controller = event.offset - 1000000; -  int rampdown_time = static_cast<int>(std::max(100.0, pow(10.0, (127.0 - hihat_controller) / 38.0))); // TODO optimize +  int rampdown_time = static_cast<int>(std::max(180.0, pow(10.0, (127.0 - hihat_controller) / 38.0))); // TODO optimize    applyChoke(settings, event_sample, rampdown_time, 0);  }  else diff --git a/src/midimapparser.cc b/src/midimapparser.cc index 059dfec..2361199 100644 --- a/src/midimapparser.cc +++ b/src/midimapparser.cc @@ -45,11 +45,17 @@ bool MidiMapParser::parseFile(const std::string& filename)  		constexpr int bad_value = 10000;  		auto note = map_node.attribute("note").as_int(bad_value);  		auto instr = map_node.attribute("instr").as_string(); +		auto controlthresh = map_node.attribute("controlthresh").as_int(bad_value);  		if(std::string(instr) == "" || note == bad_value)  		{  			continue;  		} +		if(controlthresh != bad_value) +		{ +			controlthreshmap[note][instr] = controlthresh; +		} +  		midimap[note] = instr;  	} diff --git a/src/midimapparser.h b/src/midimapparser.h index d2f2ddd..d13b4f5 100644 --- a/src/midimapparser.h +++ b/src/midimapparser.h @@ -35,4 +35,5 @@ public:  	bool parseFile(const std::string& filename);  	midimap_t midimap; +	controlthreshmap_t controlthreshmap;  }; diff --git a/src/midimapper.cc b/src/midimapper.cc index 9593aae..1f75461 100644 --- a/src/midimapper.cc +++ b/src/midimapper.cc @@ -26,7 +26,7 @@   */  #include "midimapper.h" -int MidiMapper::lookup(int note) +int MidiMapper::lookup(int note, int controller)  {  	std::lock_guard<std::mutex> guard(mutex); @@ -42,15 +42,53 @@ int MidiMapper::lookup(int note)  		return -1;  	} +	if(controller >= 0 && !controlthreshmap[note].empty()) +	{ +		// find instrument where controller is above threshold with smallest distance to threshold +		int diff = 10000; +		std::string instr = controlthreshmap[note].begin()->first; +		for(auto& control_thresh : controlthreshmap[note]) +		{ +			int cur_diff = controller - control_thresh.second; +			if(cur_diff >= 0 && cur_diff < diff) +			{ +				diff = cur_diff; +				instr = control_thresh.first; +			} +		} +		instrmap_it = instrmap.find(instr); +	} +  	return instrmap_it->second;  } -void MidiMapper::swap(instrmap_t& instrmap, midimap_t& midimap) +void MidiMapper::swap(instrmap_t& instrmap, midimap_t& midimap, controlthreshmap_t& controlthreshmap)  {  	std::lock_guard<std::mutex> guard(mutex);  	std::swap(this->instrmap, instrmap);  	std::swap(this->midimap, midimap); +	std::swap(this->controlthreshmap, controlthreshmap); + +	// find instruments which define a control threshold and store it +	for(auto& control_thresh : this->controlthreshmap) +	{ +		for(auto& instr : control_thresh.second) +		{ +			auto instrmap_it = this->instrmap.find(instr.first); +			if(instrmap_it != this->instrmap.end()) +			{ +				instwithcontrolthresh.push_back(instrmap_it->second); +			} +			maxcontrolthresh = std::max(maxcontrolthresh, instr.second); +		} +	} + +	// in case no controller threshold is defined, use fix definition +	if(maxcontrolthresh == 0) +	{ +		maxcontrolthresh = 100; +	}  }  const midimap_t& MidiMapper::getMap() diff --git a/src/midimapper.h b/src/midimapper.h index 4673e33..adb5777 100644 --- a/src/midimapper.h +++ b/src/midimapper.h @@ -29,25 +29,36 @@  #include <map>  #include <string>  #include <mutex> +#include <vector>  typedef std::map<int, std::string> midimap_t;  typedef std::map<std::string, int> instrmap_t; +typedef std::map<int, std::map<std::string, int> > controlthreshmap_t;  class MidiMapper  {  public:  	//! Lookup note in map and return its index.  	//! \returns -1 if not found or the note index. -	int lookup(int note); +	int lookup(int note, int controller = -1); + +	//! Get all instruments with controller thresholds defined. +	std::vector<int>& getInstWithControlthresh() { return instwithcontrolthresh; } + +	//! Get the maximum configured control threshold +	int getMaxControlthresh() { return maxcontrolthresh; }  	//! Set new map sets. -	void swap(instrmap_t& instrmap, midimap_t& midimap); +	void swap(instrmap_t& instrmap, midimap_t& midimap, controlthreshmap_t& controlthreshmap);  	const midimap_t& getMap();  private:  	instrmap_t instrmap;  	midimap_t midimap; +	controlthreshmap_t controlthreshmap; +	std::vector<int> instwithcontrolthresh; +	int maxcontrolthresh{0};  	std::mutex mutex;  }; diff --git a/src/settings.h b/src/settings.h index 5c2e4ee..f2d656e 100644 --- a/src/settings.h +++ b/src/settings.h @@ -3,7 +3,7 @@   *            settings.h   *   *  Tue Mar 22 10:59:46 CET 2016 - *  Copyright 2016 Christian Glöckner + *  Copyright 2016 Christian Gl�ckner   *  cgloeckner@freenet.de   ****************************************************************************/ @@ -53,6 +53,7 @@ struct Settings  	Atomic<std::string> drumkit_description{""};  	Atomic<std::string> drumkit_version{""};  	Atomic<std::size_t> drumkit_samplerate{44100}; +	Atomic<bool> drumkit_is_log_power{false};  	//! The maximum amount of memory in bytes that the AudioCache  	//! is allowed to use for preloading. Default is 1GB.  | 
