In this code (adapted from a full piece), I am taking incoming MIDI notes, converting to pch (octave.pitch-class) form, and then using a macro to “transpose” the pitch-class portion so that it is three semitones lower, but I want to keep it in the 0-11 range. The transposed value is printed as “iidx”.
The “transposition” is done with the Index macro, which as you can see subtracts 3, adds 13, and then returns the sum modulo 12.
When I play E-flat (MIDI 51), idx is 0 as expected. This is also true for any lower octave of E-flat. However, if I play E-flat one or more octaves higher (MIDI 63 or higher octaves), idx is 12.
I don’t understand how this is possible. How can 12 % 12 ever be anything but 0?
I hope someone can explain this before I lose what is left of my mind! I’m using Csound 7 built from the latest development code as of yesterday.
Hi Dave,
I see that you multiply the fractional pitch by 100. Shouldn't this be 10?
At any rate, why not, work on the MIDI note first and then convert? I don't know how much of a change it will make, but it seems simpler and thus less error prone and easier to debug.
Without examining it in detail, I think the issue that you are encountering is that one
expects the frac(x)*100 to be a whole number but the floating point operations are not giving you that.
What you are getting printed is an approximation so you don’t see it immediately.
Thanks, Jeanette. 100 is correct, because the pitch-class number uses the two digits to the right of the decimal point. For example, the note C# would be (depending on the octave) something like 8.01, so to make .01 an integer it must be multiplied by 100.
That’s an interesting idea of just working with the MIDI note directly, and I’ll look into that. Thanks for the suggestion!
Thanks, Victor, I was afraid it would be something like that. Since there’s no way to force Csound to treat a number as a plain (non floating point) integer, I may need to follow Jeanette’s suggestion and work with the MIDI note number directly.
I think that even if you use round or floor (or int), the underlying data representation is still a floating point number. Usually this is not an issue, I guess I just hit an edge case.
It does work, in general. If I put that expression in a loop where N runs from 0 to 11, all the answers are correct. But in context, where N is derived from a pch value and promoted to an integer using “frac(ipch) * 100”, it fails for inputs over a certain value. This is 100% repeatable, at least for me.
I have switched to just using “(inote - 3) % 12”, where inote is the value returned from notnum(), and this is working for all input values.