Setting very small values into a buffer~

    Oct 20 2013 | 7:49 am
    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

    • Oct 21 2013 | 2:02 pm
      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.
    • Oct 21 2013 | 2:33 pm
      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
    • Oct 21 2013 | 6:57 pm
      Ah! .. it makes much more sense now. But i'm not really aware of cv...
      and it's very possible that play~ uses interpolation
    • Nov 03 2013 | 2:05 pm
      For reference, using wave~ with the @interp attribute set to 0 did the trick :)
    • Feb 23 2014 | 10:47 am
      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.
    • Feb 23 2014 | 4:54 pm
      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]
    • Feb 24 2014 | 4:22 pm
      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.