diff options
author | Stian Selnes <stian@pexip.com> | 2016-10-03 18:43:24 +0200 |
---|---|---|
committer | Tim-Philipp Müller <tim@centricular.com> | 2017-11-25 11:10:27 +0000 |
commit | c9002e3dd52614a7df1a0992fe4a8453a74cda81 (patch) | |
tree | 46d0543e1e3b1c956dca469b126ae5193ec72f7c | |
parent | 531b1e326f06a75ac526d6f33dc20d7222472827 (diff) | |
download | gstreamer-plugins-bad-c9002e3dd52614a7df1a0992fe4a8453a74cda81.tar.gz |
netsim: Add gamma distribution for delay
This simulates the delay on wifi networks better.
-rw-r--r-- | gst/netsim/gstnetsim.c | 75 | ||||
-rw-r--r-- | gst/netsim/gstnetsim.h | 3 |
2 files changed, 69 insertions, 9 deletions
diff --git a/gst/netsim/gstnetsim.c b/gst/netsim/gstnetsim.c index d615ba0a6..29a2f7044 100644 --- a/gst/netsim/gstnetsim.c +++ b/gst/netsim/gstnetsim.c @@ -43,6 +43,7 @@ distribution_get_type (void) static const GEnumValue values[] = { {DISTRIBUTION_UNIFORM, "uniform", "uniform"}, {DISTRIBUTION_NORMAL, "normal", "normal"}, + {DISTRIBUTION_GAMMA, "gamma", "gamma"}, {0, NULL, NULL} }; GType g_define_type_id = @@ -226,20 +227,17 @@ get_random_value_uniform (GRand * rand_seed, gint32 min_value, gint32 max_value) return g_rand_int_range (rand_seed, min_value, max_value + 1); } -/* Generate a value from a normal distributation with 95% confidense interval - * between LOW and HIGH, using the Box-Muller transform. */ -static gint -get_random_value_normal (GRand * rand_seed, gint32 low, gint32 high, +/* Use the Box-Muller transform. */ +static gdouble +random_value_normal (GRand * rand_seed, gdouble mu, gdouble sigma, NormalDistributionState * state) { gdouble u1, u2, t1, t2; - gdouble mu = (high + low) / 2.0; - gdouble sigma = (high - low) / (2 * 1.96); /* 95% confidence interval */ state->generate = !state->generate; if (!state->generate) - return round (state->z1 * sigma + mu); + return state->z1 * sigma + mu; do { u1 = g_rand_double (rand_seed); @@ -251,7 +249,64 @@ get_random_value_normal (GRand * rand_seed, gint32 low, gint32 high, state->z0 = t1 * cos (t2); state->z1 = t1 * sin (t2); - return round (state->z0 * sigma + mu); + return state->z0 * sigma + mu; +} + +/* Generate a value from a normal distributation with 95% confidense interval + * between LOW and HIGH */ +static gint +get_random_value_normal (GRand * rand_seed, gint32 low, gint32 high, + NormalDistributionState * state) +{ + gdouble mu = (high + low) / 2.0; + gdouble sigma = (high - low) / (2 * 1.96); /* 95% confidence interval */ + gdouble z = random_value_normal (rand_seed, mu, sigma, state); + + return round (z); +} + +/* Marsaglia and Tsang's method */ +static gdouble +random_value_gamma (GRand * rand_seed, gdouble a, gdouble b, + NormalDistributionState * state) +{ + const gdouble d = a - 1.0 / 3.0; + const gdouble c = 1.0 / sqrt (9 * d); + gdouble x, u, z, v; + + if (a >= 1.0) { + while (TRUE) { + z = random_value_normal (rand_seed, 0.0, 1.0, state); + if (z > -1.0 / c) { + u = g_rand_double (rand_seed); + v = 1.0 + c * z; + v = v * v * v; + if (log (u) < (0.5 * z * z + d * (1 - v + log (v)))) { + x = d * v; + break; + } + } + } + } else { + u = g_rand_double (rand_seed); + x = random_value_gamma (rand_seed, a + 1, b, state) * pow (u, 1.0 / a); + } + + return x * b; +} + +static gint +get_random_value_gamma (GRand * rand_seed, gint32 low, gint32 high, + NormalDistributionState * state) +{ + /* shape parameter 1.25 gives an OK simulation of wireless networks */ + /* Find the scale parameter so that P(0 < x < high-low) < 0.95 */ + /* We know: P(0 < x < R) < 0.95 for gamma(1.25, 1), R = 3.4640381 */ + gdouble shape = 1.25; + gdouble scale = (high - low) / 3.4640381; + gdouble x = random_value_gamma (rand_seed, shape, scale, state); + /* Add offset so that low is the minimum possible value */ + return round (x + low); } @@ -276,6 +331,10 @@ gst_net_sim_delay_buffer (GstNetSim * netsim, GstBuffer * buf) delay = get_random_value_normal (netsim->rand_seed, netsim->min_delay, netsim->max_delay, &netsim->delay_state); break; + case DISTRIBUTION_GAMMA: + delay = get_random_value_gamma (netsim->rand_seed, netsim->min_delay, + netsim->max_delay, &netsim->delay_state); + break; default: g_assert_not_reached (); break; diff --git a/gst/netsim/gstnetsim.h b/gst/netsim/gstnetsim.h index 8e4d75032..c9e32d8fd 100644 --- a/gst/netsim/gstnetsim.h +++ b/gst/netsim/gstnetsim.h @@ -49,7 +49,8 @@ typedef struct _GstNetSimClass GstNetSimClass; typedef enum { DISTRIBUTION_UNIFORM, - DISTRIBUTION_NORMAL + DISTRIBUTION_NORMAL, + DISTRIBUTION_GAMMA } GstNetSimDistribution; typedef struct |