Bug in AudioFileBuffer with different sample sizes?


    Mar 22 2008 | 11:28 am
    hallo, i'm using AudioFileBuffer from the max mxj api to read soundfiles with varying sample sizes. when i try to output the floating point data from the buf field, i get correct results only for 16 bit files. 8 bit, 24 bit and 32 bit are all wrong, which to me looks like errors in int-to-float-conversion. do i overlook something here? thanks, volker.
    simple test class:
    import com.cycling74.max.*; import com.cycling74.msp.*;
    public class test_afb extends MaxObject { private AudioFileBuffer afb = null;
    public test_afb (Atom[] args) { declareInlets(new int[]{DataTypes.ALL}); declareOutlets(new int[]{DataTypes.ALL}); }
    /* load soundfile----------------------------------------------------*/ publicvoid open( String path ) { String fname = MaxSystem.locateFile(path); post("filename: "+fname);
    try { afb = new AudioFileBuffer(fname); System.out.println("frame length: "+ afb.getFrameLength()); System.out.println("samp size in bits: "+ afb.getSampleSizeInBits ()); System.out.println("num channels: "+ afb.getChannels()); System.out.println("big endian: "+ afb.isBigEndian()); System.out.println("sample rate: "+ afb.getSampleRate()); } catch(Exception e) { error("mxj test_afb: sorry, can't open that file!"); } }
    /* output sample value at index from channel 1-------------------*/ publicvoid inlet (int index) { outlet(0, afb.buf[0][index]); } }
    simple test patch:

    • Mar 22 2008 | 5:44 pm
    • Mar 23 2008 | 6:26 pm
      On 22 Mar 2008, at 18:44, topher lafata wrote: > i dont think you have overlooked anything. it is very possible > there are bugs with those bit depths. > Regardless here is the source for the class. You could copy it and > make your own.
      hi topher, thanks for the class file - interesting to look inside. i think i found the reason, why the conversion didn't work correctly, although i don't fully understand it... it seems that the fact it works for 16bit files is rather a fortunate coincidence, but which concealed why the others don't work.
      in fill_buf() you do: si = (int)( ((tmp[i+ch_offset] & 0xff) << 16) | ((tmp[i+ch_offset+1] & 0xff) << 8) | (tmp[i+ch_offset+2] & 0xff));
      where i found that the MSB needs to stay a signed byte in order for the two's complement to work. so omitting '& 0xff' in the MSB fixes the 24bit inconsistencies for me. si = (int)( ((tmp[i+ch_offset]) << 16) | ((tmp[i+ch_offset+1] & 0xff) << 8) | (tmp[i+ch_offset+2] & 0xff));
      i also found that this is the same for the other bit depths. the 16bit case simply worked because of the explicit cast to short.
      aha, and the division of the 8bit values should of course be 128 (or 127).
      there is no handling for 32 bit files. for the sake of completeness, this should be added, i think.
      i have fixed this in my own class for now, but it would certainly be nice to have a fix in AudioFileBuffer some time in the future.
      thanks, volker.
    • Mar 23 2008 | 6:39 pm
      Thanks a lot for the info. What you are saying totally makes sense. It was a fortunate circumstance that made 16 bit work and that was the only one I got to test because I was in the middle of something else when that class was busted out.if you fix anything else or do the 32 bit case please re post the code and I will get jkc to check stuff back into the trunk so it makes it into the next release. /* FROM SIDEKICK LX*/
    • May 08 2012 | 8:56 pm
      Hello, sorry for bumping this old post but has this issue been solved? I'm encountering similar issues trying to read audio files using AudioFileBuffer. When trying to read a 24bit aif file the data is nonsense. 16bit aif files work better but is still not completely accurate.