From: M O on
Hi everyone. Let me start off by saying I don't know much (at all) about audio file formats (which is the big problem). I'm trying to debug an old program that reads in data from a wav file using fseek/fread, and runs a bunch of analysis. It only reads in a short clip (maybe 2 sec from a 10 min file). What I'm trying to do is save the clip that's being read into a different wav file to allow further investigation.

My problem is that when I later load the clip, it doesn't look at all like the original. The amplitudes are much much higher, and it just doesn't look right (ie even after adjusting the spectrogram parameters, I can't find the signal of interest that was supposed to have been clipped).

If I use a wavread on the original file, I'm getting values like -.0018, .0097, etc. With the fread function, the values are more like -455, 319. etc. The fread command being used is: [x,count]=fread(fid, segmentLength, 'short');
The wav file is sampled at 96kHz (if that matters). I tried going through the wavread.m file to see how it reads the data, but got completely lost...

Anyone have any ideas? This was supposed to be a quick 1/2 hour job, and I'm into hour 3 now and quickly QUICKLY running out of time. ANY help would be appreciated. Thanks.

Michael
From: Walter Roberson on
M O wrote:
> Hi everyone. Let me start off by saying I don't know much (at all)
> about audio file formats (which is the big problem). I'm trying to
> debug an old program that reads in data from a wav file using
> fseek/fread, and runs a bunch of analysis. It only reads in a short
> clip (maybe 2 sec from a 10 min file). What I'm trying to do is save
> the clip that's being read into a different wav file to allow further
> investigation.
>
> My problem is that when I later load the clip, it doesn't look at all
> like the original. The amplitudes are much much higher, and it just
> doesn't look right (ie even after adjusting the spectrogram parameters,
> I can't find the signal of interest that was supposed to have been
> clipped).
>
> If I use a wavread on the original file, I'm getting values like -.0018,
> .0097, etc. With the fread function, the values are more like -455,
> 319. etc. The fread command being used is: [x,count]=fread(fid,
> segmentLength, 'short');

short is (for this purpose) a 2 byte signed integer, 16 bits total.

wavread() reads files that are internally marked as being in a variety of
internal formats, and wavread() by default converts those to the range +/- 1,
using an undocumented algorithm to do so. The conversion algorithm is not easy
to deduce, as the converted range is -1 *inclusive* to +1 *inclusive* but
nearly all the file formats run from a minimum *inclusive* to a logical upper
bound *exclusive* -- e.g., from -32768 to +32767, an even number of points
when one considers 0, whereas -1 to +1 *inclusive* is an odd number of points
when one considers 0. Only one internal storage format is exactly
representable as -1 to +1 inclusive without loss of information: the 32 bit
floating point number from -1 to +1.

Anyhow, exact preservation of information aside, if the code reads short, that
suggests that the original file is assumed to be stored as 16 bit signed
integers but that the code then converts it to floating point. When you use
wavwrite() to write the file, if you give it floating point and do not tell it
how many bits to save as, it will save it as 16 bit signed integers.

http://www.mathworks.com/access/helpdesk/help/techdoc/ref/wavwrite.html

All things being equal, saving as 16 bit integers for data that was 16 bits
when it was read in should be fine for your purposes. You do need, though, to
cross-check how many columns your data is: each column corresponds to a
channel. (I suspect if there is only 1 row and multiple columns that the data
would be treated as single channel, but that is not documented.)

Chances are good that the original file was not floating point. You can find
out how the data is represented in the files by using wavinfo()
From: M O on
Walter Roberson <roberson(a)hushmail.com> wrote in message <hubeg9$gok$1(a)canopus.cc.umanitoba.ca>...
> M O wrote:
> > Hi everyone. Let me start off by saying I don't know much (at all)
> > about audio file formats (which is the big problem). I'm trying to
> > debug an old program that reads in data from a wav file using
> > fseek/fread, and runs a bunch of analysis. It only reads in a short
> > clip (maybe 2 sec from a 10 min file). What I'm trying to do is save
> > the clip that's being read into a different wav file to allow further
> > investigation.
> >
> > My problem is that when I later load the clip, it doesn't look at all
> > like the original. The amplitudes are much much higher, and it just
> > doesn't look right (ie even after adjusting the spectrogram parameters,
> > I can't find the signal of interest that was supposed to have been
> > clipped).
> >
> > If I use a wavread on the original file, I'm getting values like -.0018,
> > .0097, etc. With the fread function, the values are more like -455,
> > 319. etc. The fread command being used is: [x,count]=fread(fid,
> > segmentLength, 'short');
>
> short is (for this purpose) a 2 byte signed integer, 16 bits total.
>
> wavread() reads files that are internally marked as being in a variety of
> internal formats, and wavread() by default converts those to the range +/- 1,
> using an undocumented algorithm to do so. The conversion algorithm is not easy
> to deduce, as the converted range is -1 *inclusive* to +1 *inclusive* but
> nearly all the file formats run from a minimum *inclusive* to a logical upper
> bound *exclusive* -- e.g., from -32768 to +32767, an even number of points
> when one considers 0, whereas -1 to +1 *inclusive* is an odd number of points
> when one considers 0. Only one internal storage format is exactly
> representable as -1 to +1 inclusive without loss of information: the 32 bit
> floating point number from -1 to +1.
>
> Anyhow, exact preservation of information aside, if the code reads short, that
> suggests that the original file is assumed to be stored as 16 bit signed
> integers but that the code then converts it to floating point. When you use
> wavwrite() to write the file, if you give it floating point and do not tell it
> how many bits to save as, it will save it as 16 bit signed integers.
>
> http://www.mathworks.com/access/helpdesk/help/techdoc/ref/wavwrite.html
>
> All things being equal, saving as 16 bit integers for data that was 16 bits
> when it was read in should be fine for your purposes. You do need, though, to
> cross-check how many columns your data is: each column corresponds to a
> channel. (I suspect if there is only 1 row and multiple columns that the data
> would be treated as single channel, but that is not documented.)
>
> Chances are good that the original file was not floating point. You can find
> out how the data is represented in the files by using wavinfo()

Thanks so much Walter! That was a huge help. The input file was 16 bits, so the wavwrite function did work after all. I adjusted the data first by dividing by 2^15, which got it close to the same levels as when I do a wavread (close is good enough for this - the amplitudes don't matter too much) (plus then I was able to do a much better visual comparison to the original and realize that it was indeed the same signal of interest).

I've added a wavread call just to check the number of bits in the original file and throw an error if it's not 16.

Thanks again for the quick response. I spent about an hour trying to decipher the wav file header information in the hopes of generating my own, but using wavwrite is much easier.

Michael