C/Sound
Expert: Narendra - 7/17/2005
QuestionHi. I'm not sure if you'll be able to help with this, but I've searched all over the net for an answer and couldn't find one. I have written a program that will output a mixture of two sine wave frequencies to a .WAV file (after looking up the structure of such a file).
When I compile and run it under Windows XP using GCC I get a file that sounds scratchy and Windows Media Player says that the format is invalid. However, when I copy the file to Fedora Core Linux, it sounds fine.
When I do the opposite and compile and run the program in Linux, I get the same results--the file works in Linux and sounds crappy and then halfway through says that the file is invalid--under Windows XP. So, I think there is an issue with the .WAV file format in Linux and Windows XP. I hope you can help with this. Any references would also be helpful. I have attached the code below. Thanks.
Corey
---Begin Code--------------------
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#define SECONDS 10 /* produce 10 seconds of noise */
#define PI 3.14159265358979
int put_little_short(char *t, unsigned int value)
{
*(unsigned char *)(t++)=value&255;
*(unsigned char *)(t)=(value/256)&255;
return 2;
}
int put_little_long(char *t, unsigned int value)
{
*(unsigned char *)(t++)=value&255;
*(unsigned char *)(t++)=(value/256)&255;
*(unsigned char *)(t++)=(value/(256*256))&255;
*(unsigned char *)(t)=(value/(256*256*256))&255;
return 4;
}
/* returns the number of bytes written. skips two bytes after
* each write */
int fill_data(char *start, int frequency, int seconds)
{
int i, len=0;
int value;
for(i=0; i<seconds*44100; i++) {
value=32767.0 * sin(2.0*PI*((double)(i))*(double)(frequency)/44100.0);
put_little_short(start, value);
start += 4;
len+=2;
}
return len;
}
int main(void)
{
char *buffer=malloc(SECONDS*44100*4+1000);
char *t=buffer;
int len;
int fd;
*t++='R'; *t++='I'; *t++='F'; *t++='F';
t+=4; /* total length will be put in later */
*t++='W'; *t++='A'; *t++='V'; *t++='E';
/* format chunk, 8 bytes header and 16 bytes payload */
*t++='f'; *t++='m'; *t++='t'; *t++=' ';
t+=put_little_long(t,16); /* I know the length of the fmt_ chunk
*/
t+=put_little_short(t,1); /* chunk type is always one */
t+=put_little_short(t,2); /* two channels */
t+=put_little_long(t,44100); /* samples per second */
t+=put_little_long(t,44100*2*2); /* bytes per second */
t+=put_little_short(t,4); /* bytes pro sample (all channels) */
t+=put_little_short(t,16); /* bits per sample */
/* data chunk, 8 bytes header and XXX bytes payload */
*t++='d'; *t++='a'; *t++='t'; *t++='a';
len=fill_data(t+4,450,SECONDS); /* left channel, 450Hz sine */
len+=fill_data(t+6,452,SECONDS); /* right channel, 452Hz sine */
put_little_long(t,len);
put_little_long(buffer+4,len+8+16+8);
fd=open("test23.wav", O_RDWR|O_CREAT, 0644);
write(fd,buffer,len+8+16+8+8);
close(fd);
return 0;
}
---End Code-------------------------------
AnswerI have never worked on this file format.
So, I will not be able to provide any help.
But, here is a link which contains the details of all the file formats and also some example C code.
So, you can search that for .wav format structure.
URL:
http://www.wotsit.org
Hope this helps.