reading wav files

S

Sarchiapone

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);
}
 
S

Sjouke Burry

Sarchiapone said:
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.
 
B

Beej Jorgensen

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
 
S

Sarchiapone

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

Sarchiapone

Il Sat, 30 Jan 2010 10:07:51 -0800, Beej Jorgensen ha scritto:
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.


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 ;-)
 
M

Moi

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
 
S

Sarchiapone

Il Sat, 30 Jan 2010 19:50:48 +0100, Moi ha scritto:
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);
}
 
A

Antoninus Twink

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

Sarchiapone

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

Sjouke Burry

Sarchiapone said:
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

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

Dan Mills

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

Sarchiapone

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
 
N

Nick

Sarchiapone said:
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.
 
B

Beej Jorgensen

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
 
B

Beej Jorgensen

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
 
S

Sarchiapone

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

Sarchiapone

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
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top