#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 wavstuff * | wav_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) |
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:
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:
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 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:
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: