diff options
| -rw-r--r-- | src/powerlist.cc | 212 | ||||
| -rw-r--r-- | src/powerlist.h | 7 | 
2 files changed, 93 insertions, 126 deletions
| diff --git a/src/powerlist.cc b/src/powerlist.cc index 8fec8ce..4aa916a 100644 --- a/src/powerlist.cc +++ b/src/powerlist.cc @@ -44,12 +44,13 @@   * Limited by sample set size, ie. only kicks in if sample set size is smaller   * than this number.   */ -#define MIN_SAMPLE_SET_SIZE 26 +unsigned int const MIN_SAMPLE_SET_SIZE = 26u;  // Enable to calculate power on old samples without power attribute  //#define AUTO_CALCULATE_POWER +unsigned int const SIZE = 500u; -#define SIZE 500 +float const THRES = 1.f;  PowerList::PowerList(Random& rand)  	: rand(rand) @@ -59,8 +60,6 @@ PowerList::PowerList(Random& rand)  	lastsample = nullptr;  } -#define THRES 1.0 -  void PowerList::add(Sample* sample)  {  	PowerListItem item; @@ -73,38 +72,29 @@ void PowerList::add(Sample* sample)  Channel* PowerList::getMasterChannel()  {  	std::map<Channel*, int> count; - -	std::vector<PowerListItem>::iterator si = samples.begin(); -	while(si != samples.end()) +	 +	for (auto& item: samples)  	{ -		PowerListItem& item = *si; -		Sample* sample = item.sample; - -		Channel* max_channel = nullptr; -		sample_t max_val = 0; - -		// DEBUG(rand, "Sample: %s\n", sample->name.c_str()); - -		size_t ci = 0; -		AudioFiles::iterator ai = sample->audiofiles.begin(); -		while(ai != sample->audiofiles.end()) +		Sample* sample{item.sample}; +		Channel* max_channel{nullptr}; +		sample_t max_val{0}; +		 +		for (auto& pair: sample->audiofiles)  		{ -			Channel* c = ai->first; -			AudioFile* af = ai->second; - +			Channel* c = pair.first; +			AudioFile* af = pair.second; +			  			af->load(SIZE); - -			float silence = 0; -			size_t silence_length = 4; -			for(size_t s = af->size; s > 0 && s > af->size - silence_length; -			    s--) +			 +			float silence{0.f}; +			std::size_t silence_length{4u}; +			for (auto s = af->size; s > 0 && s > af->size - silence_length; --s)  			{  				silence += af->data[s];  			}  			silence /= silence_length; - -			size_t s = 0; -			for(; s < af->size; s++) +			 +			for(auto s = 0u; s < af->size; ++s)  			{  				float val = af->data[s] * af->data[s] * (1.0 / (float)(s + 1));  				if(val > max_val) @@ -114,11 +104,8 @@ Channel* PowerList::getMasterChannel()  					break;  				}  			} - +			  			af->unload(); - -			ai++; -			ci++;  		}  		if(max_channel) @@ -127,27 +114,22 @@ Channel* PowerList::getMasterChannel()  			{  				count[max_channel] = 0;  			} -			count[max_channel]++; +			++count[max_channel];  		} - -		si++;  	} - -	Channel* master = nullptr; -	int max_count = -1; - -	std::map<Channel*, int>::iterator ci = count.begin(); -	while(ci != count.end()) +	 +	Channel* master{nullptr}; +	int max_count{-1}; +	 +	for (auto& pair: count)  	{ -		if(ci->second > max_count && -		    strstr(ci->first->name.c_str(), "Alesis") == 0) +		if (pair.second > max_count && pair.first->name.find("Alesis") == 0u)  		{ -			master = ci->first; -			max_count = ci->second; +			master = pair.first; +			max_count = pair.second;  		} -		ci++;  	} - +	  	return master;  } @@ -155,143 +137,129 @@ void PowerList::finalise()  {  #ifdef AUTO_CALCULATE_POWER  	Channel* master_channel = getMasterChannel(); - +	  	if(master_channel == nullptr)  	{  		ERR(rand, "No master channel found!\n");  		return; // This should not happen...  	} - +	  	DEBUG(rand, "Master channel: %s\n", master_channel->name.c_str());  #endif /*AUTO_CALCULATE_POWER*/ - -	std::vector<PowerListItem>::iterator si = samples.begin(); -	while(si != samples.end()) +	 +	for (auto& item: samples)  	{ -		PowerListItem& item = *si;  		Sample* sample = item.sample; -  #ifdef AUTO_CALCULATE_POWER  		DEBUG(rand, "Sample: %s\n", sample->name.c_str()); - -		AudioFile* master = nullptr; - -		AudioFiles::iterator afi = sample->audiofiles.begin(); -		while(afi != sample->audiofiles.end()) +		 +		AudioFile* master{nullptr}; +		 +		for (auto& af: sample->audiofiles)  		{ -			if(afi->first->name == master_channel->name) +			if (af.first->name == master_channel->name)  			{ -				master = afi->second; +				master = af.second;  				break;  			} -			afi++;  		} - +		  		if(master == nullptr)  		{ -			si++;  			continue;  		} - +		  		master->load();  #endif /*AUTO_CALCULATE_POWER*/ - +		  #ifdef AUTO_CALCULATE_POWER  		if(sample->power == -1)  		{ // Power not defined. Calculate it!  			DEBUG(powerlist, "Calculating power\n"); -			float power = 0; -			size_t s = 0; -			for(; s < SIZE && s < master->size; s++) +			float power{0.f}; +			for(auto s = 0u; s < SIZE && s < master->size; ++s)  			{  				power += master->data[s] * master->data[s];  			} - +			  			power = sqrt(power); - +			  			sample->power = power;  		}  #endif /*AUTO_CALCULATE_POWER*/ - +		  		item.power = sample->power; - +		  		if(item.power > power_max) +		{  			power_max = item.power; +		}  		if(item.power < power_min) +		{  			power_min = item.power; - +		} +		  		DEBUG(rand, " - power: %f\n", item.power); - -		si++;  	}  }  Sample* PowerList::get(level_t level)  { -	int retry = 3; // TODO: This must be user controllable via the UI. - -	Sample* sample = nullptr; -  	if(!samples.size())  	{  		return nullptr; // No samples to choose from.  	} - +	 +	int retry = 3; // TODO: This must be user controllable via the UI. +	 +	Sample* sample{nullptr}; +	  	float power_span = power_max - power_min; - +	  	// Width is limited to at least 10. Fioxes problem with instrument with a  	//  sample set smaller than MIN_SAMPLE_SET_SIZE.  	float width = fmax(samples.size(), MIN_SAMPLE_SET_SIZE); - +	  	// Spread out at most ~2 samples away from center if all samples have a  	// uniform distribution over the power spectrum (which they probably don't).  	float stddev = power_span / width; - +	  	// Cut off mean value with stddev/2 in both ends in order to make room for  	//  downwards expansion on velocity 0 and upwards expansion on velocity 1.  	float mean = level * (power_span - stddev) + (stddev / 2.0); - -again: -	// Select normal distributed value between -	//  (stddev/2) and (power_span-stddev/2) -	float lvl = rand.normalDistribution(mean, stddev); - -	// Adjust this value to be in range -	//  (power_min+stddev/2) and (power_max-stddev/2) -	lvl += power_min; - -	DEBUG(rand, "level: %f, lvl: %f (mean: %.2f, stddev: %.2f)\n", level, lvl, -	    mean, stddev); - -	float power = 0; -	std::vector<PowerListItem>::iterator i = samples.begin(); -	while(i != samples.end()) +	 +	float power{0.f}; +	 +	// note: loop is executed once + #retry +	do  	{ -		if(sample == nullptr) -		{ -			sample = i->sample; -			power = i->power; -		} - -		if(fabs(i->power - lvl) < fabs(power - lvl)) +		--retry; +		 +		// Select normal distributed value between +		//  (stddev/2) and (power_span-stddev/2) +		float lvl = rand.normalDistribution(mean, stddev); +		 +		// Adjust this value to be in range +		//  (power_min+stddev/2) and (power_max-stddev/2) +		lvl += power_min; +		 +		DEBUG(rand, "level: %f, lvl: %f (mean: %.2f, stddev: %.2f)\n", level, lvl, +			mean, stddev); +		 +		for (auto& item: samples)  		{ -			sample = i->sample; -			power = i->power; +			if (sample == nullptr || std::fabs(item.power - lvl) < std::fabs(power - lvl)) +			{ +				sample = item.sample; +				power = item.power; +			}  		} - -		i++; -	} - -	if(lastsample == sample && retry--) -	{ -		DEBUG(rand, "Retry [%d retries left]", retry); -		goto again; -	} - +	} while (lastsample == sample && retry >= 0); +	  	DEBUG(rand, "Found sample with power %f\n", power); - +	  	lastsample = sample; - +	  	return sample;  } diff --git a/src/powerlist.h b/src/powerlist.h index 53a42b8..ff360b4 100644 --- a/src/powerlist.h +++ b/src/powerlist.h @@ -38,13 +38,12 @@ public:  	void add(Sample* s);  	void finalise(); ///< Call this when no more samples will be added. - +	  	Sample* get(level_t velocity);  private: -	class PowerListItem +	struct PowerListItem  	{ -	public:  		Sample* sample;  		float power;  	}; @@ -54,7 +53,7 @@ private:  	std::vector<PowerListItem> samples;  	float power_max;  	float power_min; - +	  	Channel* getMasterChannel();  	Sample* lastsample;  }; | 
