if had array of numbers such [3, 5, 0, 8, 4, 2, 6], there way “smooth out” values they’re closer each other , display less variance?
i’ve looked windowing data using called gaussian function 1-dimensional case, array, having trouble implementing it. this thread seems solve need don’t understand how user naschilling (second post) came gaussian matrix values.
context: i’m working on music waveform generator (borrowing soundcloud’s design) maps amplitude of song @ time t corresponding bar height. unfortunately there’s lot of noise, , looks particularly ugly when program maps tiny amplitude results in sudden decrease in height. want smooth out bar heights aren’t varied.
the language i'm using javascript.
edit: sorry, let me more specific "smoothing out" values. according thread linked above, user took array
[10.00, 13.00, 7.00, 11.00, 12.00, 9.00, 6.00, 5.00]
and used gaussian function map to
[ 8.35, 9.35, 8.59, 8.98, 9.63, 7.94, 5.78, 7.32]
notice how numbers closer each other.
edit 2: worked! user awal garg's algorithm, here results:
no smoothing some smoothing
maximum smoothing
edit 3: here's final code in js. tweaked first , last elements of array able find neighbors wrapping around array, rather calling itself.
var array = [10, 13, 7, 11, 12, 9, 6, 5]; function smooth(values, alpha) { var weighted = average(values) * alpha; var smoothed = []; (var in values) { var curr = values[i]; var prev = smoothed[i - 1] || values[values.length - 1]; var next = curr || values[0]; var improved = number(this.average([weighted, prev, curr, next]).tofixed(2)); smoothed.push(improved); } return smoothed; } function average(data) { var sum = data.reduce(function(sum, value) { return sum + value; }, 0); var avg = sum / data.length; return avg; } smooth(array, 0.85);
interesting question!
the algorithm smooth out values vary lot, here take:
"use strict"; var array = [10, 13, 7, 11, 12, 9, 6, 5]; function avg (v) { return v.reduce((a,b) => a+b, 0)/v.length; } function smoothout (vector, variance) { var t_avg = avg(vector)*variance; var ret = array(vector.length); (var = 0; < vector.length; i++) { (function () { var prev = i>0 ? ret[i-1] : vector[i]; var next = i<vector.length ? vector[i] : vector[i-1]; ret[i] = avg([t_avg, avg([prev, vector[i], next])]); })(); } return ret; } function display (x, y) { console.clear(); console.assert(x.length === y.length); x.foreach((el, i) => console.log(`${el}\t\t${y[i]}`)); } display(array, smoothout(array, 0.85));
note: uses es6 features fat-arrow functions , template strings. firefox 35+ , chrome 45+ should work fine. please use babel repl otherwise.
my method computes average of elements in array in advance, , uses major factor compute new value along current element value, 1 prior it, , 1 after it. using prior value 1 newly computed , not 1 original array. feel free experiment , modify according needs. can pass in "variance" parameter control difference between elements. lowering bring elements closer each other since decreases value of average.
a slight variation loosen out smoothing this:
"use strict"; var array = [10, 13, 7, 11, 12, 9, 6, 5]; function avg (v) { return v.reduce((a,b) => a+b, 0)/v.length; } function smoothout (vector, variance) { var t_avg = avg(vector)*variance; var ret = array(vector.length); (var = 0; < vector.length; i++) { (function () { var prev = i>0 ? ret[i-1] : vector[i]; var next = i<vector.length ? vector[i] : vector[i-1]; ret[i] = avg([t_avg, prev, vector[i], next]); })(); } return ret; } function display (x, y) { console.clear(); console.assert(x.length === y.length); x.foreach((el, i) => console.log(`${el}\t\t${y[i]}`)); } display(array, smoothout(array, 0.85));
which doesn't take averaged value major factor.
feel free experiment, hope helps!
Comments
Post a Comment