Re: normalizing a value

2015-07-02 Thread Skip Montanaro
This looks like a straightforward linear transformation issue to me
(like Fahrenheit to Celsius). Add 50 to all input values, giving you
values in the range 0 to 100. Then scale them into your 0 to 12 range
by multiplying them by 12/100:

 for n in range(-50, 50, 3):
...   print n, n + 50, (n + 50) * 12 / 100
...
-50 0 0.0
-47 3 0.36
-44 6 0.72
-41 9 1.08
-38 12 1.44
...
34 84 10.08
37 87 10.44
40 90 10.8
43 93 11.16
46 96 11.52
49 99 11.88

Did I misread your request in some way?

Skip
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: normalizing a value

2015-07-02 Thread bvdp
On Wednesday, July 1, 2015 at 8:37:18 PM UTC-7, Dennis Lee Bieber wrote:
 On Wed, 1 Jul 2015 18:49:34 -0700 (PDT), bvdp b...@mellowood.ca declaimed
 the following:
 
 
 Thanks guys. Yes, that is exactly what I want. I have a number of places 
 where a MIDI note value is being generated. MIDI should be 0..127, but the 
 process creates notes outside the range. Guess that's another question: if 
 the value I have is 0 or 127 I add/subtract 12 'til it's in range. Don't 
 see using modulo working on this???
 
 As far as the original question: Yes, that's what I need. At times I need to 
 take a note (say 14) and map it into a single octave range. So, the 12 
 becomes 2. Both 14 and 2 are numeric values for note d, just an octave 
 apart.
 
 
 Modulo will give you the note, but throws out the octave.
 
 Your original post specified -50..50, which spans only 101 values, whereas
 MIDI spans 128 values -- so what do you really consider out of range? And
 what MIDI value is -50 supposed to map against. Is input 0 supposed to
 represent middle-C with negative values being notes on the bass clef and
 positive values being treble clef?
 
 MIDI middle-C is note 60. Presuming your 0 is supposed to be middle-C, I'd
 do the transformation as:
 
 midiNote = invalue + 60
 if midiNote  0: midiNote = midiNote % 12
 if midiNote  127: midiNote = (midiNote % 12) + 115
 
 which actually means input values of -60..+67 are shifted directly to a
 midi note number, and values outside of that range are shadowed as the
 lowest or highest octave.
 
  for i in range(-70, 80, 4):
 ...   midiNote = i + 60
 ...   if midiNote  0: midiNote = midiNote % 12
 ...   if midiNote  127: midiNote = ((midiNote - 5) % 12) + 113
 ...   print i, midiNote, CcDdEFfGgAaB[midiNote % 12], divmod(midiNote,
 12)
 ... 
 -70 2 D (0, 2)
 -66 6 f (0, 6)
 -62 10 a (0, 10)
 -58 2 D (0, 2)
 -54 6 f (0, 6)
 -50 10 a (0, 10)
 -46 14 D (1, 2)
 -42 18 f (1, 6)
 -38 22 a (1, 10)
 -34 26 D (2, 2)
 -30 30 f (2, 6)
 -26 34 a (2, 10)
 -22 38 D (3, 2)
 -18 42 f (3, 6)
 -14 46 a (3, 10)
 -10 50 D (4, 2)
 -6 54 f (4, 6)
 -2 58 a (4, 10)
 2 62 D (5, 2)
 6 66 f (5, 6)
 10 70 a (5, 10)
 14 74 D (6, 2)
 18 78 f (6, 6)
 22 82 a (6, 10)
 26 86 D (7, 2)
 30 90 f (7, 6)
 34 94 a (7, 10)
 38 98 D (8, 2)
 42 102 f (8, 6)
 46 106 a (8, 10)
 50 110 D (9, 2)
 54 114 f (9, 6)
 58 118 a (9, 10)
 62 122 D (10, 2)
 66 126 f (10, 6)
 70 118 a (9, 10)
 74 122 D (10, 2)
 78 114 f (9, 6)
  
 
 The oddity for the 127 case is that 127 is not an even octave break point.
 divmod() gives you the octave and the note.
 -- 
   Wulfraed Dennis Lee Bieber AF6VN
 wlfr...@ix.netcom.comHTTP://wlfraed.home.netcom.com/

