Setting very small values into a buffer~
Hi all,
I'm a very new M4L user, so apologies in advance for my stupid questions!
I'm trying to build a patch that needs to be able to send out sample values of very small amplitude. If they were represented by 32bit integers, they would be between 1 and 16. I'm using the peek~ object to set them and the scale object to convert values into the 0..1 32bit float range with apparently no success.
I suspect I'm suffering from rounding errors somewhere along the way, but a pair of scale objects are at least converting to and from my integer values.
Does anyone have any tips? Did any of that make any sense to you?
Thanks,
Will
are you meaning that amplitude should be in the range of -0.5 to 0.5 ? then just divide the signal by 2 ?..
teh 32 bit you're talking about is a manner of coding numerical values, and probably should not be at the center of your preoccupations here.
Hi vichug,
Thanks for your reply. I'm not sure my original post was very clear as to what I am trying to achieve. The destination for my audio signal is a CV handler in another application and it understands 32 bit integer, so expresses its signal amplitude in integers between -2,147,483,648 and 2,147,483,647. Obviously, Max's way of expressing the equivalent is a floating point value between -1 and 1.
If I want to output a set of sample values with amplitudes of between 1 and 16 in 32 bit integer terms, that effectively means dividing each integer by 2,147,483,647. However, I don't seem to be getting the right value at the destination, which leads me to believe that there is a rounding error occurring at some point.
N.B. The scale inputs I'm using are "0. 1. 0 2147483647" and "0 2147483647 0. 1." respectively.
One other point worth noting is that I'm using play~ to play back the contents of the buffer~ and I wonder whether there's some interpolation at work. I will test out using wave~ (with interpolation disabled) and index~ to see if these help.
Cheers,
Will
Ah! .. it makes much more sense now. But i'm not really aware of cv...
and it's very possible that play~ uses interpolation
For reference, using wave~ with the @interp attribute set to 0 did the trick :)
In case anyone else needs to be able to set explicit values into a signal, count~ and index~ are also a good option for this.
Glad you seem to have found a solution.
The problem (to the extent I have correctly understood what you were doing) is that with integers you were working with the four least significant bits of the integer range (value from 0 to 15; 16 gets you the fifth bit) but then you were converting the full 32-bit integer range to floating point. With 32-bit floats, you only have a 24-bit mantissa, so when converting from integers you lose the eight least significant bits. The remaining bits in the numbers you're working with are all zeros.
If your integer range is [0 .. 16] and you just want to use [buffer~] as a convenient storage facility, you could [scale 0. 16. 0. 1.] going into the [buffer~] and [scale 0. 1. 0 16] going out.
For that matter, there's no reason to use scale at all. People get hung up about audio being in the unit range, but [buffer~] is just a storage container for 32-bit floats. Just poke your integers 0—16 into the [buffer~] and peek them out again. [buffer~] will happily store any values you can put into a floating point value. And that's a lot bigger than [0 .. 16]
You are correct that we weren't able to use those very small values in the end, for exactly that reason. Actually we needed the signal to leave Max, so actually we ended up having to scale the values up and then back down on the other side, but at least they were accurate using this method.
One other gotcha I found along the way was the rounding that putting floats into [coll]s implies. I had to multiply them by a large power of two for storage and then dividing by it on retrieval. As you may see from my other recent post about MIDI event handling, I actually ended up implementing it all as an mxj~, which made it all a little bit more straightforward.