wav.c File Reference

#include <string.h>
#include "st.h"
#include "wav.h"
#include "sciprint.h"

Include dependency graph for wav.c:

Go to the source code of this file.

Data Structures

struct  wavstuff

Typedefs

typedef wavstuffwav_t

Functions

static char * wav_format_str (unsigned int wFormatTag)
void wavstartread (ft_t ft, WavInfo *Wi, int flag)
int wavread (ft_t ft, long int *buf, long int len)
void wavstopread (ft_t ft)
void wavstartwrite (ft_t ft)
void wavwritehdr (ft_t ft)
void wavwrite (ft_t ft, long int *buf, long int len)
void wavstopwrite (ft_t ft)


Typedef Documentation

typedef struct wavstuff * wav_t


Function Documentation

static char * wav_format_str ( unsigned int  wFormatTag  )  [static]

Definition at line 456 of file wav.c.

References IBM_FORMAT_ADPCM, IBM_FORMAT_ALAW, IBM_FORMAT_MULAW, WAVE_FORMAT_ADPCM, WAVE_FORMAT_ALAW, WAVE_FORMAT_DIGIFIX, WAVE_FORMAT_DIGISTD, WAVE_FORMAT_MULAW, WAVE_FORMAT_OKI_ADPCM, WAVE_FORMAT_PCM_SCI, and WAVE_FORMAT_UNKNOWN.

Referenced by wavwritehdr().

00457 {
00458   switch (wFormatTag)
00459     {
00460     case WAVE_FORMAT_UNKNOWN:
00461       return "Microsoft Official Unknown";
00462     case WAVE_FORMAT_PCM_SCI:
00463       return "Microsoft PCM";
00464     case WAVE_FORMAT_ADPCM:
00465       return "Microsoft ADPCM";
00466     case WAVE_FORMAT_ALAW:
00467       return "Microsoft A-law";
00468     case WAVE_FORMAT_MULAW:
00469       return "Microsoft U-law";
00470     case WAVE_FORMAT_OKI_ADPCM:
00471       return "OKI ADPCM format.";
00472     case WAVE_FORMAT_DIGISTD:
00473       return "Digistd format.";
00474     case WAVE_FORMAT_DIGIFIX:
00475       return "Digifix format.";
00476     case IBM_FORMAT_MULAW:
00477       return "IBM U-law format.";
00478     case IBM_FORMAT_ALAW:
00479       return "IBM A-law";
00480     case IBM_FORMAT_ADPCM:
00481       return "IBM ADPCM";
00482     default:
00483       return "Unknown";
00484     }
00485 }

Here is the caller graph for this function:

int wavread ( ft_t  ft,
long int buf,
long int  len 
)

Definition at line 280 of file wav.c.

References done, ft, soundstream::priv, rawread(), wavstuff::samples, and sciprint().

Referenced by loadwave().

00282 {
00283   wav_t wav = (wav_t) ft->priv;
00284   int   done;
00285 
00286   if (len > wav->samples) len = wav->samples;
00287   if (len == 0)
00288     return 0;
00289   done = rawread(ft, buf, len);
00290   if (done == 0)
00291     sciprint("Premature EOF on .wav input file\r\n");
00292   wav->samples -= done;
00293   return done;
00294 }

Here is the call graph for this function:

Here is the caller graph for this function:

void wavstartread ( ft_t  ft,
WavInfo Wi,
int  flag 
)

Definition at line 53 of file wav.c.

References soundstream::fp, ft, soundstream::ierr, len, soundstream::priv, rllong(), sciprint(), soundstream::seekable, and soundstream::swap.

Referenced by loadwave().

