Bug in AudioFileBuffer with different sample sizes?

volker böhm's icon

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:

Max Patch
Copy patch and select New From Clipboard in Max.

topher lafata's icon
volker böhm's icon

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.

topher lafata's icon

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*/

wavy's icon

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.