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)
    Sarchiapone, Jan 30, 2010
    1. Advertisements

  2. Antoninus Twink, Jan 30, 2010
    1. Advertisements

  3. Sarchiapone

    Sjouke Burry Guest

    I have a piece of dos 16 bit software, reading, testing
    and then sounding a wav file on an SB PRO compatible
    If you want it, tell me where to mail it, source code and exe.
    Sjouke Burry, Jan 30, 2010
  4. Here's another web page about it:

    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.
    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 Jorgensen, Jan 30, 2010
  5. Sarchiapone

    Sarchiapone Guest

    Il Sat, 30 Jan 2010 18:03:12 +0100, Sjouke Burry ha scritto:
    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

    Sarchiapone, Jan 30, 2010
  6. Sarchiapone

    Sarchiapone Guest

    Il Sat, 30 Jan 2010 10:07:51 -0800, Beej Jorgensen ha scritto:
    Maybe it is extremely bad luck ;-)
    Sarchiapone, Jan 30, 2010
  7. Sarchiapone

    Moi Guest

    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.

    Moi, Jan 30, 2010
  8. Sarchiapone

    Sarchiapone Guest

    Il Sat, 30 Jan 2010 19:50:48 +0100, Moi ha scritto:
    short int c;
    I counted negative and positive values, and they were all negatives.

    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ù
    // 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
    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;
    printf("Lunghezza argv[1]: %d\n",strlen(argv[1]));
    filename=(char *)(malloc(strlen(argv[1])+1));
    header=(RIFF_HEADER *)malloc(sizeof(RIFF_HEADER));
    printf("Header Size=%d\n",sizeof(RIFF_HEADER));
    printf("Is Padded %d\n",ispadded(header));
    printf("Subchunk1ID:%4.4s\n", header->Subchunk1ID);
    dati=(char *) malloc(header->DataSize+1);
    if(dati==NULL) printf("Errore. memoria insufficiente!\n");
    //if (fread(dati,header->DataSize,1,fp)>0) printf("Lettura eseguita
    //printf("Lettura non eseguita correttamente\n");

    while(fread(&c,sizeof(short int),1,fp)>0)
    if (c>0) num_pos++;
    printf("\n Neg:%d Pos:%d\n",num_neg, num_pos);

    //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;
    printf("Header size=%d fields size=%d\n",sizeofheaders,size_of_fields);
    return (sizeofheaders==size_of_fields);
    Sarchiapone, Jan 30, 2010
  9. 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
  10. Sarchiapone

    Sarchiapone Guest

    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
  11. Sarchiapone

    Sjouke Burry Guest

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

    Sjouke Burry Guest

    Sorry, at least 1 mail bounced.

    You can download from
    Sjouke Burry, Jan 30, 2010
  13. Sarchiapone

    Sarchiapone Guest

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

    Dan Mills Guest

    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).

    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
  15. 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. 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.

    Sarchiapone, Jan 31, 2010
  16. Sarchiapone

    Nick 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.
    Nick, Jan 31, 2010
  17. 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:

    Beej Jorgensen, Jan 31, 2010
  18. You should use 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...
    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
    Is this "1" for your always-negative data?
    And this should always print "Data:data". If it doesn't, something's
    hosed (probably Extra != 0).

    Beej Jorgensen, Jan 31, 2010
  19. Sarchiapone

    Sarchiapone Guest

    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
  20. Sarchiapone

    Sarchiapone Guest

    It is a very good idea, thank you
    Sarchiapone, Jan 31, 2010
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.