Thanks. I like your solution for values 0 127. Makes more sense than 
mindlessly adding/subtracting 12 to bring into range. In this case I'm just 
trying to take an out-of-range note to the top/bottom of the valid midi range.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: normalizing a value

2015-07-01 Thread Mark Lawrence

On 02/07/2015 01:12, bvdp wrote:

Not sure what this is called (and I'm sure it's not normalize). Perhaps 
scaling?

Anyway, I need to convert various values ranging from around -50 to 50 to an 0 
to 12 range (this is part of a MIDI music program). I have a number of places 
where I do:

while x  0: x += 12
while x = 12: x -= 12

Okay, that works. Just wondering if there is an easier (or faster) way to 
accomplish this.



Further to other answers have you tried looking for a library, or even 
just a recipe, that has already been written and tested that does this 
for you?


--
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

--
https://mail.python.org/mailman/listinfo/python-list


Re: normalizing a value

2015-07-01 Thread bvdp
On Wednesday, July 1, 2015 at 6:27:57 PM UTC-7, rand...@fastmail.us wrote:
 On Wed, Jul 1, 2015, at 20:12, bvdp wrote:
  Not sure what this is called (and I'm sure it's not normalize). Perhaps
  scaling?
  
  Anyway, I need to convert various values ranging from around -50 to 50 to
  an 0 to 12 range (this is part of a MIDI music program). I have a number
  of places where I do:
  
 while x  0: x += 12
 while x = 12: x -= 12
 
 And this gives you what you want? With e.g. 13=1, 14=2, 22=10, 23=11,
 24=0, 25 = 1, etc. Seems unusual that that's what you would want.
 
 Also note this gives an 0 to 11 range for the results, not 0 to 12.
 
 Anyway, x %= 12 will give the same results.

Thanks guys. Yes, that is exactly what I want. I have a number of places where 
a MIDI note value is being generated. MIDI should be 0..127, but the process 
creates notes outside the range. Guess that's another question: if the value I 
have is 0 or 127 I add/subtract 12 'til it's in range. Don't see using modulo 
working on this???

As far as the original question: Yes, that's what I need. At times I need to 
take a note (say 14) and map it into a single octave range. So, the 12 becomes 
2. Both 14 and 2 are numeric values for note d, just an octave apart.

Interesting that negative values translate properly. That's an non-intuitive 
result to me. Guess I should have studied that math stuff harder way back when!


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: normalizing a value

2015-07-01 Thread Steven D'Aprano
On Thu, 2 Jul 2015 10:12 am, bvdp wrote:

 Not sure what this is called (and I'm sure it's not normalize). Perhaps
 scaling?


Could be normalising, could be scaling.
 
 Anyway, I need to convert various values ranging from around -50 to 50 to
 an 0 to 12 range (this is part of a MIDI music program). I have a number
 of places where I do:

You say around -50 to 50. Can you get 51? 151? How do you want to treat
such out of range numbers?

Are the values integer valued, or can they include fractional values like
27.356?

while x  0: x += 12
while x = 12: x -= 12
 
 Okay, that works. Just wondering if there is an easier (or faster) way to
 accomplish this.


One approach is to just re-scale the numbers from the range -50...50 to
0...12 inclusive. That is:

before = after
-50 = 0
0 = 6
50 = 12


and everything in between is scaled equivalently. Given x between -50 and 50
inclusive, calculate:

y = (x+50)/100.0*12


(Note that in Python 2, you need to make at least one of those values a
float, otherwise you may get unexpected results.)

That will give you y values from the range 0.0 to 12.0 inclusive. If x is
less than -50.0 or more than +50.0 y will likewise be out of range. You can
clip the result:

y = min(12.0, max(0.0, y))

