diff options
Diffstat (limited to 'src/powerlist.cc')
-rw-r--r-- | src/powerlist.cc | 212 |
1 files changed, 90 insertions, 122 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; } |