If you have a problem or need to report a bug please email : support@dsprobotics.com
There are 3 sections to this support area:
DOWNLOADS: access to product manuals, support files and drivers
HELP & INFORMATION: tutorials and example files for learning or finding pre-made modules for your projects
USER FORUMS: meet with other users and exchange ideas, you can also get help and assistance here
NEW REGISTRATIONS - please contact us if you wish to register on the forum
Users are reminded of the forum rules they sign up to which prohibits any activity that violates any laws including posting material covered by copyright
Help With Ruby Normalization
10 posts
• Page 1 of 1
Help With Ruby Normalization
Hey everyone!
I am trying to figure out how to mimic the green "Norm" module with Ruby, so that it normalizes an incoming float array to -1 to 1 range. Its description says "Normalises a float array so that the values are between -1 and 1". I tried looking online for some examples but didnt manage to have the same results as the green module. Does anybody have an idea of a formula how it works?
Thanks!
I am trying to figure out how to mimic the green "Norm" module with Ruby, so that it normalizes an incoming float array to -1 to 1 range. Its description says "Normalises a float array so that the values are between -1 and 1". I tried looking online for some examples but didnt manage to have the same results as the green module. Does anybody have an idea of a formula how it works?
Thanks!
- adamszabo
- Posts: 667
- Joined: Sun Jul 11, 2010 7:21 am
Re: Help With Ruby Normalization
Try looking for 'Rational Mapper', or 'Float Scaler'.
I know we had some from the SM toolboxes.
I know we had some from the SM toolboxes.
- RJHollins
- Posts: 1571
- Joined: Thu Mar 08, 2012 7:58 pm
Re: Help With Ruby Normalization
if a[k] is the array divide each element by max_{k=0...K} |a[k]|
-
martinvicanek - Posts: 1328
- Joined: Sat Jun 22, 2013 8:28 pm
Re: Help With Ruby Normalization
martinvicanek wrote:if a[k] is the array divide each element by max_{k=0...K} |a[k]|
That's producing the range 0, 1 if the numbers are all positive (which for example midi numbers would be). So additionally add ... (- 0.5 * 2) in that case.
Adam, normalizing usually means to set the highest value equal to 1. You do that by dividing all numbers by the highest one. That's what Martin wrote above (in case you are like me and enjoy a little explanation over complicated math).
4/4 = 1
2/4 = 0.5
-2/4 = -0.5
-4/4 = -1
It can get more tricky if the range is somewhat odd, like -2 to 13, or 1 to 9.
EDIT: Ok, here's code in case you indeed want the numbers to be exactly matched to -1 and +1, and don't want to be frustrated by trying it for yourself
- Code: Select all
#some array
a = [-4, 5, 8]
#range covered in array
amin = a.min
amax = a.max
arange = amax - amin
#range we want the array to map to
rmin = -1.0
rmax = 1.0
rrange = rmax - rmin
#map the numbers
r = a.map { |n| n = rmin + (n - amin) * (rrange / arange)}
##of course you can change rmin and rmax to your liking, should you need
##to normalize differently (like 0 to 1, for example)
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
Re: Help With Ruby Normalization
Thanks guys very much appreciated!
Ive tried these but got different results from the Norm module and I started investigating more and with your guys help I figured it out. What the Norm does it finds the largest value, and multiplies it by the difference so that highest value will reach 1. So it does an ABS on all the values, finds the largest, divides 1 by that, and multiplies the entire array like so:
Ive tried these but got different results from the Norm module and I started investigating more and with your guys help I figured it out. What the Norm does it finds the largest value, and multiplies it by the difference so that highest value will reach 1. So it does an ABS on all the values, finds the largest, divides 1 by that, and multiplies the entire array like so:
- Code: Select all
a = @input
output 0, a.map { |n| n * 1 / ( (a.map { |n| n.abs }).max )}
- adamszabo
- Posts: 667
- Joined: Sun Jul 11, 2010 7:21 am
Re: Help With Ruby Normalization
adamszabo wrote:So it does an ABS on all the values, finds the largest, divides 1 by that, and multiplies the entire array like so:
Yes; for normalising audio signals, that makes sense - you need to scale around zero so that a DC offset doesn't get introduced.
NB) The code would work much more efficiently like this...
- Code: Select all
scale = 1.0 / array.max_by{|x| x.abs }
output(0, array.map{|x| x * scale })
Having the scale calculation inside the mapping code block gives you a loop within a loop - the number of iterations goes up with the square of the number of array elements. With scaling moved outside, it's only double the number of elements.
The method max_by handily makes it even more efficient because it doesn't need to create a temporary mapped Array before calling max on it; there's also a min_by method, and even a maxmin_by that gets both at once. They come from the Enumerable module, which is a component of most Ruby containers - it's always worth checking if you don't see what you want under the listings for Array or Hash.)
All schematics/modules I post are free for all to use - but a credit is always polite!
Don't stagnate, mutate to create!
Don't stagnate, mutate to create!
-
trogluddite - Posts: 1730
- Joined: Fri Oct 22, 2010 12:46 am
- Location: Yorkshire, UK
Re: Help With Ruby Normalization
trogluddite wrote:adamszabo wrote:So it does an ABS on all the values, finds the largest, divides 1 by that, and multiplies the entire array like so:
Yes; for normalising audio signals, that makes sense - you need to scale around zero so that a DC offset doesn't get introduced.
NB) The code would work much more efficiently like this...
- Code: Select all
scale = 1.0 / array.max_by{|x| x.abs }
output(0, array.map{|x| x * scale })
Having the scale calculation inside the mapping code block gives you a loop within a loop - the number of iterations goes up with the square of the number of array elements. With scaling moved outside, it's only double the number of elements.
The method max_by handily makes it even more efficient because it doesn't need to create a temporary mapped Array before calling max on it; there's also a min_by method, and even a maxmin_by that gets both at once. They come from the Enumerable module, which is a component of most Ruby containers - it's always worth checking if you don't see what you want under the listings for Array or Hash.)
Now that I see Adam's finding and a nice, clean code from Trog, I think I have to apologize to Martin. Doesn't |a[k]| mean the product of (or absolute of) a for k = 0 to array length? Or do I start to drift right now?
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
Re: Help With Ruby Normalization
tulamide wrote:Doesn't |a[k]| mean the product of (or absolute of) a for k = 0 to array length?
Yes, I meant the maximum of all absolute values.
-
martinvicanek - Posts: 1328
- Joined: Sat Jun 22, 2013 8:28 pm
Re: Help With Ruby Normalization
Thanks you guys are awesome!
Trog your code is great, however I noticed that sometimes my graph was inverted and I noticed that your way of getting abs was givingdifferent results. So if I have a dataset like this:
0
-0.9
0.7
My one "(@input.map { |n| n.abs }).max" gives 0.9
And your one "@input.max_by{|x| x.abs }" gives -0.9
So we have to make another abs on the scale itself, and maybe add a small value to prevent it from getting #IND when dividing by zero?
scale = 1.0 / (@input.max_by{|x| x.abs } + 0.00001)
output(0, @input.map{|x| x * scale.abs })
Trog your code is great, however I noticed that sometimes my graph was inverted and I noticed that your way of getting abs was givingdifferent results. So if I have a dataset like this:
0
-0.9
0.7
My one "(@input.map { |n| n.abs }).max" gives 0.9
And your one "@input.max_by{|x| x.abs }" gives -0.9
So we have to make another abs on the scale itself, and maybe add a small value to prevent it from getting #IND when dividing by zero?
scale = 1.0 / (@input.max_by{|x| x.abs } + 0.00001)
output(0, @input.map{|x| x * scale.abs })
- adamszabo
- Posts: 667
- Joined: Sun Jul 11, 2010 7:21 am
Re: Help With Ruby Normalization
Oops!
Yes, you're quite right, Adam. The max_by method returns the original Array element, not the version transformed by the code block, so you need to abs what it returns.
You don't need the infinity check, though. Infinities are treated as valid number values by the CPU - wherever there is a defined mathematical result, the calculation will work; and dividing by infinity is defined to always return zero (as confirmed by stringing together a couple of float divide primitives.) BTW; strictly speaking, your code doesn't entirely exclude zero - you need to abs before adding the offset, otherwise you get zero if the sample is exactly -0.00001!
Yes, you're quite right, Adam. The max_by method returns the original Array element, not the version transformed by the code block, so you need to abs what it returns.
You don't need the infinity check, though. Infinities are treated as valid number values by the CPU - wherever there is a defined mathematical result, the calculation will work; and dividing by infinity is defined to always return zero (as confirmed by stringing together a couple of float divide primitives.) BTW; strictly speaking, your code doesn't entirely exclude zero - you need to abs before adding the offset, otherwise you get zero if the sample is exactly -0.00001!
All schematics/modules I post are free for all to use - but a credit is always polite!
Don't stagnate, mutate to create!
Don't stagnate, mutate to create!
-
trogluddite - Posts: 1730
- Joined: Fri Oct 22, 2010 12:46 am
- Location: Yorkshire, UK
10 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 71 guests