Reading audio WAVE file data & header

Hi everybody,

I try to read a WAVE file in order to apply later a DFT but I got some problems. I legaly got a WAVE file here : http://soundcloud.com/alec_empire/atari-teenage-riot-black and I want to read it using a fstream.

I read this page http://edn.embarcadero.com/article/21300 in order to understand how a WAVE format is built. But when I try to extract the informations from the WAVE header I got weird stuff. Here is my code :

fstream ifs ("/home/polochon/Téléchargements/ATR_-_Black_Flags_Muffler_Remix.wav", ios_base::in);
if(ifs.is_open())
{
char * First_Chunk_ID = new char;
ifs.read(First_Chunk_ID,4);

char * charArray_File_Size = new char;
ifs.read(charArray_File_Size, sizeof(long));
long File_Size = atol(charArray_File_Size);

char* Form_Type_ID = new char;
ifs.read(Form_Type_ID,4);

char* Second_Chunk_ID = new char;
ifs.read(Second_Chunk_ID,4);

char * charArray_Wave_Format_Size = new char;
ifs.read(charArray_Wave_Format_Size, sizeof(long));
long Wave_Format_Size = atol(charArray_Wave_Format_Size);

char * Wave_Format_Info = new char;
ifs.read(Wave_Format_Info, Wave_Format_Size);

char * Third_Chunk_ID = new char;
ifs.read(Third_Chunk_ID, 4);

char * charArray_Data_Size = new char;
ifs.read(charArray_Data_Size, sizeof(long));
long Data_Size = atol(charArray_Data_Size);

char * Data = new char;
ifs.get(Data, 10000);

cout << "First_Chunk_ID : " << First_Chunk_ID << endl
<< "charArray_File_Size : " << charArray_File_Size << endl
<< "File_Size : " << File_Size << endl
<< "Form_Type_ID : " << Form_Type_ID << endl
<< "Second_Chunk_ID : " << Second_Chunk_ID << endl
<< "charArray_Wave_Format_Size : " << CharArray_Wave_Format_Size << endl
<< "Wave_Format_Size : " << Wave_Format_Size << endl
<< "Wave_Format_Info : " << Wave_Format_Info << endl
<< "Third_Chunk_ID : " << Third_Chunk_ID << endl
<< "charArray_Data_Size : " << charArray_Data_Size << endl
<< "Data_Size : " << Data_Size << endl
<< "Data : " << Data << endl
<< "Data gcount : " << ifs.gcount() << endl << endl;
}

And here is what I got :

First_Chunk_ID : RIFF
charArray_File_Size : ���
File_Size : 0
Form_Type_ID : WAVE
Second_Chunk_ID : fmt
charArray_Wave_Format_Size : 
Wave_Format_Size : 0
Wave_Format_Info :
Third_Chunk_ID : 
charArray_Data_Size : D�
Data_Size : 0
Data : �
Data gcount : 9999

As you can see, my fstream is not empty (according to the last gcount) but I don't know where I did it wrong when reading the header. Any Idea?

Thanks.
For starters, you are horribly corrupting the heap:

1
2
char * First_Chunk_ID = new char;  // allocates 1 char
ifs.read(First_Chunk_ID,4);  // reads 4 chars -- but you only have room for 1 


You are doing this for every read. You are overflowing your allocated space and corrupting memory. You need to make a buffer large enough to hold the data you are reading.



Secondly, these are binary files. Integral data is not stored as strings. The only thing stored as strings are the chunk headers (ie, "RIFF", "_fmt", etc) and any actual text (like comments). But even those are not null terminated like normal C strings.

1
2
3
char * charArray_File_Size = new char;  // again, only allocating 1 char
ifs.read(charArray_File_Size, sizeof(long));  // again reading 4 chars, overflowing allocated space
long File_Size = atol(charArray_File_Size);  // trying to convert from string to long, but the data is not a string 




Lastly, you have all these new's but not deletes, so you are leaking memory. Remember that every new must have a coresponding delete. C++ does not automatically free new'd buffers. It'd be better if you just didn't use new at all unless needed.



This is how you do it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//char * First_Chunk_ID = new char;
//ifs.read(First_Chunk_ID,4);

char First_Chunk_ID[5] = "";  // an array of 5 chars.  4 for the ID and 1 extra to put a null terminator at the end
ifs.read(First_Chunk_ID,4);



//char * charArray_File_Size = new char;
//ifs.read(charArray_File_Size, sizeof(long));
//long File_Size = atol(charArray_File_Size);

long File_Size;  // no need for this to be a char array.  The data is stored in binary
ifs.read( reinterpret_cast<char*>(&File_Size), sizeof(long) );



//...

//char * Data = new char;
//ifs.get(Data, 10000);

char Data[10000];  // if you want to read 10000 chars, make a buffer of 10000 chars
ifs.read(Data,10000);  // use read(), not get().  Everything in the file is binary 
Thank you!
Topic archived. No new replies allowed.