00054 {
00055   wav_t wav = (wav_t) ft->priv;
00056   char  magic[4];
00057   unsigned len;  
00058   int   littlendian = 1;
00059   char  *endptr;
00060   
00061   /* wave file characteristics */
00062   endptr = (char *) &littlendian;
00063   if (!*endptr) ft->swap = 1;
00065   /* If you need to seek around the input file. */
00066   if (0 && ! ft->seekable)
00067     {
00068       sciprint("Sorry, .wav input file must be a file, not a pipe\r\n");
00069       ft->ierr=1;return;
00070     }
00071   
00072   if (   fread(magic, 1, 4, ft->fp) != 4
00073       || strncmp("RIFF", magic, 4))
00074     {
00075       sciprint("Sorry, not a RIFF file\r\n");
00076       ft->ierr=1;return;
00077     }
00078   
00079   len = rllong(ft);
00080   
00081   if (   fread(magic, 1, 4, ft->fp) != 4
00082       || strncmp("WAVE", magic, 4))
00083     {
00084       sciprint("Sorry, not a WAVE file\r\n");
00085       ft->ierr=1;return;
00086     }
00087   
00088   /* Now look for the format chunk */
00089   for (;;)
00090     {
00091       if ( fread(magic, 1, 4, ft->fp) != 4 )
00092         {
00093           sciprint("Sorry, missing fmt spec\r\n");
00094           ft->ierr=1;return;
00095         }
00096       len = rllong(ft);
00097       if (strncmp("fmt ", magic, 4) == 0)
00098         break;                  /* Found the format chunk */
00099       while (len > 0 && !feof(ft->fp)) /* skip to next chunk */
00100         {
00101           getc(ft->fp);
00102           len--;
00103         }
00104     }
00105   
00106   if ( len < 16 )
00107     {
00108       sciprint("Sorry, fmt chunk is too short\r\n");
00109       ft->ierr=1;return;
00110     }
00111   
00112   Wi->wFormatTag = rlshort(ft);
00113   switch ( Wi->wFormatTag)
00114     {
00115     case WAVE_FORMAT_UNKNOWN:
00116       {
00117         sciprint("Sorry, this WAV file is in Microsoft Official Unknown format.\r\n");
00118         ft->ierr=1;return;
00119       }
00120     case WAVE_FORMAT_PCM_SCI:   /* this one, at least, I can handle */
00121       if (ft->info.style != -1 && ft->info.style != UNSIGNED && ft->info.style != SIGN2)
00122         sciprint("User options overiding style read in .wav header\r\n");
00123       break;
00124     case WAVE_FORMAT_ADPCM:
00125       {
00126         sciprint("Sorry, this WAV file is in Microsoft ADPCM format.\r\n");
00127         ft->ierr=1;return;
00128       }
00129 
00130     case WAVE_FORMAT_ALAW:      /* Think I can handle this */
00131       if (ft->info.style == -1 || ft->info.style == ALAW)
00132         ft->info.style = ALAW;
00133       else
00134         sciprint("User options overiding style read in .wav header\r\n");
00135       break;
00136     case WAVE_FORMAT_MULAW:     /* Think I can handle this */
00137       if (ft->info.style == -1 || ft->info.style == ULAW)
00138         ft->info.style = ULAW;
00139       else
00140         sciprint("User options overiding style read in .wav header\r\n");
00141       break;
00142     case WAVE_FORMAT_OKI_ADPCM:
00143       {
00144         sciprint("Sorry, this WAV file is in OKI ADPCM format.\r\n");
00145         ft->ierr=1;return;
00146       }
00147 
00148     case WAVE_FORMAT_DIGISTD:
00149       {
00150         sciprint("Sorry, this WAV file is in Digistd format.\r\n");
00151         ft->ierr=1;return;
00152       }
00153     case WAVE_FORMAT_DIGIFIX:
00154       {
00155         sciprint("Sorry, this WAV file is in Digifix format.\r\n");
00156         ft->ierr=1;return;
00157       }
00158     case IBM_FORMAT_MULAW:
00159       {
00160         sciprint("Sorry, this WAV file is in IBM U-law format.\r\n");
00161         ft->ierr=1;return;
00162       }
00163     case IBM_FORMAT_ALAW:
00164       {
00165         sciprint("Sorry, this WAV file is in IBM A-law format.\r\n");
00166         ft->ierr=1;return;
00167       }
00168     case IBM_FORMAT_ADPCM:
00169       {
00170         sciprint("Sorry, this WAV file is in IBM ADPCM format.\r\n");
00171         ft->ierr=1;return;
00172       }
00173     default:    
00174       {
00175         sciprint("Sorry, don't understand format\r\n");
00176         ft->ierr=1;return;
00177       }
00178     }
00179   Wi->wChannels = rlshort(ft);
00180   /* User options take precedence */
00181   if (ft->info.channels == -1 || ft->info.channels == Wi->wChannels)
00182     ft->info.channels = Wi->wChannels;
00183   else
00184     sciprint("User options overiding channels read in .wav header\r\n");
00185   Wi->wSamplesPerSecond = rllong(ft);
00186   if (ft->info.rate == (unsigned int)0 || ft->info.rate == Wi->wSamplesPerSecond)
00187     ft->info.rate = Wi->wSamplesPerSecond;
00188   else
00189     sciprint("User options overiding rate read in .wav header\r\n");
00190   Wi->wAvgBytesPerSec = rllong(ft);     /* Average bytes/second */
00191   Wi->wBlockAlign = rlshort(ft);        /* Block align */
00192   Wi->wBitsPerSample =  rlshort(ft); /* bits per sample per channel */
00193   Wi->bytespersample = (Wi->wBitsPerSample + 7)/8;
00194   switch (Wi->bytespersample)
00195     {
00196     case 1:
00197       /* User options take precedence */
00198       if (ft->info.size == -1 || ft->info.size == BYTESCI)
00199         ft->info.size = BYTESCI;
00200       else
00201         sciprint("User options overiding size read in .wav header\r\n");
00202       if (ft->info.style == -1 || ft->info.style == UNSIGNED)
00203         ft->info.style = UNSIGNED;
00204       else if (ft->info.style != ALAW && ft->info.style != ULAW) 
00205         sciprint("User options overiding style read in .wav header\r\n");
00206       break;
00207     case 2:
00208       if (ft->info.size == -1 || ft->info.size == WORDSCI)
00209         ft->info.size = WORDSCI;
00210       else
00211         sciprint("User options overiding size read in .wav header\r\n");
00212       if (ft->info.style == -1 || ft->info.style == SIGN2)
00213         ft->info.style = SIGN2;
00214       else
00215         sciprint("User options overiding style read in .wav header\r\n");
00216       break;
00217     case 4:
00218       if (ft->info.size == -1 || ft->info.size == LONGSCI)
00219         ft->info.size = LONGSCI;
00220       else
00221         sciprint("User options overiding size read in .wav header\r\n");
00222       if (ft->info.style == -1 || ft->info.style == SIGN2)
00223         ft->info.style = SIGN2;
00224       else
00225         sciprint("User options overiding style read in .wav header\r\n");
00226       break;
00227     default:
00228       {
00229         sciprint("Sorry, don't understand .wav size\r\n");
00230         ft->ierr=1;return;
00231       }
00232     }
00233   len -= 16;
00234   while (len > 0 && !feof(ft->fp))
00235     {
00236       getc(ft->fp);
00237       len--;
00238     }
00239   
00240   /* Now look for the wave data chunk */
00241   for (;;)
00242     {
00243       if ( fread(magic, 1, 4, ft->fp) != 4 )
00244         {
00245           sciprint("Sorry, missing data chunk\r\n");
00246           ft->ierr=1;return;
00247         }
00248       len = rllong(ft);
00249       if (strncmp("data", magic, 4) == 0)
00250         break;                  /* Found the data chunk */
00251       while (len > 0 && !feof(ft->fp)) /* skip to next chunk */
00252         {
00253           getc(ft->fp);
00254           len--;
00255         }
00256     }
00257   Wi->data_length = len;
00258   wav->samples = Wi->data_length/ft->info.size; /* total samples */
00259   
00260   if ( flag == 1 ) 
00261     {
00262       sciprint("Reading Wave file: %s format, %d channel%s, %d samp/sec\r\n",
00263                wav_format_str(Wi->wFormatTag), Wi->wChannels,
00264                Wi->wChannels == 1 ? "" : "s", Wi->wSamplesPerSecond);
00265       sciprint("        %d byte/sec, %d block align, %d bits/samp, %u data bytes\r\n",
00266                Wi->wAvgBytesPerSec, Wi->wBlockAlign,Wi->wBitsPerSample, Wi->data_length);
00267     }
00268   Wi->wav_format = wav_format_str(Wi->wFormatTag);
00269 }

