Re: normalizing a value
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
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
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
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
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
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
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
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
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
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
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
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