C/Sound

Advertisement


Question
Hi. 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-------------------------------

Answer
I 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.

C

All Answers


Answers by Expert:


Ask Experts

Volunteer


Narendra

Expertise

I can answer questions in C related to programming, data structures, pointers and file manipulation. I use Solaris for doing C code and if you have questions related to C programming on Solaris, I will be able to help better.

Experience

6.5

Organizations belong to
Sun Microsystems

Awards and Honors
Brain Bench Certified Expert C programmer.
Advanced System Software Certified

©2012 About.com, a part of The New York Times Company. All rights reserved.