00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <string.h>
00032 #include "st.h"
00033 #include "wav.h"
00034 #include "sciprint.h"
00035
00036
00037 typedef struct wavstuff
00038 {
00039 long samples;
00040 int second_header;
00041 } *wav_t;
00042
00043 static char *wav_format_str(unsigned int wFormatTag);
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 void wavstartread(ft_t ft, WavInfo *Wi, int flag)
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
00062 endptr = (char *) &littlendian;
00063 if (!*endptr) ft->swap = 1;
00065
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
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;
00099 while (len > 0 && !feof(ft->fp))
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:
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:
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:
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
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);
00191 Wi->wBlockAlign = rlshort(ft);
00192 Wi->wBitsPerSample = rlshort(ft);
00193 Wi->bytespersample = (Wi->wBitsPerSample + 7)/8;
00194 switch (Wi->bytespersample)
00195 {
00196 case 1:
00197
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
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;
00251 while (len > 0 && !feof(ft->fp))
00252 {
00253 getc(ft->fp);
00254 len--;
00255 }
00256 }
00257 Wi->data_length = len;
00258 wav->samples = Wi->data_length/ft->info.size;
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 }
00270
00271
00272
00273
00274
00275
00276
00277 #if defined(__alpha)|defined(__ia64__)
00278 int wavread(ft_t ft,int *buf, long int len)
00279 #else
00280 int wavread(ft_t ft, long int *buf, long int len)
00281 #endif
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 }
00295
00296
00297
00298
00299
00300
00301 void wavstopread(ft_t ft)
00302 {
00303 }
00304
00305 void wavstartwrite(ft_t ft)
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 }
00320
00321 void wavwritehdr(ft_t ft)
00322 {
00323 wav_t wav = (wav_t) ft->priv;
00324
00325 unsigned short wFormatTag;
00326 unsigned short wChannels;
00327 unsigned long wSamplesPerSecond;
00328 unsigned long wAvgBytesPerSec;
00329 unsigned short wBlockAlign;
00330 unsigned short wBitsPerSample;
00331 unsigned long data_length;
00332 unsigned long bytespersample;
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)
00397 data_length = 0x7fffffff - (8+16+12);
00398 else
00399 data_length = bytespersample * wav->samples;
00400
00401
00402 fputs("RIFF", ft->fp);
00403 wllong(ft, data_length + 8+16+12);
00404 fputs("WAVE", ft->fp);
00405 fputs("fmt ", ft->fp);
00406 wllong(ft, (long)16);
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);
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 }
00428
00429 void wavwrite(ft_t ft, long int *buf, long int len)
00430 {
00431 wav_t wav = (wav_t) ft->priv;
00432 wav->samples += len;
00433 rawwrite(ft, buf, len);
00434 }
00435
00436 void wavstopwrite(ft_t ft)
00437 {
00438
00439
00440
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 }
00451
00452
00453
00454
00455 static char *
00456 wav_format_str(unsigned int wFormatTag)
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 }
00486
00487