Here is the call graph for this function:

Here is the caller graph for this function:

void wavstartwrite ( ft_t  ft  ) 

Definition at line 305 of file wav.c.

References ft, soundstream::priv, wavstuff::samples, sciprint(), wavstuff::second_header, soundstream::seekable, soundstream::swap, and wavwritehdr().

Referenced by savewave().

00306 {
00307   wav_t wav = (wav_t) ft->priv;
00308   int   littlendian = 1;
00309   char  *endptr;
00310   
00311   endptr = (char *) &littlendian;
00312   if (!*endptr) ft->swap = 1;
00313   
00314   wav->samples = 0;
00315   wav->second_header = 0;
00316   if (! ft->seekable)
00317     sciprint("Length in output .wav header will wrong since can't seek to fix it\r\n");
00318   wavwritehdr(ft);
00319 }

Here is the call graph for this function:

Here is the caller graph for this function:

void wavstopread ( ft_t  ft  ) 

Definition at line 301 of file wav.c.

00302 {
00303 }

void wavstopwrite ( ft_t  ft  ) 

Definition at line 436 of file wav.c.

References soundstream::fp, ft, soundstream::ierr, L, soundstream::priv, sciprint(), soundstream::seekable, and wavwritehdr().

Referenced by savewave().

00437 {
00438   /* All samples are already written out. */
00439   /* If file header needs fixing up, for example it needs the */
00440   /* the number of samples in a field, seek back and write them here. */
00441   if (!ft->seekable)
00442     return;
00443   if (fseek(ft->fp, 0L, 0) != 0)
00444     {
00445       sciprint("Sorry, can't rewind output file to rewrite .wav header.\r\n");
00446       ft->ierr=1;return;
00447     }
00448   ((wav_t) ft->priv)->second_header = 1;
00449   wavwritehdr(ft);
00450 }

