reading wav files

Discussion in 'C Programming' started by Sarchiapone, Jan 30, 2010.

  1. Sarchiapone

    Sarchiapone Guest

    Has anyone experieces in reading wav files ? After some efforts I was
    able to read the header, but now I need to read the data. I really don't
    understand if they are byte, short in or int. I only get negative
    numbers, if I execute this code

    while(fread(&c,sizeof(short int),1,fp)>0)
    {
    printf("%d\n",c);
    }
    Sarchiapone, Jan 30, 2010
    #1
    1. Advertising

  2. Antoninus Twink, Jan 30, 2010
    #2
    1. Advertising

  3. Sarchiapone

    Sjouke Burry Guest

    Sarchiapone wrote:
    > Has anyone experieces in reading wav files ? After some efforts I was
    > able to read the header, but now I need to read the data. I really don't
    > understand if they are byte, short in or int. I only get negative
    > numbers, if I execute this code
    >
    > while(fread(&c,sizeof(short int),1,fp)>0)
    > {
    > printf("%d\n",c);
    > }
    >

    I have a piece of dos 16 bit software, reading, testing
    and then sounding a wav file on an SB PRO compatible
    soundcard.
    If you want it, tell me where to mail it, source code and exe.
    Sjouke Burry, Jan 30, 2010
    #3
  4. On 01/30/2010 07:18 AM, Sarchiapone wrote:
    > Has anyone experieces in reading wav files ? After some efforts I was
    > able to read the header, but now I need to read the data. I really don't
    > understand if they are byte, short in or int. I only get negative
    > numbers, if I execute this code


    Here's another web page about it:

    http://www.dragonwins.com/wav/

    Each sample type is dictated by the "sample depth" you got out of the
    "fmt " subchunk. If it's 8 bits or less, it's unsigned, else it's
    signed. The number of bytes taken by the sample is the minimum number
    of whole bytes that can store it.

    > while(fread(&c,sizeof(short int),1,fp)>0)
    > {
    > printf("%d\n",c);
    > }


    It's weird, to me, that every number should print as negative, though.
    It seems like /some/ of them should come out as positive even if you're
    reading data of the wrong size or your alignment is off. Maybe it's
    just extremely bad luck?

    -Beej
    Beej Jorgensen, Jan 30, 2010
    #4
  5. Sarchiapone

    Sarchiapone Guest

    Il Sat, 30 Jan 2010 18:03:12 +0100, Sjouke Burry ha scritto:

    > Sarchiapone wrote:
    >> Has anyone experieces in reading wav files ? After some efforts I was
    >> able to read the header, but now I need to read the data. I really
    >> don't understand if they are byte, short in or int. I only get negative
    >> numbers, if I execute this code
    >>
    >> while(fread(&c,sizeof(short int),1,fp)>0) {
    >> printf("%d\n",c);
    >> }
    >>

    > I have a piece of dos 16 bit software, reading, testing and then
    > sounding a wav file on an SB PRO compatible soundcard.
    > If you want it, tell me where to mail it, source code and exe.


    Well, I need source code, for I am compiling under Linux OS. If you could
    send me the code, it would be great. My email address is francesco dot
    difusco at gmail dot com

    Francesco
    Sarchiapone, Jan 30, 2010
    #5
  6. Sarchiapone

    Sarchiapone Guest

    Il Sat, 30 Jan 2010 10:07:51 -0800, Beej Jorgensen ha scritto:

    > On 01/30/2010 07:18 AM, Sarchiapone wrote:
    >> Has anyone experieces in reading wav files ? After some efforts I was
    >> able to read the header, but now I need to read the data. I really
    >> don't understand if they are byte, short in or int. I only get negative
    >> numbers, if I execute this code

    >
    > Here's another web page about it:
    >
    > http://www.dragonwins.com/wav/
    >
    > Each sample type is dictated by the "sample depth" you got out of the
    > "fmt " subchunk. If it's 8 bits or less, it's unsigned, else it's
    > signed. The number of bytes taken by the sample is the minimum number
    > of whole bytes that can store it.
    >
    >> while(fread(&c,sizeof(short int),1,fp)>0) {
    >> printf("%d\n",c);
    >> }

    >
    > It's weird, to me, that every number should print as negative, though.
    > It seems like /some/ of them should come out as positive even if you're
    > reading data of the wrong size or your alignment is off. Maybe it's
    > just extremely bad luck?
    >
    > -Beej


    Maybe it is extremely bad luck ;-)
    Sarchiapone, Jan 30, 2010
    #6
  7. Sarchiapone

    Moi Guest

    On Sat, 30 Jan 2010 15:18:25 +0000, Sarchiapone wrote:

    > Has anyone experieces in reading wav files ? After some efforts I was
    > able to read the header, but now I need to read the data. I really don't
    > understand if they are byte, short in or int. I only get negative
    > numbers, if I execute this code
    >
    > while(fread(&c,sizeof(short int),1,fp)>0) {
    > printf("%d\n",c);
    > }


    What is the definition of c ?

    If c is a signed short, why do you use %d as a format (%d expects an int).
    use %hd if c is a short.
    Also, I believe the sample frequency for .wav files is 44KHz,
    which means that a typical music frequency takes in the order of 100
    cycles for a full cycle. If the first sample is negative, I'd expect
    the next ~~ 50 cycles to be negative, too.

    BTW: post some complete code.
    BTW2: use hexdump or octdump to verify your program's logic.
    Just visually skip the file header.

    HTH,
    AvK
    Moi, Jan 30, 2010
    #7
  8. Sarchiapone

    Sarchiapone Guest

    Il Sat, 30 Jan 2010 19:50:48 +0100, Moi ha scritto:

    > On Sat, 30 Jan 2010 15:18:25 +0000, Sarchiapone wrote:
    >
    >> Has anyone experieces in reading wav files ? After some efforts I was
    >> able to read the header, but now I need to read the data. I really
    >> don't understand if they are byte, short in or int. I only get negative
    >> numbers, if I execute this code
    >>
    >> while(fread(&c,sizeof(short int),1,fp)>0) { printf("%d\n",c);
    >> }

    >
    > What is the definition of c ?


    short int c;
    >
    > If c is a signed short, why do you use %d as a format (%d expects an
    > int). use %hd if c is a short.
    > Also, I believe the sample frequency for .wav files is 44KHz, which
    > means that a typical music frequency takes in the order of 100
    > cycles for a full cycle. If the first sample is negative, I'd expect
    > the next ~~ 50 cycles to be negative, too.


    I counted negative and positive values, and they were all negatives.
    >
    > BTW: post some complete code.
    > BTW2: use hexdump or octdump to verify your program's logic. Just
    > visually skip the file header.



    This is the code

    #include "stdio.h"
    #include "stdlib.h"
    #include "string.h"
    typedef unsigned char uint8;
    typedef unsigned short uint16;
    typedef unsigned long uint32;
    typedef enum {false,true} boolean;
    typedef struct
    {
    unsigned char chunkID[4]; // Contiene le lettere "RIFF" in
    formato ASCII form (0x52494646 formato big-endian)
    unsigned int ChunkSize; // 36 + SubChunk2Size, o più
    precisamente:
    // 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
    // Questa è la dimensione del resto del chunk
    che segue questo numero.Questa è la dimensione dell'intero file
    // in bytes meno 8 bytes per i due campi non
    inclusi in queto conteggio
    // ChunkID e ChunkSize.
    unsigned char Format[4]; // Contiene le lettere
    "WAVE"(0x57415645 formato big-endian).
    unsigned char Subchunk1ID[4]; // Contiene le lettere "fmt
    " (0x666d7420 formato big-endian).
    unsigned int Subchunk1Size; // 16 for PCM. This is the size of the
    rest of the Subchunk which follows this number
    short int AudioFormat; // PCM = 1 (i.e. Linear quantization)
    // Values other than 1 indicate someform of
    compression.
    short int NumChannels; // Mono = 1, Stereo += 2, etc.
    int SampleRate; // 8000, 44100, etc.
    int ByteRate; // = SampleRate * NumChannels * BitsPerSample/8
    short int BlockAlign; // = NumChannels * BitsPerSample/8
    // The number of bytes for one sample including
    all channels
    short int BitsPerSample;// 8 bits += 8, 16 bits += 16, etc.
    short int Extra;
    unsigned char Data[4]; // Contains the letters "data" (0x64617461 big-
    endian form).
    unsigned int DataSize ; // = NumSamples * NumChannels *
    BitsPerSample/8 This is the number of bytes in the data.
    } __attribute__ (( packed )) RIFF_HEADER;
    boolean ispadded(RIFF_HEADER *header);
    int main(int argc, char *argv[])
    {
    RIFF_HEADER *header;
    FILE *fp;
    int i;
    int num_neg=0;
    int num_pos=0;
    short int c;
    char *filename;
    char *dati;
    if(argc>1)
    {
    printf("Lunghezza argv[1]: %d\n",strlen(argv[1]));
    filename=(char *)(malloc(strlen(argv[1])+1));
    strcpy(filename,argv[1]);
    printf("Filename:%s\n",filename);
    fp=fopen(filename,"rb");
    }
    header=(RIFF_HEADER *)malloc(sizeof(RIFF_HEADER));
    printf("Header Size=%d\n",sizeof(RIFF_HEADER));
    fread(header,sizeof(RIFF_HEADER),1,fp);
    printf("Is Padded %d\n",ispadded(header));
    printf("ChunkID:%4.4s\n",header->chunkID);
    printf("ChunkSize:%u\n",header->ChunkSize);
    printf("Format:%4.4s\n",header->Format);
    printf("Subchunk1ID:%4.4s\n", header->Subchunk1ID);
    printf("Subchunk1Size:%u\n",header->Subchunk1Size);
    printf("AudioFormat:%d\n",header->AudioFormat);
    printf("NumChannels:%d\n",header->NumChannels);
    printf("SampleRate:%d\n",header->SampleRate);
    printf("ByteRate:%d\n",header->ByteRate);
    printf("BlockAlign:%d\n",header->BlockAlign);
    printf("BitsPerSample:%d\n",header->BitsPerSample);
    printf("Extra:%d\n",header->Extra);
    printf("Data:%4.4s\n",header->Data);
    printf("DataSize:%u\n",(header->DataSize));
    dati=(char *) malloc(header->DataSize+1);
    if(dati==NULL) printf("Errore. memoria insufficiente!\n");
    i=0;
    //if (fread(dati,header->DataSize,1,fp)>0) printf("Lettura eseguita
    correttamente\n");
    //else
    //printf("Lettura non eseguita correttamente\n");
    //printf("strlen(dati)=%d\n",strlen(dati));
    //dati[strlen(dati)+1]='\0';
    //printf("strlen(dati)=%d\n",strlen(dati));
    //fread(&c,sizeof(int),1,fp);

    while(fread(&c,sizeof(short int),1,fp)>0)
    {
    if (c>0) num_pos++;
    else
    num_neg++;
    printf("%hd\n",c);
    }
    printf("\n Neg:%d Pos:%d\n",num_neg, num_pos);
    //while(*dati!='\0'){

    //for (i=0;i<header->DataSize;i++)
    //printf("\t i=%d dati=%d",i,dati);
    return 0;
    }
    boolean ispadded(RIFF_HEADER *header)
    {
    short int sizeofheaders=sizeof(RIFF_HEADER);
    short int size_of_fields=0;
    size_of_fields+=sizeof(header->chunkID);
    size_of_fields+=sizeof(header->ChunkSize);
    size_of_fields+=sizeof(header->Format);
    size_of_fields+=sizeof(header->Subchunk1ID);
    size_of_fields+=sizeof(header->Subchunk1Size);
    size_of_fields+=sizeof(header->AudioFormat);
    size_of_fields+=sizeof(header->NumChannels);
    size_of_fields+=sizeof(header->SampleRate);
    size_of_fields+=sizeof(header->ByteRate);
    size_of_fields+=sizeof(header->BlockAlign);
    size_of_fields+=sizeof(header->BitsPerSample);
    size_of_fields+=sizeof(header->Data);
    size_of_fields+=sizeof(header->DataSize);
    size_of_fields+=sizeof(header->Extra);
    printf("Header size=%d fields size=%d\n",sizeofheaders,size_of_fields);
    return (sizeofheaders==size_of_fields);
    }
    Sarchiapone, Jan 30, 2010
    #8
  9. On 30 Jan 2010 at 18:50, Moi wrote:
    > If c is a signed short, why do you use %d as a format (%d expects an int).
    > use %hd if c is a short.


    Why?

    If c is a signed short then it will be promoted to signed int before the
    function call anyway.

    I think the main use for the h length modifier is in scanf. I guess it
    could just conceivably be useful to use %hu in a printf when
    sizeof(short) < sizeof(int): you could supply an unsigned int as an
    argument, and have it reduced mod USHORT_MAX+1 without needing to write
    an explicit cast.
    Antoninus Twink, Jan 30, 2010
    #9
  10. Sarchiapone

    Sarchiapone Guest


    > It's weird, to me, that every number should print as negative, though.
    > It seems like /some/ of them should come out as positive even if you're
    > reading data of the wrong size or your alignment is off. Maybe it's
    > just extremely bad luck?
    >
    > -Beej


    Well, I tried to play the wav file I was trying to read, and it was a
    wrong file, so I tried with a different wav file, and the C program
    worked properly.
    Sarchiapone, Jan 30, 2010
    #10
  11. Sarchiapone

    Sjouke Burry Guest

    Sarchiapone wrote:
    > Il Sat, 30 Jan 2010 18:03:12 +0100, Sjouke Burry ha scritto:
    >
    >> Sarchiapone wrote:
    >>> Has anyone experieces in reading wav files ? After some efforts I was
    >>> able to read the header, but now I need to read the data. I really
    >>> don't understand if they are byte, short in or int. I only get negative
    >>> numbers, if I execute this code
    >>>
    >>> while(fread(&c,sizeof(short int),1,fp)>0) {
    >>> printf("%d\n",c);
    >>> }
    >>>

    >> I have a piece of dos 16 bit software, reading, testing and then
    >> sounding a wav file on an SB PRO compatible soundcard.
    >> If you want it, tell me where to mail it, source code and exe.

    >
    > Well, I need source code, for I am compiling under Linux OS. If you could
    > send me the code, it would be great. My email address is francesco dot
    > difusco at gmail dot com
    >
    > Francesco

    I hope you got 2 emails, if not, yell, and I do something else.
    Sjouke Burry, Jan 30, 2010
    #11
  12. Sarchiapone

    Sjouke Burry Guest

    Sjouke Burry wrote:
    > Sarchiapone wrote:
    >> Il Sat, 30 Jan 2010 18:03:12 +0100, Sjouke Burry ha scritto:
    >>
    >>> Sarchiapone wrote:
    >>>> Has anyone experieces in reading wav files ? After some efforts I was
    >>>> able to read the header, but now I need to read the data. I really
    >>>> don't understand if they are byte, short in or int. I only get negative
    >>>> numbers, if I execute this code
    >>>>
    >>>> while(fread(&c,sizeof(short int),1,fp)>0) {
    >>>> printf("%d\n",c);
    >>>> }
    >>>>
    >>> I have a piece of dos 16 bit software, reading, testing and then
    >>> sounding a wav file on an SB PRO compatible soundcard.
    >>> If you want it, tell me where to mail it, source code and exe.

    >> Well, I need source code, for I am compiling under Linux OS. If you could
    >> send me the code, it would be great. My email address is francesco dot
    >> difusco at gmail dot com
    >>
    >> Francesco

    > I hope you got 2 emails, if not, yell, and I do something else.


    Sorry, at least 1 mail bounced.

    You can download from
    > http://home.planet.nl/~burry004/wavsoft.zip
    Sjouke Burry, Jan 30, 2010
    #12
  13. Sarchiapone

    Sarchiapone Guest


    >> I hope you got 2 emails, if not, yell, and I do something else.

    >
    > Sorry, at least 1 mail bounced.
    >
    > You can download from
    >> http://home.planet.nl/~burry004/wavsoft.zip


    Thank you very much, I got it, now I am studying it
    Sarchiapone, Jan 30, 2010
    #13
  14. Sarchiapone

    Dan Mills Guest

    On Sat, 30 Jan 2010 18:28:19 +0000, Sarchiapone wrote:

    > Well, I need source code, for I am compiling under Linux OS. If you
    > could send me the code, it would be great. My email address is
    > francesco dot difusco at gmail dot com


    Sounds like you want libsndfile, which handles wav, aiff, caf, aiff...
    Very easy to use and you probably have the library itself already
    installed (and just need to download the header files).

    www.mega-nerd.com/libsndfile/

    Wav if tricky to parse (especially if you need to allow for all (or at
    least the common) the broken implementations!), and there is generally
    little margin in re inventing the wheel.

    Regards, Dan.
    Dan Mills, Jan 30, 2010
    #14
  15. Sarchiapone

    Sarchiapone Guest


    > Wav if tricky to parse (especially if you need to allow for all (or at
    > least the common) the broken implementations!), and there is generally
    > little margin in re inventing the wheel.
    >
    > Regards, Dan.


    I need to read data from a wav file as a source of random values. That's
    all. I don't need to change data, or playing waves. But I have found some
    problems, sometimes headers are not in canonical format. Sometimes they
    are not 44 bytes, I have found some headers measuring 50 bytes. And I am
    completely new to wav files format.

    Francesco
    Sarchiapone, Jan 31, 2010
    #15
  16. Sarchiapone

    Nick Guest

    Sarchiapone <> writes:

    >> Wav if tricky to parse (especially if you need to allow for all (or at
    >> least the common) the broken implementations!), and there is generally
    >> little margin in re inventing the wheel.
    >>
    >> Regards, Dan.

    >
    > I need to read data from a wav file as a source of random values. That's
    > all. I don't need to change data, or playing waves. But I have found some
    > problems, sometimes headers are not in canonical format. Sometimes they
    > are not 44 bytes, I have found some headers measuring 50 bytes. And I am
    > completely new to wav files format.


    Well why not start a reasonable distance in then? You will miss the
    header, and also avoid any initial silence, or gentle fade-ins, which
    could make your "random" values even less random.
    --
    Online waterways route planner | http://canalplan.eu
    Plan trips, see photos, check facilities | http://canalplan.org.uk
    Nick, Jan 31, 2010
    #16
  17. On 01/30/2010 10:50 AM, Moi wrote:
    > Also, I believe the sample frequency for .wav files is 44KHz,


    Actually, for the record, it can be anything between 1 and 2^32-1
    samples per second. (Yes, some of us can tell the difference between
    200 million and 201 million samples per second! No, I'm lying.)

    But it would be sane to be 22050 or 44100 Hz, so your cycle estimates
    are very likely to be true.

    However, we've been assuming that it's uncompressed PCM data... it might
    not be. The 'fmt ' chunk will have a 16-bit unsigned (little-endian)
    "compression type" as the first field--if this compression type isn't
    0x0001, then it's not necessarily uncompressed PCM and all bets are off.
    That seems like it would be more likely to lead to "all negative" data.
    And if the total headers length was coming up to 50 instead of 44, this
    suggests extra data in the 'fmt ' chunk, which suggests a different
    compression type.

    WAV compression types:

    http://tools.ietf.org/html/rfc2361#appendix-A

    -Beej
    Beej Jorgensen, Jan 31, 2010
    #17
  18. On 01/30/2010 10:58 AM, Sarchiapone wrote:
    > This is the code


    You should use pastebin.com or something like it if you're not going to
    keep the formatting sane:

    This assumes all kinds of stuff, like the RIFF chunk being followed by
    the fmt chunk, being followed by the data chunk... and that you're on a
    little-endian machine...

    > typedef struct
    > {
    > unsigned char chunkID[4]; // Contiene le lettere "RIFF" in
    > unsigned int ChunkSize; // 36 + SubChunk2Size, o più
    > unsigned char Format[4]; // Contiene le lettere
    > unsigned char Subchunk1ID[4]; // Contiene le lettere "fmt
    > unsigned int Subchunk1Size; // 16 for PCM. This is the size of the
    > short int AudioFormat; // PCM = 1 (i.e. Linear quantization)
    > short int NumChannels; // Mono = 1, Stereo += 2, etc.
    > int SampleRate; // 8000, 44100, etc.
    > int ByteRate; // = SampleRate * NumChannels * BitsPerSample/8
    > short int BlockAlign; // = NumChannels * BitsPerSample/8
    > short int BitsPerSample;// 8 bits += 8, 16 bits += 16, etc.
    > short int Extra;
    > unsigned char Data[4]; // Contains the letters "data" (0x64617461 big-
    > unsigned int DataSize ; // = NumSamples * NumChannels *
    > } __attribute__ (( packed )) RIFF_HEADER;


    One web reference said the Extra short wouldn't be there if there was no
    extra data... but the spec says it's always present (and 0 in the case
    of PCM). But mplayer complains about Extra being 0, though, so I don't
    know what the Right Way is.

    However, if it is more than 0, it means there will be that many more
    bytes between Extra and Data, and then badness would occur with
    DataSize.

    > printf("AudioFormat:%d\n",header->AudioFormat);


    Is this "1" for your always-negative data?

    > printf("Data:%4.4s\n",header->Data);


    And this should always print "Data:data". If it doesn't, something's
    hosed (probably Extra != 0).

    -Beej
    Beej Jorgensen, Jan 31, 2010
    #18
  19. Sarchiapone

    Sarchiapone Guest

    >>
    >> I need to read data from a wav file as a source of random values.
    >> That's all. I don't need to change data, or playing waves.

    >
    > Fine, so just read them a byte at a time, as unsigned char.
    >

    Thank you for your suggestions. I will try your code. But now I am very
    curious to read a wav file, it is really intriguing.
    Sarchiapone, Jan 31, 2010
    #19
  20. Sarchiapone

    Sarchiapone Guest


    >
    > Well why not start a reasonable distance in then? You will miss the
    > header, and also avoid any initial silence, or gentle fade-ins, which
    > could make your "random" values even less random.


    It is a very good idea, thank you
    Sarchiapone, Jan 31, 2010
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. aten
    Replies:
    1
    Views:
    648
    Roedy Green
    Oct 4, 2003
  2. C-man
    Replies:
    1
    Views:
    6,182
    Andrew Thompson
    Nov 3, 2003
  3. Replies:
    3
    Views:
    744
    Andrew Thompson
    Jan 23, 2004
  4. Replies:
    4
    Views:
    11,608
    Thomas Weidenfeller
    Apr 21, 2006
  5. '2+
    Replies:
    2
    Views:
    476
Loading...

Share This Page