If your x values are integer values (no fractional values) between -50 and
+50 you can use clock arithmetic. Think of a clock marked 0 to 12 (so there
are 13 values), once you reach 12 adding 1 takes you back to 0.

0, 13, 26, 39 = 0
1, 14, 27, 40 = 1
2, 15, 28, 41 = 2
...
12, 25, 38, 51 = 12


Extending that to negative values in the most obvious fashion:

-1, -14, -27, -40 = 12
...
-12, -25, -38, -51 = 1
-13, -26, -39, -52 = 0


We can do that easily with the % (modulo) operator:

y = x % y


Modulo even works with non-integer values:

py 13.5 % 13
0.5



-- 
Steven

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: normalizing a value

2015-07-01 Thread random832
On Wed, Jul 1, 2015, at 21:49, bvdp wrote:
 Interesting that negative values translate properly. That's an
 non-intuitive result to me. Guess I should have studied that math stuff
 harder way back when!

There are multiple interpretations of the operation, and not all
languages behave the same way as Python does with negative operands.
Python is the odd one out when one considers C/C++, C#, and Java which
all behave a different way.

In general, almost all languages behave in a way so that given q, r = a
// b, a % b; q * b + r == a. However, this simply changes the question
to how division results involving negative operands are rounded.

Here's an article by GvR about why python behaves the way it does:
http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: normalizing a value

2015-07-01 Thread bvdp
On Wednesday, July 1, 2015 at 7:15:28 PM UTC-7, Steven D'Aprano wrote:
 On Thu, 2 Jul 2015 10:12 am, bvdp wrote:
 
  Not sure what this is called (and I'm sure it's not normalize). Perhaps
  scaling?
 
 
 Could be normalising, could be scaling.
  
  Anyway, I need to convert various values ranging from around -50 to 50 to
  an 0 to 12 range (this is part of a MIDI music program). I have a number
  of places where I do:
 
 You say around -50 to 50. Can you get 51? 151? How do you want to treat
 such out of range numbers?
 
 Are the values integer valued, or can they include fractional values like
 27.356?
 
 while x  0: x += 12
 while x = 12: x -= 12
  
  Okay, that works. Just wondering if there is an easier (or faster) way to
  accomplish this.
 
 
 One approach is to just re-scale the numbers from the range -50...50 to
 0...12 inclusive. That is:
 
 before = after
 -50 = 0
 0 = 6
 50 = 12
 
 
 and everything in between is scaled equivalently. Given x between -50 and 50
 inclusive, calculate:
 
 y = (x+50)/100.0*12
 
 
 (Note that in Python 2, you need to make at least one of those values a
 float, otherwise you may get unexpected results.)
 
 That will give you y values from the range 0.0 to 12.0 inclusive. If x is
 less than -50.0 or more than +50.0 y will likewise be out of range. You can
 clip the result:
 
 y = min(12.0, max(0.0, y))
 
 If your x values are integer values (no fractional values) between -50 and
 +50 you can use clock arithmetic. Think of a clock marked 0 to 12 (so there
 are 13 values), once you reach 12 adding 1 takes you back to 0.
 
 0, 13, 26, 39 = 0
 1, 14, 27, 40 = 1
 2, 15, 28, 41 = 2
 ...
 12, 25, 38, 51 = 12
 
 
 Extending that to negative values in the most obvious fashion:
 
 -1, -14, -27, -40 = 12
 ...
 -12, -25, -38, -51 = 1
 -13, -26, -39, -52 = 0
 
 
 We can do that easily with the % (modulo) operator:
 
 y = x % y
 
 
 Modulo even works with non-integer values:
 
 py 13.5 % 13
 0.5
 
 
 
 -- 
 Steven

Thanks for this Steven. However, I think it's not correct in this case. Like I 
said in another message X%12 is working just fine. No matter what the value is.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: normalizing a value

