summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndré Nusser <andre.nusser@googlemail.com>2019-03-04 18:26:26 +0100
committerAndré Nusser <andre.nusser@googlemail.com>2019-05-11 14:53:23 +0200
commit1965889ac953b354763f194cd7ec44932942477d (patch)
tree0e726c04946a890e38f0773229314da58862e713 /src
parent32b12957b2fa875a7a0044c7c9c620809de9ae47 (diff)
First version of new sample algorithm.
Diffstat (limited to 'src')
-rw-r--r--src/instrument.cc2
-rw-r--r--src/powerlist.cc73
-rw-r--r--src/powerlist.h4
3 files changed, 51 insertions, 28 deletions
diff --git a/src/instrument.cc b/src/instrument.cc
index 6cc4ee9..ffc928d 100644
--- a/src/instrument.cc
+++ b/src/instrument.cc
@@ -59,7 +59,7 @@ const Sample* Instrument::sample(level_t level, size_t pos)
if(version >= VersionStr("2.0"))
{
// Version 2.0
- return powerlist.get(level * mod);
+ return powerlist.get(level * mod, pos);
}
else
{
diff --git a/src/powerlist.cc b/src/powerlist.cc
index 0ffcb14..e593f7e 100644
--- a/src/powerlist.cc
+++ b/src/powerlist.cc
@@ -53,6 +53,16 @@ std::size_t const MIN_SAMPLE_SET_SIZE = 26u;
//#define AUTO_CALCULATE_POWER
unsigned int const LOAD_SIZE = 500u;
+namespace
+{
+
+float pow2(float f)
+{
+ return f*f;
+}
+
+} // end anonymous namespace
+
PowerList::PowerList(Random& rand, Settings& settings)
: rand(rand)
, settings(settings)
@@ -204,9 +214,11 @@ void PowerList::finalise()
DEBUG(rand, " - power: %f\n", item.power);
}
+
+ last.resize(samples.size(), 0);
}
-Sample* PowerList::get(level_t level)
+Sample* PowerList::get(level_t level, std::size_t pos)
{
auto velocity_stddev = settings.velocity_stddev.load();
@@ -215,12 +227,10 @@ Sample* PowerList::get(level_t level)
return nullptr; // No samples to choose from.
}
- Sample* sample{nullptr};
-
float power_span = power_max - power_min;
// Width is limited to at least 10. Fixes problem with instrument with a
- // sample set smaller than MIN_SAMPLE_SET_SIZE.
+ // sample set smaller than MIN_SAMPLE_SET_SIZE.
float width = std::max(samples.size(), MIN_SAMPLE_SET_SIZE);
// Spread out at most ~2 samples away from center if all samples have a
@@ -228,53 +238,64 @@ Sample* PowerList::get(level_t level)
float mean_stepwidth = 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.
+ // downwards expansion on velocity 0 and upwards expansion on velocity 1.
float mean = level * (power_span - mean_stepwidth) + (mean_stepwidth / 2.0);
float stddev = settings.enable_velocity_modifier.load() ? velocity_stddev * mean_stepwidth : 0.;
- std::size_t index;
- float power{0.f};
- float obj_function_value{std::numeric_limits<float>::max()};
+ std::size_t index_opt = 0;
+ float power_opt{0.f};
+ float value_opt{std::numeric_limits<float>::max()};
+ // TODO: those are mostly for debugging at the moment
+ float random_opt = 0.;
+ float distance_opt = 0.;
+ float recent_opt = 0.;
// Select normal distributed value between
- // (stddev/2) and (power_span-stddev/2)
+ // (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)
+ // (power_min+stddev/2) and (power_max-stddev/2)
lvl += power_min;
- DEBUG(rand, "level: %f, lvl: %f (mean: %.2f, stddev: %.2f, mean_stepwidth: %f,
- power_min: %f, power_max: %f)\n", level, lvl, mean, stddev, mean_stepwidth,
+ DEBUG(rand, "level: %f, lvl: %f (mean: %.2f, stddev: %.2f, mean_stepwidth: %f,"
+ "power_min: %f, power_max: %f)\n", level, lvl, mean, stddev, mean_stepwidth,
power_min, power_max);
- float alpha = 10.0;
- float beta = 1000.0;
- float gamma = 0.0;
+ // TODO: expose parameters to GUI
+ float alpha = 1.0;
+ float beta = 1.0;
+ float gamma = .5;
+ // TODO: start with most promising power value and then stop when reaching far values
+ // which cannot become opt anymore
for (std::size_t i = 0; i < samples.size(); ++i)
{
auto const& item = samples[i];
// compute objective function value
- auto r = rand.floatInRange(0.,1.);
- auto value =
- alpha*pow2(item.power - power) + beta*pow2(1./(current - last[index])) + gamma*r;
+ auto random = rand.floatInRange(0.,1.);
+ auto distance = item.power - lvl;
+ auto recent = (float)settings.samplerate/std::max<std::size_t>(pos - last[i], 1);
+ auto value = alpha*pow2(distance) + beta*pow2(recent) + gamma*random;
- if (value < obj_function_value)
+ if (value < value_opt)
{
- index = i;
- power = item.power;
- obj_function_value = value;
+ index_opt = i;
+ power_opt = item.power;
+ value_opt = value;
+ random_opt = random;
+ distance_opt = distance;
+ recent_opt = recent;
}
}
- DEBUG(rand, "Found sample with power %f\n", power);
+ DEBUG(rand, "Chose sample with index: %d, value: %f, power %f, random: %f, distance: %f, recent: %f", (int)index_opt, value_opt, power_opt, random_opt, distance_opt, recent_opt);
- // FIXME
- lastsample = samples[index].sample;
+ lastsample = samples[index_opt].sample;
+ last[index_opt] = pos;
- return samples[index].sample;
+ return samples[index_opt].sample;
}
float PowerList::getMaxPower() const
diff --git a/src/powerlist.h b/src/powerlist.h
index 6741828..b3b47e4 100644
--- a/src/powerlist.h
+++ b/src/powerlist.h
@@ -41,7 +41,7 @@ public:
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, std::size_t pos);
float getMaxPower() const;
float getMinPower() const;
@@ -62,4 +62,6 @@ private:
const Channel* getMasterChannel();
Sample* lastsample;
+
+ std::vector<std::size_t> last;
};