diff options
-rw-r--r-- | src/powerlist.cc | 382 | ||||
-rw-r--r-- | src/powerlist.h | 39 |
2 files changed, 224 insertions, 197 deletions
diff --git a/src/powerlist.cc b/src/powerlist.cc index b6640e9..f94dbb2 100644 --- a/src/powerlist.cc +++ b/src/powerlist.cc @@ -53,216 +53,244 @@ PowerList::PowerList() { - power_max = 0; - power_min = 100000000; - lastsample = NULL; + power_max = 0; + power_min = 100000000; + lastsample = nullptr; } #define THRES 1.0 -void PowerList::add(Sample *sample) +void PowerList::add(Sample* sample) { - PowerListItem item; - item.power = -1; - item.sample = sample; + PowerListItem item; + item.power = -1; + item.sample = sample; - samples.push_back(item); + samples.push_back(item); } -Channel *PowerList::getMasterChannel() +Channel* PowerList::getMasterChannel() { - std::map<Channel *, int> count; - - std::vector<PowerListItem>::iterator si = samples.begin(); - while(si != samples.end()) { - PowerListItem &item = *si; - Sample *sample = item.sample; - - Channel *max_channel = NULL; - 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()) { - Channel *c = ai->first; - AudioFile *af = ai->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--) { - silence += af->data[s]; - } - silence /= silence_length; - - size_t s = 0; - for(; s < af->size; s++) { - float val = af->data[s] * af->data[s] * (1.0 / (float)(s+1)); - if(val > max_val) { - max_val = val; - max_channel = c; - break; - } - } - - af->unload(); - - ai++; - ci++; - } - - if(max_channel) { - if(count.find(max_channel) == count.end()) count[max_channel] = 0; - count[max_channel]++; - } - - si++; - } - - Channel *master = NULL; - int max_count = -1; - - std::map<Channel *, int>::iterator ci = count.begin(); - while(ci != count.end()) { - if(ci->second > max_count && - strstr(ci->first->name.c_str(), "Alesis") == 0) { - master = ci->first; - max_count = ci->second; - } - ci++; - } - - return master; + std::map<Channel*, int> count; + + std::vector<PowerListItem>::iterator si = samples.begin(); + while(si != samples.end()) + { + 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()) + { + Channel* c = ai->first; + AudioFile* af = ai->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--) + { + silence += af->data[s]; + } + silence /= silence_length; + + size_t s = 0; + for(; s < af->size; s++) + { + float val = af->data[s] * af->data[s] * (1.0 / (float)(s + 1)); + if(val > max_val) + { + max_val = val; + max_channel = c; + break; + } + } + + af->unload(); + + ai++; + ci++; + } + + if(max_channel) + { + if(count.find(max_channel) == count.end()) + { + count[max_channel] = 0; + } + count[max_channel]++; + } + + si++; + } + + Channel* master = nullptr; + int max_count = -1; + + std::map<Channel*, int>::iterator ci = count.begin(); + while(ci != count.end()) + { + if(ci->second > max_count && + strstr(ci->first->name.c_str(), "Alesis") == 0) + { + master = ci->first; + max_count = ci->second; + } + ci++; + } + + return master; } void PowerList::finalise() { #ifdef AUTO_CALCULATE_POWER - Channel *master_channel = getMasterChannel(); + Channel* master_channel = getMasterChannel(); - if(master_channel == NULL) { - ERR(rand, "No master channel found!\n"); - return; // This should not happen... - } + 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*/ + 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()) { - PowerListItem &item = *si; - Sample *sample = item.sample; - - #ifdef AUTO_CALCULATE_POWER - DEBUG(rand, "Sample: %s\n", sample->name.c_str()); - - AudioFile *master = NULL; - - AudioFiles::iterator afi = sample->audiofiles.begin(); - while(afi != sample->audiofiles.end()) { - if(afi->first->name == master_channel->name) { - master = afi->second; - break; - } - afi++; - } - - if(master == NULL) { - si++; - continue; - } - - master->load(); -#endif/*AUTO_CALCULATE_POWER*/ + std::vector<PowerListItem>::iterator si = samples.begin(); + while(si != samples.end()) + { + PowerListItem& item = *si; + Sample* sample = item.sample; #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++) { - 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++; - } -} + DEBUG(rand, "Sample: %s\n", sample->name.c_str()); + + AudioFile* master = nullptr; + + AudioFiles::iterator afi = sample->audiofiles.begin(); + while(afi != sample->audiofiles.end()) + { + if(afi->first->name == master_channel->name) + { + master = afi->second; + break; + } + afi++; + } + + if(master == nullptr) + { + si++; + continue; + } + + master->load(); +#endif /*AUTO_CALCULATE_POWER*/ -Sample *PowerList::get(level_t level) -{ - int retry = 3; // TODO: This must be user controllable via the UI. - - Sample *sample = NULL; +#ifdef AUTO_CALCULATE_POWER + if(sample->power == -1) + { // Power not defined. Calculate it! + DEBUG(powerlist, "Calculating power\n"); - if(!samples.size()) return NULL; // No samples to choose from. + float power = 0; + size_t s = 0; + for(; s < SIZE && s < master->size; s++) + { + power += master->data[s] * master->data[s]; + } - float power_span = power_max - power_min; + power = sqrt(power); - // 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); + sample->power = power; + } +#endif /*AUTO_CALCULATE_POWER*/ - // 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; + item.power = sample->power; - // 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); + if(item.power > power_max) + power_max = item.power; + if(item.power < power_min) + power_min = item.power; -again: - // Select normal distributed value between - // (stddev/2) and (power_span-stddev/2) - float lvl = rand.normalDistribution(mean, stddev); + DEBUG(rand, " - power: %f\n", item.power); - // Adjust this value to be in range - // (power_min+stddev/2) and (power_max-stddev/2) - lvl += power_min; + si++; + } +} - DEBUG(rand, "level: %f, lvl: %f (mean: %.2f, stddev: %.2f)\n", - level, lvl, mean, stddev); +Sample* PowerList::get(level_t level) +{ + int retry = 3; // TODO: This must be user controllable via the UI. - float power = 0; - std::vector<PowerListItem>::iterator i = samples.begin(); - while(i != samples.end()) { - if(sample == NULL) { - sample = i->sample; - power = i->power; - } + Sample* sample = nullptr; - if(fabs(i->power - lvl) < fabs(power - lvl)) { - sample = i->sample; - power = i->power; - } + if(!samples.size()) + { + return nullptr; // No samples to choose from. + } - i++; - } + float power_span = power_max - power_min; - if(lastsample == sample && retry--) { - DEBUG(rand, "Retry [%d retries left]", retry); - goto again; - } + // 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); - DEBUG(rand, "Found sample with power %f\n", power); + // 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; - lastsample = sample; + // 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); - return sample; +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()) + { + if(sample == nullptr) + { + sample = i->sample; + power = i->power; + } + + if(fabs(i->power - lvl) < fabs(power - lvl)) + { + sample = i->sample; + power = i->power; + } + + i++; + } + + if(lastsample == sample && retry--) + { + DEBUG(rand, "Retry [%d retries left]", retry); + goto again; + } + + DEBUG(rand, "Found sample with power %f\n", power); + + lastsample = sample; + + return sample; } diff --git a/src/powerlist.h b/src/powerlist.h index 1077d8c..a3af475 100644 --- a/src/powerlist.h +++ b/src/powerlist.h @@ -24,38 +24,37 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_POWERLIST_H__ -#define __DRUMGIZMO_POWERLIST_H__ +#pragma once #include <vector> #include "sample.h" #include "random.h" -class PowerList { +class PowerList +{ public: - PowerList(); + PowerList(); - void add(Sample *s); - void finalise(); ///< Call this when no more samples will be added. + void add(Sample* s); + void finalise(); ///< Call this when no more samples will be added. - Sample *get(level_t velocity); + Sample* get(level_t velocity); private: - class PowerListItem { - public: - Sample *sample; - float power; - }; + class PowerListItem + { + public: + Sample* sample; + float power; + }; - Random rand; + Random rand; - std::vector<PowerListItem> samples; - float power_max; - float power_min; + std::vector<PowerListItem> samples; + float power_max; + float power_min; - Channel *getMasterChannel(); - Sample *lastsample; + Channel* getMasterChannel(); + Sample* lastsample; }; - -#endif/*__DRUMGIZMO_POWERLIST_H__*/ |