2015-07-01 Thread bvdp
On Wednesday, July 1, 2015 at 7:23:19 PM UTC-7, rand...@fastmail.us wrote:
 On Wed, Jul 1, 2015, at 21:49, bvdp wrote:
  Interesting that negative values translate properly. That's an
  non-intuitive result to me. Guess I should have studied that math stuff
  harder way back when!
 
 There are multiple interpretations of the operation, and not all
 languages behave the same way as Python does with negative operands.
 Python is the odd one out when one considers C/C++, C#, and Java which
 all behave a different way.
 
 In general, almost all languages behave in a way so that given q, r = a
 // b, a % b; q * b + r == a. However, this simply changes the question
 to how division results involving negative operands are rounded.
 
 Here's an article by GvR about why python behaves the way it does:
 http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html

Interesting link. Thanks. I always thought that modulo was modulo. Guess this 
is another example of why converting code between languages is hard :)

Anyway, far as shoving my MIDI notes into a single octave, x % 12 seems to be 
perfect.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: normalizing a value

2015-07-01 Thread Paul Rubin
bvdp b...@mellowood.ca writes:
while x  0: x += 12
while x = 12: x -= 12
 Okay, that works. Just wondering if there is an easier (or faster) way
 to accomplish this.

x = x % 12

should be the same as the above.  But are you sure that's really what
you want?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: normalizing a value

2015-07-01 Thread Denis McMahon
On Wed, 01 Jul 2015 17:12:36 -0700, bvdp wrote:

 Not sure what this is called (and I'm sure it's not normalize). Perhaps
 scaling?
 
 Anyway, I need to convert various values ranging from around -50 to 50
 to an 0 to 12 range (this is part of a MIDI music program). I have a
 number of places where I do:
 
while x  0: x += 12 while x = 12: x -= 12
 
 Okay, that works. Just wondering if there is an easier (or faster) way
 to accomplish this.

Are you sure it works? Do you simply want to reduce it to the arbitrary 
range, or do you want to also retain the relationship between different x 
values such that if x1  x2, f(x1)  f(x2)?

Consider the following x values:

-11, -12, -13, 11, 12, 13

-11 - 1
-12 - 0
-13 - 11
11 - 11
12 - 0
13 - 1

So -13 gives the same output value as 11 in your current code. Is this 
what you want?

You could try the following:

# step 1, limit x to the range -50 .. 50
if x  -50:
x = -50.0
ix x = 50:
x = 50.0
# step 2, scale x to the range 0 .. 12
x = x * 0.12 + 6.0

If you want an integer value, you need to determine which method is most 
relevant. I would suggest rounding.

-- 
Denis McMahon, denismfmcma...@gmail.com
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: normalizing a value

2015-07-01 Thread MRAB

On 2015-07-02 01:12, bvdp wrote:

Not sure what this is called (and I'm sure it's not normalize). Perhaps 
scaling?

Anyway, I need to convert various values ranging from around -50 to 50 to an 0 
to 12 range (this is part of a MIDI music program). I have a number of places 
where I do:

while x  0: x += 12
while x = 12: x -= 12

Okay, that works. Just wondering if there is an easier (or faster) way to 
accomplish this.


That's called modular arithmetic. Use the modulo operator, '%':

x = x % 12

or just:

x %= 12

--
https://mail.python.org/mailman/listinfo/python-list


Re: normalizing a value

2015-07-01 Thread random832
On Wed, Jul 1, 2015, at 20:12, bvdp wrote:
 Not sure what this is called (and I'm sure it's not normalize). Perhaps
 scaling?
 
 Anyway, I need to convert various values ranging from around -50 to 50 to
 an 0 to 12 range (this is part of a MIDI music program). I have a number
 of places where I do:
 
while x  0: x += 12
while x = 12: x -= 12

And this gives you what you want? With e.g. 13=1, 14=2, 22=10, 23=11,
24=0, 25 = 1, etc. Seems unusual that that's what you would want.

Also note this gives an 0 to 11 range for the results, not 0 to 12.

Anyway, x %= 12 will give the same results.
-- 
https://mail.python.org/mailman/listinfo/python-list