Here is the call graph for this function:

Here is the caller graph for this function:

void wavwrite ( ft_t  ft,
long int buf,
long int  len 
)

Definition at line 429 of file wav.c.

References ft, soundstream::priv, rawwrite(), and wavstuff::samples.

Referenced by savewave().

00430 {
00431   wav_t wav = (wav_t) ft->priv;
00432   wav->samples += len;
00433   rawwrite(ft, buf, len);
00434 }

Here is the call graph for this function:

Here is the caller graph for this function:

void wavwritehdr ( ft_t  ft  ) 

Definition at line 321 of file wav.c.

References ALAW, BYTESCI, signalinfo::channels, soundstream::fp, ft, soundstream::info, LONGSCI, soundstream::priv, signalinfo::rate, wavstuff::samples, sciprint(), wavstuff::second_header, SIGN2, signalinfo::size, sizes, signalinfo::style, ULAW, UNSIGNED, wav_format_str(), WAVE_FORMAT_ALAW, WAVE_FORMAT_MULAW, WAVE_FORMAT_PCM_SCI, wllong(), wlshort(), and WORDSCI.

Referenced by wavstartwrite(), and wavstopwrite().

00322 {
00323   wav_t wav = (wav_t) ft->priv;
00324   /* wave file characteristics */
00325   unsigned short wFormatTag;    /* data format */
00326   unsigned short wChannels;     /* number of channels */
00327   unsigned long  wSamplesPerSecond; /* samples per second per channel */
00328   unsigned long  wAvgBytesPerSec; /* estimate of bytes per second needed */
00329   unsigned short wBlockAlign;   /* byte alignment of a basic sample block */
00330   unsigned short wBitsPerSample; /* bits per sample */
00331   unsigned long  data_length;   /* length of sound data in bytes */
00332   unsigned long  bytespersample; /* bytes per sample (per channel) */
00333   
00334   switch (ft->info.size)
00335     {
00336     case BYTESCI:
00337       wBitsPerSample = 8;
00338       if (ft->info.style == -1 || ft->info.style == UNSIGNED)
00339         ft->info.style = UNSIGNED;
00340       else if (!wav->second_header && ft->info.style != ALAW && ft->info.style != ULAW) 
00341         sciprint("User options overiding style written to .wav header\r\n");
00342       break;
00343     case WORDSCI:
00344       wBitsPerSample = 16;
00345       if (ft->info.style == -1 || ft->info.style == SIGN2)
00346         ft->info.style = SIGN2;
00347       else if (!wav->second_header)
00348         sciprint("User options overiding style written to .wav header\r\n");
00349       break;
00350     case LONGSCI:
00351       wBitsPerSample = 32;
00352       if (ft->info.style == -1 || ft->info.style == SIGN2)
00353         ft->info.style = SIGN2; 
00354       else if (!wav->second_header)
00355         sciprint("User options overiding style written to .wav header\r\n");
00356       break;
00357     default:
00358       wBitsPerSample = 32;
00359       if (ft->info.style == -1)
00360         ft->info.style = SIGN2; 
00361       if (!wav->second_header)
00362         sciprint("Sciprinting - writing bad .wav file using %s\r\n",sizes[ft->info.size]);
00363       break;
00364     }
00365   
00366   switch (ft->info.style)
00367     {
00368     case UNSIGNED:
00369       wFormatTag = WAVE_FORMAT_PCM_SCI;
00370       if (wBitsPerSample != 8 && !wav->second_header)
00371         sciprint("Sciprinting - writing bad .wav file using unsigned data and %d bits/sample\r\n",wBitsPerSample);
00372       break;
00373     case SIGN2:
00374       wFormatTag = WAVE_FORMAT_PCM_SCI;
00375       if (wBitsPerSample == 8 && !wav->second_header)
00376         sciprint("Sciprinting - writing bad .wav file using signed data and %d bits/sample\r\n",wBitsPerSample);
00377       break;
00378     case ALAW:
00379       wFormatTag = WAVE_FORMAT_ALAW;
00380       if (wBitsPerSample != 8 && !wav->second_header)
00381         sciprint("Sciprinting - writing bad .wav file using A-law data and %d bits/sample\r\n",wBitsPerSample);
00382       break;
00383     case ULAW:
00384       wFormatTag = WAVE_FORMAT_MULAW;
00385       if (wBitsPerSample != 8 && !wav->second_header)
00386         sciprint("Sciprinting - writing bad .wav file using U-law data and %d bits/sample\r\n",wBitsPerSample);
00387       break;
00388     }
00389   
00390   
00391   wSamplesPerSecond = ft->info.rate;
00392   bytespersample = (wBitsPerSample + 7)/8;
00393   wAvgBytesPerSec = ft->info.rate * ft->info.channels * bytespersample;
00394   wChannels = ft->info.channels;
00395   wBlockAlign = (unsigned short) (ft->info.channels * bytespersample);
00396   if (!wav->second_header)      /* use max length value first time */
00397     data_length = 0x7fffffff - (8+16+12);
00398   else                          /* fixup with real length */
00399     data_length = bytespersample * wav->samples;
00400   
00401   /* figured out header info, so write it */
00402   fputs("RIFF", ft->fp);
00403   wllong(ft, data_length + 8+16+12); /* Waveform chunk size: FIXUP(4) */
00404   fputs("WAVE", ft->fp);
00405   fputs("fmt ", ft->fp);
00406   wllong(ft, (long)16);         /* fmt chunk size */
00407   wlshort(ft, wFormatTag);
00408   wlshort(ft, wChannels);
00409   wllong(ft, wSamplesPerSecond);
00410   wllong(ft, wAvgBytesPerSec);
00411   wlshort(ft, wBlockAlign);
00412   wlshort(ft, wBitsPerSample);
00413   
00414   fputs("data", ft->fp);
00415   wllong(ft, data_length);      /* data chunk size: FIXUP(40) */
00416   
00417   if (!wav->second_header) 
00418     {
00419       sciprint("Writing Wave file: %s format, %d channel%s, %d samp/sec\r\n",
00420                wav_format_str(wFormatTag), wChannels,
00421                wChannels == 1 ? "" : "s", wSamplesPerSecond);
00422       sciprint("        %d byte/sec, %d block align, %d bits/samp\r\n",
00423                wAvgBytesPerSec, wBlockAlign, wBitsPerSample);
00424     } 
00425   else
00426     sciprint("Finished writing Wave file, %u data bytes\r\n",data_length);
00427 }

Here is the call graph for this function:

Here is the caller graph for this function:


Generated on Sun Mar 4 16:12:43 2007 for Scilab [trunk] by  doxygen 1.5.1