"Fossies" - the Fresh Open Source Software Archive

Member "speech_tools/speech_class/EST_wave_io.cc" (4 Sep 2017, 46595 Bytes) of package /linux/misc/speech_tools-2.5.0-release.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "EST_wave_io.cc" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.4-release_vs_2.5.0-release.

    1 /*************************************************************************/
    2 /*                                                                       */
    3 /*                Centre for Speech Technology Research                  */
    4 /*                     University of Edinburgh, UK                       */
    5 /*                         Copyright (c) 1996                            */
    6 /*                        All Rights Reserved.                           */
    7 /*                                                                       */
    8 /*  Permission is hereby granted, free of charge, to use and distribute  */
    9 /*  this software and its documentation without restriction, including   */
   10 /*  without limitation the rights to use, copy, modify, merge, publish,  */
   11 /*  distribute, sublicense, and/or sell copies of this work, and to      */
   12 /*  permit persons to whom this work is furnished to do so, subject to   */
   13 /*  the following conditions:                                            */
   14 /*   1. The code must retain the above copyright notice, this list of    */
   15 /*      conditions and the following disclaimer.                         */
   16 /*   2. Any modifications must be clearly marked as such.                */
   17 /*   3. Original authors' names are not deleted.                         */
   18 /*   4. The authors' names are not used to endorse or promote products   */
   19 /*      derived from this software without specific prior written        */
   20 /*      permission.                                                      */
   21 /*                                                                       */
   22 /*  THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK        */
   23 /*  DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING      */
   24 /*  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT   */
   25 /*  SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE     */
   26 /*  FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    */
   27 /*  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN   */
   28 /*  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,          */
   29 /*  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF       */
   30 /*  THIS SOFTWARE.                                                       */
   31 /*                                                                       */
   32 /*************************************************************************/
   33 /*                  Author :  Alan Black and Paul Taylor                 */
   34 /*                  Date   :  June 1996                                  */
   35 /*-----------------------------------------------------------------------*/
   36 /*   File I/O functions specific to various file formats                 */
   37 /*                                                                       */
   38 /*   Note that internally data will always be shorts and                 */
   39 /*   native byte order, conversions to/from other byte formats           */
   40 /*   or encodings happend at read/write time                             */
   41 /*                                                                       */
   42 /*=======================================================================*/
   43 #include <cstdlib> 
   44 #include <cstdio>
   45 #include "EST_unix.h"
   46 #include <cstring>
   47 #include "EST_wave_aux.h"
   48 #include "EST_wave_utils.h"
   49 #include "EST_strcasecmp.h"
   50 #include "waveP.h"
   51 #include "EST_FileType.h"
   52 
   53 static int def_load_sample_rate = 16000;
   54 
   55 /*************************************************************************/
   56 /*                                                                       */
   57 /* Functions specific for each file format                               */
   58 /*                                                                       */
   59 /*************************************************************************/
   60 
   61 /*=======================================================================*/
   62 /* Sphere Nist files                                                     */
   63 /*=======================================================================*/
   64 
   65 static const char *NIST_SIG = "NIST_1A\n   1024\n";
   66 static const char *NIST_END_SIG = "end_head\n";
   67 #define NIST_HDR_SIZE 1024
   68 
   69 int nist_get_param_int(const char *hdr, const char *field, int def_val)
   70 {
   71     const char *p;
   72     int val;
   73 
   74     if (((p=strstr(hdr,field)) != NULL) &&
   75     (strncmp(" -i ",p+strlen(field),4) == 0))
   76     {
   77     sscanf(p+strlen(field)+4,"%d",&val);
   78     return val;
   79     }
   80     else
   81     return def_val;
   82 
   83 }
   84 
   85 char *nist_get_param_str(const char *hdr, const char *field, const char *def_val)
   86 {
   87     const char *p;
   88     char *val;
   89     int size;
   90 
   91     if (((p=strstr(hdr,field)) != NULL) &&
   92     (strncmp(" -s",p+strlen(field),3) == 0))
   93     {
   94     sscanf(p+strlen(field)+3,"%d",&size);
   95     val = walloc(char,size+1);
   96     /* Hmm don't know how long the %d is so do it again */
   97     sscanf(p+strlen(field)+3,"%d %s",&size,val);
   98     return val;
   99     }
  100     else
  101     return wstrdup(def_val);
  102 
  103 
  104 }
  105 
  106 const char *sample_type_to_nist(enum EST_sample_type_t sample_type)
  107 {
  108     const char *c;
  109     switch (sample_type) {
  110     case st_unknown:  
  111     c = ""; break;
  112     case st_schar:  
  113     c = "PCM-1"; break;
  114     case st_mulaw:
  115     c = "ULAW"; break;
  116     case st_short: 
  117     c = "pcm"; break;
  118     case st_int:   
  119     c = "PCM-4"; break;
  120     case st_float:
  121     c = "REAL"; break;
  122       case st_double:
  123     c = "REAL"; break;
  124     default:
  125     fprintf(stderr,"Unknown sample type for nist");
  126     c = "";
  127     }
  128     return c;
  129 }
  130 
  131 enum EST_sample_type_t nist_to_sample_type(char *type)
  132 {
  133     if ((streq(type,"pcm")) ||
  134     (streq(type,"PCM")) ||
  135     (streq(type,"pcm-2")))
  136     return st_short;
  137     if (strcmp(type,"pcm,embedded-shorten-v1.1") == 0)
  138     return st_shorten;
  139     else if ((EST_strcasecmp(type,"ULAW",NULL) == 0) ||
  140          (EST_strcasecmp(type,"U-LAW",NULL) == 0) ||
  141          (EST_strcasecmp(type,"mu-law",NULL) == 0) ||
  142          (EST_strcasecmp(type,"mulaw",NULL) == 0))
  143     return st_mulaw;
  144     else if (strcmp(type,"alaw") == 0)
  145     return st_alaw;
  146     else if (strcmp(type,"PCM-1") == 0)
  147     return st_schar;
  148     else if (strcmp(type,"PCM-4") == 0)
  149     return st_int;
  150     else if (strcmp(type,"REAL") == 0)
  151     return st_float;
  152     else
  153 
  154     {
  155     fprintf(stderr,"NIST: unknown sample type: %s\n",type);
  156     return st_unknown;
  157     }
  158 }
  159 
  160 enum EST_read_status load_wave_nist(EST_TokenStream &ts, short **data, int
  161                *num_samples, int *num_channels, int
  162                *word_size, int *sample_rate, enum
  163                EST_sample_type_t *sample_type, int *bo , int
  164                offset, int length)
  165 
  166 {
  167     char header[NIST_HDR_SIZE];
  168     int samps,sample_width,data_length,actual_bo;
  169     unsigned char *file_data;
  170     enum EST_sample_type_t actual_sample_type;
  171     char *byte_order, *sample_coding;
  172     int n;
  173     int current_pos;
  174 
  175     current_pos = ts.tell();
  176     if (ts.fread(header,NIST_HDR_SIZE,1) != 1)
  177     return wrong_format;
  178 
  179     if (strncmp(header,NIST_SIG,strlen(NIST_SIG)) != 0)
  180     return wrong_format;
  181 
  182     samps = nist_get_param_int(header,"sample_count",-1);
  183     *num_channels = nist_get_param_int(header,"channel_count",1);
  184     sample_width = nist_get_param_int(header,"sample_n_bytes",2);
  185     *sample_rate = 
  186     nist_get_param_int(header,"sample_rate",def_load_sample_rate);
  187     byte_order = nist_get_param_str(header,"sample_byte_format",
  188                     (EST_BIG_ENDIAN ? "10" : "01"));
  189     sample_coding = nist_get_param_str(header,"sample_coding","pcm");
  190     if (streq(byte_order,"mu-law"))
  191     {
  192     byte_order = wstrdup((EST_BIG_ENDIAN ? "10" : "01"));
  193     sample_coding = wstrdup("ULAW");
  194     }
  195 
  196     /* code for reading in Tony Robinson's shorten files.
  197        This is a temporary fix which calls the unshorten program on the
  198        speech file and reads in the answer by calling this function.
  199        It would be nice to have a simple library routine which did the
  200        unshortening. 
  201        removed Jun 14th 2016 by awb , security risk, and only works in CSTR 
  202        */
  203     
  204     if (streq(sample_coding,"pcm,embedded-shorten-v1.1"))
  205     {
  206 #if 0
  207     char *tmpfile, *cmdstr;
  208     enum EST_read_status rval;
  209 #endif
  210 
  211     fprintf(stderr,"WAVE read: nist type is shorten\n");
  212     fprintf(stderr,"WAVE read: no support for shorten -- you need to use some external program to unshorten the data\n");
  213     return misc_read_error;
  214 
  215 #if 0
  216     tmpfile = cmake_tmp_filename();
  217     cmdstr = walloc(char,strlen(tmpfile)+200);
  218         /* This doesn't work, unless you have cstrshorten, and */
  219         /* doesn't work if your file name is interesting */
  220     sprintf(cmdstr,"cstrshorten %s %s",
  221         (const char*)ts.filename(),tmpfile);
  222     printf("Command: %s\n", cmdstr);
  223     system(cmdstr);
  224     EST_TokenStream tt;
  225     tt.open(tmpfile);
  226     
  227     rval = load_wave_nist(tt, data, num_samples,
  228                   num_channels, word_size, sample_rate,
  229                   sample_type, bo, offset, length);
  230     unlink(tmpfile);
  231     wfree(tmpfile);
  232     wfree(cmdstr);
  233     tt.close();
  234     return rval;
  235 #endif
  236     }
  237 
  238     if (length == 0)
  239     data_length = (samps - offset)*(*num_channels);
  240     else
  241     data_length = length*(*num_channels);
  242 
  243     file_data = walloc(unsigned char,sample_width * data_length);
  244 
  245     ts.seek(current_pos+NIST_HDR_SIZE+(sample_width*offset*(*num_channels)));
  246 
  247     n = ts.fread(file_data,sample_width,data_length);
  248 
  249     if ((n < 1) && (n != data_length))
  250     {
  251     wfree(file_data); 
  252     wfree(sample_coding);
  253     wfree(byte_order);
  254     return misc_read_error;
  255     }
  256     else if ((n < data_length) && (data_length/(*num_channels) == n))
  257     {
  258     fprintf(stderr,"WAVE read: nist header is (probably) non-standard\n");
  259     fprintf(stderr,"WAVE read: assuming different num_channel interpretation\n");
  260     data_length = n;   /* wrongly headered file */
  261     }
  262     else if (n < data_length)
  263     {
  264     fprintf(stderr,"WAVE read: short file %s\n",
  265         (const char *)ts.filename());
  266     fprintf(stderr,"WAVE read: at %d got %d instead of %d samples\n",
  267         offset,n,data_length);
  268     data_length = n;
  269     }
  270 
  271     actual_sample_type = nist_to_sample_type(sample_coding);
  272     actual_bo = ((strcmp(byte_order,"10") == 0) ? bo_big : bo_little);
  273 
  274     *data = convert_raw_data(file_data,data_length,
  275                  actual_sample_type,actual_bo);
  276 
  277     *num_samples = data_length/ (*num_channels);
  278     *sample_type = st_short;
  279     *bo = EST_NATIVE_BO;
  280     *word_size = 2;
  281     wfree(sample_coding);
  282     wfree(byte_order);
  283 
  284     return format_ok;
  285 }
  286 
  287 enum EST_write_status save_wave_nist(FILE *fp, const short *data, int offset,
  288                      int num_samples, int num_channels, 
  289                      int sample_rate,
  290                      enum EST_sample_type_t sample_type, int bo)   
  291 {
  292     char h[1024], p[1024];
  293     const char *t;
  294     
  295     memset(h,0,1024);
  296     
  297     strcat(h, NIST_SIG);
  298     sprintf(p, "channel_count -i %d\n", num_channels);
  299     strcat(h, p);
  300     sprintf(p, "sample_count -i %d\n", num_samples);    
  301     strcat(h, p);
  302     sprintf(p, "sample_rate -i %d\n", sample_rate); 
  303     strcat(h, p);
  304     
  305     t = sample_type_to_nist(sample_type);
  306     if (t)
  307     {
  308     sprintf(p, "sample_coding -s%d %s\n", (signed)strlen(t), t);  
  309     strcat(h, p);
  310     sprintf(p, "sample_n_bytes -i %d\n", get_word_size(sample_type));
  311     strcat(h, p);
  312     }
  313     
  314     if (get_word_size(sample_type) > 1)
  315     {
  316     sprintf(p, "sample_byte_format -s%d %s\n", 2, 
  317         ((bo == bo_big) ? "10" : "01"));
  318     strcat(h, p);
  319     }
  320     
  321     strcat(h, NIST_END_SIG);
  322     /*makes it nice to read */
  323     strcat(h, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); 
  324     
  325     if (fwrite(&h, 1024, 1, fp) != 1)
  326     return misc_write_error;
  327     
  328     return save_raw_data(fp,data,offset,num_samples,num_channels,
  329              sample_type,bo);
  330     
  331 }
  332 
  333 /*=======================================================================*/
  334 /* EST's own format                                                      */
  335 /*=======================================================================*/
  336 
  337 enum EST_read_status load_wave_est(EST_TokenStream &ts, short **data, int
  338                    *num_samples, int *num_channels, int
  339                    *word_size, int *sample_rate, enum
  340                    EST_sample_type_t *sample_type, int *bo, 
  341                    int offset, int length)
  342 {
  343     int data_length, actual_bo;
  344     short *file_data;
  345     EST_String byte_order;
  346     int n;
  347     EST_EstFileType t;
  348     EST_Option hinfo;
  349     bool ascii;
  350     EST_read_status r;
  351     EST_sample_type_t actual_sample_type;
  352     
  353     offset = 0;
  354     
  355     if ((r = read_est_header(ts, hinfo, ascii, t)) != format_ok)
  356     return r;
  357     if (t != est_file_wave)
  358     return misc_read_error;
  359     
  360     *num_samples = hinfo.ival("NumSamples");
  361     *num_channels = hinfo.ival("NumChannels");
  362     *sample_rate = hinfo.ival("SampleRate");
  363     
  364     byte_order = hinfo.val("ByteOrder");
  365     
  366     if (length == 0)
  367     data_length = (*num_samples)*(*num_channels);
  368     else
  369     data_length = length*(*num_channels);
  370     
  371     file_data = walloc(short, data_length);
  372     
  373     n = ts.fread(file_data, sizeof(short), data_length);
  374     if ((n != data_length) && (n < 1))
  375     {
  376     cerr << "EST wave load: " << ts.pos_description() << endl;
  377     cerr << "failed to read file\n";
  378     wfree(file_data); 
  379     return misc_read_error;
  380     }
  381     else if (n != data_length)
  382     {
  383     cerr << "Wrong number of samples/channels in EST wave file\n";  
  384     cerr << ts.pos_description() << " ";
  385     cerr << "expected " << data_length << " got " << n << endl;
  386     data_length = n;
  387     }
  388     
  389     actual_bo = (byte_order == "10") ? bo_big : bo_little;
  390     if (hinfo.present("SampleType"))
  391     actual_sample_type = str_to_sample_type(hinfo.val("SampleType"));
  392     else
  393     actual_sample_type = st_short; // some older files don't have this
  394     
  395     *data = convert_raw_data((unsigned char *)file_data, 
  396                  data_length, actual_sample_type, actual_bo);
  397     // because internally data is always shorts
  398     *sample_type = st_short;
  399     *bo = EST_NATIVE_BO;
  400     *word_size = 2;
  401     
  402     return format_ok;
  403 }
  404 
  405 enum EST_write_status save_wave_est(FILE *fp, const short *data, int offset,
  406                        int num_samples, int num_channels, 
  407                        int sample_rate,
  408                        enum EST_sample_type_t sample_type, int bo)   
  409 {
  410     fprintf(fp, "EST_File wave\n");
  411     fprintf(fp, "DataType binary\n");
  412     fprintf(fp, "SampleRate %d\n", sample_rate);
  413     fprintf(fp, "NumSamples %d\n", num_samples);
  414     fprintf(fp, "NumChannels %d\n", num_channels);
  415     fprintf(fp, "SampleType %s\n", sample_type_to_str(sample_type));
  416     if (get_word_size(sample_type) > 1)
  417     fprintf(fp, "ByteOrder %s\n", ((bo == bo_big) ? "10" : "01"));
  418     
  419     fprintf(fp, "EST_Header_End\n");
  420     
  421     return save_raw_data(fp, data, offset, num_samples, num_channels,
  422              sample_type, bo);
  423     
  424 }
  425 
  426 /*=======================================================================*/
  427 /*  Microsoft RIFF (.wav) audio files                                    */
  428 /*                                                                       */
  429 /*  The information on this format was gained by reading a document      */
  430 /*  found on the net called "Multimedia Programming Interface and        */
  431 /*  Data Specification v1.0" and by looking at Rick Richardson,          */
  432 /*  Lance Norskog And Sundry Contributors code in SOX.  All this code    */
  433 /*  is rewritten from scratch though, but I couldn't do it without       */
  434 /*  other's explanations. I would have used the SOX code directly but    */
  435 /*  was not really in the right form so starting again was easier        */
  436 /*=======================================================================*/
  437 #define WAVE_FORMAT_PCM    0x0001
  438 #define WAVE_FORMAT_ADPCM  0x0002
  439 #define WAVE_FORMAT_ALAW   0x0006
  440 #define WAVE_FORMAT_MULAW  0x0007
  441 
  442 enum EST_read_status load_wave_riff(EST_TokenStream &ts, short **data, int
  443                     *num_samples, int *num_channels, int
  444                     *word_size, int *sample_rate, enum
  445                     EST_sample_type_t *sample_type, int *bo , int
  446                     offset, int length)
  447 {
  448     char info[4];
  449     int samps,sample_width,data_length;
  450     short shortdata;
  451     int dsize,intdata;
  452     unsigned char *file_data;
  453     enum EST_sample_type_t actual_sample_type;
  454     
  455     if (ts.fread(info,sizeof(char),4) != 4)
  456     return wrong_format;    /* its almost definitely an error */
  457     if (strncmp(info,"RIFF",4) != 0)
  458     return wrong_format;
  459 
  460     /* We've got a riff file */
  461     ts.fread(&dsize,4,1);
  462     /* .wav files are always little endian */
  463     if (EST_BIG_ENDIAN) dsize = SWAPINT(dsize);
  464     if ((ts.fread(info,sizeof(char),4) != 4) ||
  465     (strncmp(info,"WAVE",4) != 0))
  466     {
  467     fprintf(stderr, "RIFF file is not of type WAVE\n");
  468     return misc_read_error; /* not a wave file */
  469     }
  470     if ((ts.fread(info,sizeof(char),4) != 4) ||
  471     (strncmp(info,"fmt ",4) != 0))
  472     return misc_read_error; /* something else wrong */
  473 
  474     ts.fread(&dsize,4,1);
  475     if (EST_BIG_ENDIAN) dsize = SWAPINT(dsize);
  476     ts.fread(&shortdata,2,1);
  477     if (EST_BIG_ENDIAN) shortdata = SWAPSHORT(shortdata);
  478 
  479     switch (shortdata)
  480     {
  481     /* This is a non-proprietary format */
  482     case WAVE_FORMAT_PCM:
  483     actual_sample_type = st_short; break;
  484     /* The follow are registered proprietary WAVE formats  (?) */
  485     case WAVE_FORMAT_MULAW:
  486     actual_sample_type = st_mulaw; break;
  487     case WAVE_FORMAT_ADPCM:
  488     fprintf(stderr, "RIFF file: unsupported proprietary sample format ADPCM\n"); 
  489     actual_sample_type = st_short;
  490     break;
  491     /*    actual_sample_type = st_adpcm; break; */ /* yes but which adpcm ! */
  492     case WAVE_FORMAT_ALAW:
  493     default:
  494     fprintf(stderr, "RIFF file: unknown sample format\n");
  495     actual_sample_type = st_short;
  496     /*  return misc_read_error; */
  497     }
  498     ts.fread(&shortdata,2,1);
  499     if (EST_BIG_ENDIAN) shortdata = SWAPSHORT(shortdata);
  500     *num_channels = shortdata;
  501     ts.fread(sample_rate,4,1);
  502     if (EST_BIG_ENDIAN) *sample_rate = SWAPINT(*sample_rate);
  503     ts.fread(&intdata,4,1); /* average bytes per second -- ignored */
  504     if (EST_BIG_ENDIAN) intdata = SWAPINT(intdata);
  505     ts.fread(&shortdata,2,1);   /* block align ? */
  506     if (EST_BIG_ENDIAN) shortdata = SWAPSHORT(shortdata);
  507     ts.fread(&shortdata,2,1);
  508     if (EST_BIG_ENDIAN) shortdata = SWAPSHORT(shortdata);
  509 
  510     sample_width = (shortdata+7)/8;
  511     if ((sample_width == 1) && (actual_sample_type == st_short))
  512     actual_sample_type = st_uchar; /* oops I meant 8 bit */
  513 
  514     ts.seek((dsize-16)+ts.tell());     /* skip rest of header */
  515     while (1)
  516     {
  517     if (ts.fread(info,sizeof(char),4) != 4)
  518     {
  519         fprintf(stderr,"RIFF file truncated\n");
  520         return misc_read_error; /* something else wrong */
  521     }
  522     if (strncmp(info,"data",4) == 0)
  523     {
  524         ts.fread(&samps,4,1);
  525         if (EST_BIG_ENDIAN) samps = SWAPINT(samps);
  526         samps /= (sample_width*(*num_channels));
  527         break;
  528     }
  529     else if (strncmp(info,"fact",4) == 0)
  530     {           /* some other type of chunk -- skip it */
  531         ts.fread(&samps,4,1);
  532         if (EST_BIG_ENDIAN) samps = SWAPINT(samps);
  533         ts.seek(samps+ts.tell());   /* skip rest of header */
  534         /* Hope this is the right amount */
  535     }
  536     else
  537     {
  538             //      fprintf(stderr,"Ignoring unsupported chunk type \"%c%c%c%c\" in RIFF file\n",
  539             //    info[0],info[1],info[2],info[3]);
  540         //return misc_read_error;
  541         ts.fread(&dsize,4,1);
  542         if (EST_BIG_ENDIAN) dsize = SWAPINT(dsize);
  543         ts.seek(dsize+ts.tell());     /* skip this chunk */
  544     }
  545     }
  546     if (length == 0)
  547     data_length = (samps - offset)*(*num_channels);
  548     else
  549     data_length = length*(*num_channels);
  550     
  551     file_data = walloc(unsigned char,sample_width * data_length);
  552     
  553     ts.seek((sample_width*offset*(*num_channels))+ts.tell());
  554     if ((dsize=ts.fread(file_data,sample_width,data_length)) != data_length)
  555     {
  556     /*  It seems so many WAV files have their datasize wrong I'll */
  557     /*  let it through -- I think SOX is a major culprit          */
  558     if (length == 0) /* the file did the identification */
  559         fprintf(stderr,"Unexpected end of file but continuing (apparently missing %d samples)\n",data_length-dsize);
  560     else
  561     {
  562         fprintf(stderr,"Unexpected end of file: (missing %d samples)\n",data_length-dsize);
  563         wfree(file_data);
  564         return misc_read_error;
  565     }
  566     }
  567     
  568     *data = convert_raw_data(file_data,dsize,
  569                  actual_sample_type, bo_little);
  570     
  571     *num_samples = dsize / (*num_channels);
  572     *sample_type = st_short;
  573     *bo = EST_NATIVE_BO;
  574     *word_size = 2;
  575     
  576     return format_ok;
  577 }
  578 
  579 enum EST_write_status save_wave_riff(FILE *fp, const short *data, int offset,
  580                      int num_samples, int num_channels, 
  581                      int sample_rate,
  582                      enum EST_sample_type_t sample_type, int bo)   
  583 {
  584     (void)bo;
  585     const char *info;
  586     int data_size, data_int;
  587     short data_short;
  588 
  589     if (sample_type == st_schar)
  590       {
  591     EST_warning("RIFF format: Signed 8-bit not allowed by this file format");
  592     sample_type=st_uchar; 
  593       }
  594     
  595     info = "RIFF"; fwrite(info,4,1,fp);
  596     data_size = num_channels*num_samples*get_word_size(sample_type)+ 8+16+12;
  597     /* WAV files are always LITTLE_ENDIAN (i.e. intel x86 format) */
  598     if (EST_BIG_ENDIAN) data_size = SWAPINT(data_size);
  599     fwrite(&data_size,1,4,fp);  /* total number of bytes in file */
  600     info = "WAVE"; fwrite(info,4,1,fp);
  601     info = "fmt "; fwrite(info,4,1,fp);
  602     data_size = 16;
  603     if (EST_BIG_ENDIAN) data_size = SWAPINT(data_size);
  604     fwrite(&data_size,1,4,fp);  /* size of header */
  605     switch (sample_type)
  606     {
  607     case st_short:  data_short = WAVE_FORMAT_PCM; break;
  608     case st_uchar: data_short = WAVE_FORMAT_PCM; break;
  609     case st_mulaw: data_short = WAVE_FORMAT_MULAW; break;
  610     case st_alaw: data_short = WAVE_FORMAT_ALAW; break;
  611     case st_adpcm: data_short = WAVE_FORMAT_ADPCM; break;
  612     default:
  613       fprintf(stderr,"RIFF format: unsupported data format %d\n",
  614           sample_type);
  615       return misc_write_error;
  616            }
  617     if (EST_BIG_ENDIAN) data_short = SWAPSHORT(data_short);
  618     fwrite(&data_short,1,2,fp); /* sample type */
  619     data_short = num_channels;
  620     if (EST_BIG_ENDIAN) data_short = SWAPSHORT(data_short);
  621     fwrite(&data_short,1,2,fp); /* number of channels */
  622     data_int = sample_rate;
  623     if (EST_BIG_ENDIAN) data_int = SWAPINT(data_int);
  624     fwrite(&data_int,1,4,fp);   /* sample rate */
  625     data_int = sample_rate * num_channels * get_word_size(sample_type);
  626     if (EST_BIG_ENDIAN) data_int = SWAPINT(data_int);
  627     fwrite(&data_int,1,4,fp);   /* Average bytes per second */
  628     data_short = num_channels * get_word_size(sample_type);
  629     if (EST_BIG_ENDIAN) data_short = SWAPSHORT(data_short);
  630     fwrite(&data_short,1,2,fp); /* block align */
  631     data_short = get_word_size(sample_type) * 8;
  632     if (EST_BIG_ENDIAN) data_short = SWAPSHORT(data_short);
  633     fwrite(&data_short,1,2,fp); /* bits per sample */
  634     info = "data"; fwrite(info,4,1,fp);
  635     data_size = num_channels*num_samples*get_word_size(sample_type);
  636     if (EST_BIG_ENDIAN) data_size = SWAPINT(data_size);
  637     fwrite(&data_size,1,4,fp);  /* total number of bytes in data */
  638     
  639     return save_raw_data(fp,data,offset,num_samples,num_channels,
  640              sample_type,bo_little);
  641 }
  642 
  643 /*=======================================================================*/
  644 /* Amiga/Apple AIFF waveform format                                      */
  645 /* This was constructed using info in AudioIFF1.3.hqx found on the web   */
  646 /* and also I did look at SOX's aiff.c written by Guido van Rossum       */
  647 /* and Sundry Contributors.                                              */
  648 /*=======================================================================*/
  649 
  650 struct AIFFchunk {
  651     char id[4];
  652     int size;
  653 };
  654 
  655 struct AIFFssnd {       /* Sound Data Chunk */
  656     int offset;
  657     int blocksize;
  658 };
  659 
  660 enum EST_read_status load_wave_aiff(EST_TokenStream &ts, short **data, int
  661                     *num_samples, int *num_channels, int
  662                     *word_size, int *sample_rate, enum
  663                     EST_sample_type_t *sample_type, int *bo , int
  664                     offset, int length)
  665 {
  666     char info[4];
  667     struct AIFFchunk chunk;
  668     short comm_channels;
  669     int comm_samples;
  670     short comm_bits;
  671     unsigned char ieee_ext_sample_rate[10];
  672     struct AIFFssnd ssndchunk;
  673     enum EST_sample_type_t actual_sample_type;
  674     int dsize,data_length,n;
  675     unsigned char *file_data;
  676     
  677     if (ts.fread(info,sizeof(char),4) != 4)
  678     return wrong_format;    /* but its almost definitely an error */
  679     if (strncmp(info,"FORM",4) != 0)
  680     return wrong_format;
  681 
  682     /* We've got an aiff file, I hope */
  683     ts.fread(&dsize,4,1);
  684     if (EST_LITTLE_ENDIAN)  /* file is in different byte order */
  685     dsize = SWAPINT(dsize);
  686     if ((ts.fread(info,sizeof(char),4) != 4) ||
  687     (strncmp(info,"AIFF",4) != 0))
  688     {
  689     fprintf(stderr, "AIFF file does not have AIFF chunk\n");
  690     return misc_read_error; 
  691     }
  692     
  693     for ( ; ts.fread(&chunk,1,sizeof(chunk)) == sizeof(chunk) ; )
  694     {               /* for each chunk in the file */
  695     if (EST_LITTLE_ENDIAN)  /* file is in different byte order */
  696         chunk.size = SWAPINT(chunk.size);
  697     if (strncmp(chunk.id,"COMM",4) == 0)
  698     {
  699         if (chunk.size != 18)
  700         {
  701         fprintf(stderr,"AIFF chunk: bad size\n");
  702         return misc_read_error;
  703         }
  704         ts.fread(&comm_channels,1,sizeof(short));
  705         ts.fread(&comm_samples,1,sizeof(int));
  706         ts.fread(&comm_bits,1,sizeof(short));
  707         if (ts.fread(ieee_ext_sample_rate,1,10) != 10)
  708         {
  709         fprintf(stderr,"AIFF chunk: eof within COMM chunk\n");
  710         return misc_read_error;
  711         }
  712         if (EST_LITTLE_ENDIAN)
  713         {
  714         comm_channels = SWAPSHORT(comm_channels);
  715         comm_samples = SWAPINT(comm_samples);
  716         comm_bits = SWAPSHORT(comm_bits);
  717         }
  718         *sample_rate = (int)ConvertFromIeeeExtended(ieee_ext_sample_rate);
  719     }
  720     else if (strncmp(chunk.id,"SSND",4) == 0)
  721     {
  722         if (ts.fread(&ssndchunk,1,sizeof(ssndchunk)) != sizeof(ssndchunk))
  723         {
  724         fprintf(stderr,"AIFF chunk: eof within SSND chunk\n");
  725         return misc_read_error;
  726         }
  727         if (EST_LITTLE_ENDIAN)
  728         {
  729         ssndchunk.offset = SWAPINT(ssndchunk.offset);
  730         ssndchunk.blocksize = SWAPINT(ssndchunk.blocksize);
  731         }
  732         
  733         *num_channels = comm_channels;
  734         switch (comm_bits)
  735         {
  736         case 8: actual_sample_type = st_uchar; break;
  737         case 16: actual_sample_type = st_short; break;
  738         default:
  739             fprintf(stderr,"AIFF: unsupported sample width %d bits\n",
  740                 comm_bits);
  741             return misc_read_error;
  742         }
  743         
  744         ts.seek(ssndchunk.offset+(comm_channels*offset)+ts.tell());
  745         if (length == 0)
  746         data_length = (comm_samples-offset)*comm_channels;
  747         else
  748         data_length = length*comm_channels;
  749         file_data = walloc(unsigned char, 
  750                    data_length*comm_channels*
  751                    get_word_size(actual_sample_type));
  752         if ((n=ts.fread(file_data,get_word_size(actual_sample_type),
  753              data_length)) != data_length)
  754         {
  755         fprintf(stderr,"AIFF read: short file %s\n",
  756             (const char *)ts.filename());
  757         fprintf(stderr,"AIFF read: at %d got %d instead of %d samples\n",
  758             offset,n,data_length);
  759         data_length = n;
  760         }
  761         
  762         *data = convert_raw_data(file_data,data_length,
  763                      actual_sample_type,bo_big);
  764         *num_samples = data_length/comm_channels;
  765         *sample_type = st_short;
  766         *word_size = 2;
  767         *bo = EST_NATIVE_BO;
  768         break;          /* only care about the first SSND chunk */
  769     }
  770     else 
  771     {           /* skip bytes in chunk */
  772         ts.seek(ts.tell()+chunk.size);
  773     }
  774     }
  775     
  776     return format_ok;
  777 }
  778 
  779 enum EST_write_status save_wave_aiff(FILE *fp, const short *data, int offset,
  780                      int num_samples, int num_channels, 
  781                      int sample_rate,
  782                      enum EST_sample_type_t sample_type, int bo)   
  783 {
  784     (void)bo;
  785     const char *info;
  786     int data_size, data_int;
  787     unsigned char ieee_ext_buf[10];
  788     short data_short;
  789     
  790     info = "FORM";
  791     fwrite(info,1,4,fp);
  792     /* This number seems to be derived different for each example */
  793     data_size = 54+(num_samples*num_channels*get_word_size(sample_type));
  794     if (EST_LITTLE_ENDIAN)
  795     data_size = SWAPINT(data_size);
  796     fwrite(&data_size,1,4,fp);
  797     info = "AIFF";
  798     fwrite(info,1,4,fp);
  799     info = "COMM";
  800     fwrite(info,1,4,fp);
  801     data_int = 18;
  802     if (EST_LITTLE_ENDIAN)
  803     data_int = SWAPINT(data_int);
  804     fwrite(&data_int,1,4,fp);
  805     data_short = num_channels;
  806     if (EST_LITTLE_ENDIAN)
  807     data_short = SWAPSHORT(data_short);
  808     fwrite(&data_short,1,2,fp);
  809     data_int = num_samples;
  810     if (EST_LITTLE_ENDIAN)
  811     data_int = SWAPINT(data_int);
  812     fwrite(&data_int,1,4,fp);
  813     data_short = 8*get_word_size(sample_type);
  814     if (EST_LITTLE_ENDIAN)
  815     data_short = SWAPSHORT(data_short);
  816     fwrite(&data_short,1,2,fp);
  817     ConvertToIeeeExtended((double)sample_rate,ieee_ext_buf);
  818     fwrite(ieee_ext_buf,1,10,fp);
  819     info = "SSND";
  820     fwrite(info,1,4,fp);
  821     data_int = 8 + (num_samples*num_channels*get_word_size(sample_type));
  822     if (EST_LITTLE_ENDIAN)
  823     data_int = SWAPINT(data_int);
  824     fwrite(&data_int,1,4,fp);
  825     data_int = 0;
  826     if (EST_LITTLE_ENDIAN)
  827     data_int = SWAPINT(data_int);
  828     fwrite(&data_int,1,4,fp);   /* offset */
  829     if (EST_LITTLE_ENDIAN)
  830     data_int = SWAPINT(data_int);
  831     fwrite(&data_int,1,4,fp);   /* blocksize */
  832     
  833     if ((sample_type == st_short) ||
  834     (sample_type == st_uchar))
  835     return save_raw_data(fp,data,offset,num_samples,num_channels,
  836                  sample_type,bo_big);
  837     else
  838     {
  839     fprintf(stderr,"AIFF: requested data type not uchar or short\n");
  840     return misc_write_error;
  841     }
  842     
  843 }
  844 
  845 /*=======================================================================*/
  846 /* ulaw EST_filetype are just raw data with 8K ulaw contents                 */
  847 /*=======================================================================*/
  848 
  849 enum EST_read_status load_wave_ulaw(EST_TokenStream &ts, short **data, int
  850                     *num_samples, int *num_channels, int *word_size, int
  851                     *sample_rate, enum EST_sample_type_t *sample_type, int *bo,
  852                     int offset, int length)
  853 
  854 {
  855     unsigned char *ulaw;
  856     int data_length,samps;
  857     
  858     ts.seek_end();
  859     samps = ts.tell();
  860     
  861     if (length == 0)
  862     data_length = samps - offset;
  863     else
  864     data_length = length;
  865     
  866     ulaw = walloc(unsigned char, data_length);
  867     ts.seek(offset);
  868     if (ts.fread(ulaw,1,data_length) != data_length)
  869     {
  870     wfree(ulaw); 
  871     return misc_read_error;
  872     }
  873     
  874     *data = walloc(short,data_length);
  875     ulaw_to_short(ulaw,*data,data_length);
  876     wfree(ulaw);
  877     
  878     *num_samples = data_length;
  879     *sample_rate = 8000;
  880     *num_channels = 1;
  881     *sample_type = st_short;
  882     *word_size = 2;
  883     *bo = EST_NATIVE_BO;
  884     
  885     return format_ok;
  886 }
  887 
  888 enum EST_write_status save_wave_ulaw(FILE *fp, const short *data, int offset,
  889                      int num_samples, int num_channels, 
  890                      int sample_rate, 
  891                      enum EST_sample_type_t sample_type, int bo)
  892 {
  893     (void)sample_rate;
  894     (void)sample_type;
  895     return save_wave_raw(fp,data,offset,num_samples,num_channels,
  896              8000,st_mulaw,bo);
  897     
  898     
  899 }
  900 
  901 /*=======================================================================*/
  902 /* Sun and Next snd files                                                */
  903 /*=======================================================================*/
  904 
  905 typedef struct {
  906     unsigned int    magic;  /* magic number */
  907     unsigned int    hdr_size;   /* size of this header */
  908     int    data_size;           /* length of data (optional) */
  909     unsigned int    encoding;   /* data encoding format */
  910     unsigned int    sample_rate; /* samples per second */
  911     unsigned int    channels;    /* number of interleaved channels */
  912 } Sun_au_header;
  913 
  914 enum EST_read_status load_wave_snd(EST_TokenStream &ts, short **data, int
  915                    *num_samples, int *num_channels, int *word_size, int
  916                    *sample_rate,enum EST_sample_type_t *sample_type, int *bo ,
  917                    int offset, int length)
  918 {
  919     /* Header structures */
  920     Sun_au_header header;
  921     enum EST_sample_type_t encoding_type;
  922     int data_length, sample_width, bytes, samps, n;
  923     unsigned char *file_data;
  924     int current_pos;
  925     
  926     current_pos = ts.tell();
  927     ts.fread(&header, sizeof(Sun_au_header), 1);
  928     
  929     /* test for magic number */
  930     if ((EST_LITTLE_ENDIAN) && 
  931     ((unsigned int)0x2e736e64 == SWAPINT(header.magic)))
  932     {               /* wrong byte order, swap header */
  933     header.hdr_size = SWAPINT(header.hdr_size);
  934     header.data_size = SWAPINT(header.data_size);
  935     header.encoding = SWAPINT(header.encoding);
  936     header.sample_rate = SWAPINT(header.sample_rate);
  937     header.channels = SWAPINT(header.channels);
  938     }
  939     else if ((unsigned int)0x2e736e64 != header.magic)
  940     return wrong_format;
  941     
  942     switch (header.encoding) 
  943     {
  944     case 1:
  945     encoding_type = st_mulaw;   
  946     break;
  947     case 2:
  948     encoding_type = st_uchar;   
  949     break;
  950     case 3:
  951     encoding_type = st_short;   
  952     break;
  953     default:
  954     fprintf(stderr, "Unsupported data type in SND header\n");
  955     return misc_read_error;
  956     }
  957     
  958     *num_channels = header.channels;
  959     sample_width = get_word_size(encoding_type);
  960     *sample_rate = header.sample_rate;
  961     
  962     if ((header.data_size == 0) ||
  963     (header.data_size == -1))
  964     {
  965     ts.seek_end();
  966     bytes = ts.tell() - header.hdr_size;
  967     }
  968     else
  969     bytes = header.data_size;
  970     samps = bytes/sample_width;
  971     
  972     if (length == 0)
  973     data_length = (samps - offset)*(*num_channels);
  974     else
  975     data_length = length *(*num_channels);
  976     
  977     file_data = walloc(unsigned char, sample_width * data_length);
  978     ts.seek(current_pos+header.hdr_size+(sample_width*offset*(*num_channels)));
  979     if ((n=ts.fread(file_data,sample_width,data_length)) != data_length)
  980     {
  981     fprintf(stderr,"WAVE read: short file %s\n",
  982         (const char *)ts.filename());
  983     fprintf(stderr,"WAVE read: at %d got %d instead of %d samples\n",
  984         offset,n,data_length);
  985     data_length = n;
  986     }
  987     
  988     *data = convert_raw_data(file_data,data_length,encoding_type,bo_big);
  989 
  990     if (*data == NULL)
  991       return read_error;
  992     
  993     *num_samples = data_length/ (*num_channels);
  994     *sample_type = st_short;
  995     *bo = EST_NATIVE_BO;
  996     *word_size = 2;
  997     return read_ok;
  998 }
  999 
 1000 enum EST_write_status save_wave_snd(FILE *fp, const short *data, int offset,
 1001                     int num_samples, int num_channels, 
 1002                     int sample_rate, 
 1003                     enum EST_sample_type_t sample_type, int bo)
 1004 {
 1005     (void)bo;
 1006     /* Header structures */
 1007     Sun_au_header header;
 1008     
 1009     /* Fill in header structure */
 1010     header.magic = (unsigned int)0x2e736e64; /* should be a macro surely */
 1011     header.hdr_size = sizeof(header);        /* ! */
 1012     header.data_size = get_word_size(sample_type) * num_channels * num_samples;
 1013     
 1014     switch (sample_type) {
 1015     case st_mulaw:
 1016     header.encoding = 1;
 1017     break;
 1018     case st_uchar:
 1019     header.encoding = 2;
 1020     break;
 1021     case st_short:
 1022     header.encoding = 3;
 1023     break;
 1024     
 1025     default:
 1026     fprintf(stderr, 
 1027         "Unsupported sample type cannot be saved in SND format\n");
 1028     return misc_write_error;
 1029     
 1030     }
 1031     
 1032     /* check consistency */
 1033     
 1034     header.sample_rate = sample_rate;
 1035     
 1036     header.channels = num_channels;
 1037     
 1038     if (EST_LITTLE_ENDIAN)
 1039     {
 1040     /* snd files all in big endian format */
 1041     header.magic = SWAPINT(header.magic);
 1042     header.hdr_size = SWAPINT(header.hdr_size);
 1043     header.data_size = SWAPINT(header.data_size);
 1044     header.encoding = SWAPINT(header.encoding);
 1045     header.sample_rate = SWAPINT(header.sample_rate);
 1046     header.channels = SWAPINT(header.channels);
 1047     
 1048     }
 1049     /* write header */
 1050     if (fwrite(&header, sizeof(header), 1, fp) != 1)
 1051     return misc_write_error;
 1052 
 1053     /* snd files are always in BIG_ENDIAN (sun) byte order */
 1054     return save_raw_data(fp,data,offset,num_samples,num_channels,
 1055              sample_type,bo_big);
 1056 }
 1057 
 1058 /*=======================================================================*/
 1059 /* CSTR Audlab files (from the last century)                             */
 1060 /* They are always bigendian                                             */
 1061 /*=======================================================================*/
 1062 struct s1 {
 1063     char   c[17];
 1064     float  f1;
 1065     float  f2;
 1066 };
 1067 
 1068 struct s2 {
 1069     float f1;
 1070     float f2;   
 1071     float f3;
 1072     char c1;
 1073     char c2;
 1074     int i1;
 1075     int i2;
 1076 };
 1077 
 1078 struct audlabfh {
 1079     struct s1 z; 
 1080     char  file_type[8];
 1081     char  c1[17];
 1082     char  c2[17];
 1083     char  c3[17];
 1084     int   start;
 1085     char  data_type;    
 1086     char  c5[64];
 1087 };
 1088 
 1089 struct audlabsh {
 1090     int   channel_count;
 1091     char  serial;
 1092     int   sample_rate;
 1093     char  c1[20];
 1094     int   i1;
 1095     char  c2;
 1096     char  c3[121];
 1097     char  c4[121];
 1098     
 1099 };
 1100 struct audlabsd {
 1101     char descr[17];
 1102     int sample_count;
 1103     int nbits;
 1104     float f1;
 1105     struct s2 z;
 1106 };
 1107 
 1108 enum EST_read_status load_wave_audlab(EST_TokenStream &ts, short **data, int
 1109                       *num_samples, int *num_channels, int *word_size, int
 1110                       *sample_rate, enum EST_sample_type_t *sample_type, int *bo, int
 1111                       offset, int length)
 1112 {
 1113     /* Header structures */
 1114     struct audlabfh fh;
 1115     struct audlabsh sh;
 1116     struct audlabsd sd;
 1117     int data_length,sample_count;
 1118     int hdr_length;
 1119     int current_pos;
 1120     
 1121     /* Read header structures from char array */
 1122     current_pos = ts.tell();
 1123     ts.fread(&fh, sizeof(struct audlabfh), 1);
 1124     if (strcmp(fh.file_type, "Sample") != 0) 
 1125     return wrong_format;
 1126     
 1127     ts.fread(&sh, sizeof(struct audlabsh), 1);
 1128     ts.fread(&sd, sizeof(struct audlabsd), 1);
 1129     hdr_length = sizeof(struct audlabfh) +
 1130     sizeof(struct audlabsh) +
 1131         sizeof(struct audlabsd);
 1132     
 1133     if (EST_BIG_ENDIAN)
 1134     {
 1135     *num_channels = sh.channel_count;
 1136     *sample_rate = sh.sample_rate;
 1137     sample_count = sd.sample_count;
 1138     }
 1139     else            // audlab files are bigendian
 1140     {
 1141     *num_channels = SWAPINT(sh.channel_count);
 1142     *sample_rate = SWAPINT(sh.sample_rate);
 1143     sample_count = SWAPINT(sd.sample_count);
 1144     }
 1145     if (length == 0)
 1146     data_length = (sample_count - offset) * (*num_channels);
 1147     else
 1148     data_length = length *(*num_channels);
 1149     
 1150     *data = walloc(short,sizeof(short) * data_length);
 1151     ts.seek(current_pos+hdr_length+(sizeof(short)*offset*(*num_channels)));
 1152     
 1153     if ((int)ts.fread(*data, sizeof(short), data_length) != data_length)
 1154     {
 1155     wfree(*data);
 1156     return misc_read_error;
 1157     }
 1158     if (EST_LITTLE_ENDIAN)
 1159     swap_bytes_short(*data,data_length);
 1160     
 1161     *num_samples = data_length / (*num_channels);
 1162     *sample_type = st_short;    /* set internal type*/
 1163     *word_size = sizeof(short);
 1164     *bo = EST_NATIVE_BO;
 1165     
 1166     return format_ok;
 1167 }
 1168 
 1169 enum EST_write_status save_wave_audlab(FILE *fp, const short *data, int offset,
 1170                        int num_samples, int num_channels, 
 1171                        int sample_rate, 
 1172                        enum EST_sample_type_t sample_type, int bo)
 1173 {
 1174     (void)bo;
 1175     (void)sample_type;
 1176     /* Header structures */
 1177     struct audlabfh fh;
 1178     struct audlabsh sh;
 1179     struct audlabsd sd;
 1180     
 1181     fh.start = sizeof (struct audlabfh) +
 1182     sizeof (struct audlabsh) + sizeof (struct audlabsd);
 1183     fh.data_type = 2;
 1184     strcpy(fh.file_type, "Sample");
 1185     
 1186     if (EST_LITTLE_ENDIAN) 
 1187     {               // need to swap some of those numbers 
 1188     sh.channel_count = SWAPINT(num_channels);
 1189     sh.serial = 1;
 1190     sh.sample_rate = SWAPINT(sample_rate);
 1191     
 1192     sd.sample_count = SWAPINT(num_samples);
 1193     sd.nbits = SWAPINT(16);
 1194     }
 1195     else
 1196     {
 1197     sh.channel_count = num_channels;
 1198     sh.serial = 1;
 1199     sh.sample_rate = sample_rate;
 1200     
 1201     sd.sample_count = num_samples;
 1202     sd.nbits = 16;
 1203     }
 1204     sprintf(sd.descr, "Filter 1");
 1205     
 1206     /* write headers */
 1207     fwrite (&fh, sizeof(fh), 1, fp);
 1208     fwrite (&sh, sizeof(sh), 1, fp);
 1209     fwrite (&sd, sizeof(sd), 1, fp);
 1210     
 1211     /* write data*/
 1212     return save_raw_data(fp,data,offset,num_samples,num_channels,
 1213              st_short,bo_big);
 1214 }
 1215 
 1216 /*=======================================================================*/
 1217 /* Entropic ESPS SD files: portable (non-proprietary) method             */
 1218 /*=======================================================================*/
 1219 
 1220 /* Deep thanks go to Peter Kabal from McGill University whose AF code */
 1221 /* showed me this was even possible.  I looked at his code to find    */
 1222 /* parts I couldn't work out myself.  Also to Rodney Johnson of       */
 1223 /* Entropic whose document "ESPS APPLICATION NOTE: Non-ESPS Programs  */
 1224 /* and the ESPS File System" gave details of how to access ESPS files */
 1225 /* without using the ESPS library code.                               */
 1226 
 1227 #include "esps_utils.h"
 1228 enum EST_read_status load_wave_sd(EST_TokenStream &ts, short **data, int
 1229                   *num_samples, int *num_channels, int
 1230                   *word_size, int *sample_rate, enum
 1231                   EST_sample_type_t *sample_type, int *bo , int
 1232                   offset, int length)
 1233 {
 1234     /* A license free version of an esps file reading program */
 1235     FILE *fd;
 1236     esps_hdr hdr;
 1237     int actual_bo, sample_width, data_length;
 1238     enum EST_read_status rv;
 1239     int dl;
 1240     enum EST_sample_type_t actual_sample_type;
 1241     double d;
 1242     unsigned char *file_data;
 1243 
 1244     if ((fd = ts.filedescriptor()) == NULL)
 1245     {
 1246     fprintf(stderr, "Can't open esps file %s for reading\n",
 1247         (const char *)ts.filename());
 1248     return misc_read_error;
 1249     }
 1250     
 1251     if ((rv=read_esps_hdr(&hdr,fd)) != format_ok)
 1252     return rv;
 1253     
 1254     if (hdr->file_type != ESPS_SD)
 1255     {
 1256     fprintf(stderr,"ESPS file: not an FEA_SD file\n");
 1257     delete_esps_hdr(hdr);
 1258     return misc_read_error;
 1259     }
 1260     
 1261     if (fea_value_d("record_freq",0,hdr,&d) != 0)
 1262     {
 1263     fprintf(stderr,"ESPS file: can't find sample_rate in header assuming 16000\n");
 1264     *sample_rate = 16000;
 1265     }
 1266     else
 1267     *sample_rate = (int)d;
 1268     actual_sample_type = st_short; /* you're not trying hard enough */
 1269     sample_width = get_word_size(actual_sample_type);
 1270     *num_channels = hdr->field_dimension[0];
 1271     if (hdr->swapped)
 1272     actual_bo = (EST_BIG_ENDIAN ? bo_little : bo_big);
 1273     else
 1274     actual_bo = (EST_BIG_ENDIAN ? bo_big : bo_little);
 1275     
 1276     if (length == 0)
 1277     data_length = (hdr->num_records - offset)*(*num_channels);
 1278     else
 1279     data_length = length *(*num_channels);
 1280     
 1281     file_data = walloc(unsigned char, sample_width * data_length);
 1282     fseek(fd,hdr->hdr_size+(sample_width*offset*(*num_channels)),
 1283       SEEK_SET);
 1284     if ((dl=fread(file_data,sample_width,data_length,fd)) != data_length)
 1285     {
 1286     fprintf(stderr,"WAVE read: esps short file %s\n",
 1287         (const char *)ts.filename());
 1288     fprintf(stderr,"WAVE read: at %d got %d instead of %d samples\n",
 1289         offset,dl,data_length);
 1290     data_length = dl;
 1291     }
 1292     
 1293     *data = convert_raw_data(file_data,data_length,
 1294                  actual_sample_type,
 1295                  actual_bo);
 1296     
 1297     *num_samples = data_length/ (*num_channels);
 1298     *sample_type = st_short;
 1299     *bo = EST_NATIVE_BO;
 1300     *word_size = 2;
 1301     delete_esps_hdr(hdr);
 1302     return format_ok;
 1303     
 1304 }
 1305 
 1306 enum EST_write_status save_wave_sd(FILE *fp, const short *data, int offset,
 1307                    int num_samples, int num_channels, 
 1308                    int sample_rate, 
 1309                    enum EST_sample_type_t sample_type, int bo)
 1310 
 1311 {
 1312     (void)bo;
 1313     esps_hdr hdr = make_esps_sd_hdr();
 1314     enum EST_write_status rv;
 1315     short esps_type;
 1316     
 1317     hdr->num_records = num_samples;
 1318     switch (sample_type)
 1319     {
 1320     case st_short:  esps_type = ESPS_SHORT; break;
 1321         case st_schar:  esps_type = ESPS_CHAR; break; /* maybe should be BYTE */
 1322         case st_int:    esps_type = ESPS_INT; break;
 1323         case st_float:  esps_type = ESPS_FLOAT; break;
 1324         case st_double: esps_type = ESPS_DOUBLE; break;
 1325         default:
 1326             fprintf(stderr,"ESPS file: no support for sample_type %s\n",
 1327                 sample_type_to_str(sample_type));
 1328             return misc_write_error;
 1329         }
 1330     /* I believe all of the following are necessary and in this order */
 1331     add_field(hdr,"samples",esps_type,num_channels);
 1332     add_fea_special(hdr,ESPS_FEA_DIRECTORY,"margo:/disk/disk10/home/awb/projects/speech_tools/main");
 1333     add_fea_special(hdr,ESPS_FEA_COMMAND,
 1334             "EDST waveform written as ESPS FEA_SD.\n\
 1335             ");
 1336     add_fea_d(hdr,"start_time",0,(double)0);
 1337     add_fea_d(hdr,"record_freq",0,(double)sample_rate);
 1338     add_fea_d(hdr,"max_value",0,(double)27355);
 1339     
 1340     if ((rv=write_esps_hdr(hdr,fp)) != write_ok)
 1341     {
 1342     delete_esps_hdr(hdr);
 1343     return rv;
 1344     }
 1345     /* lets ignore desired bo and sample type for the time being */
 1346     delete_esps_hdr(hdr);
 1347     
 1348     return save_raw_data(fp,data,offset,num_samples,num_channels,
 1349              sample_type,EST_NATIVE_BO);
 1350 }
 1351 
 1352 /*=======================================================================*/
 1353 /* Raw data files -- unheadered                                          */
 1354 /* THESE FUNCTIONS ARE DIFFERENT FROM THE REST                           */
 1355 /* These function have more parameters than the standard file i/o        */
 1356 /* as information cannot be gleamed from the file                        */
 1357 /*=======================================================================*/
 1358 
 1359 enum EST_read_status load_wave_raw(EST_TokenStream &ts, short **data, int
 1360                    *num_samples, int *num_channels, 
 1361                    int *word_size, int
 1362                    *sample_rate,  
 1363                    enum EST_sample_type_t *sample_type, 
 1364                    int *bo, int offset, int length, 
 1365                    int isample_rate, 
 1366                    enum EST_sample_type_t isample_type,
 1367                    int ibo, int inc)
 1368 {
 1369     unsigned char *file_data;
 1370     int data_length,samps,sample_width;
 1371     int guess,i,samp;
 1372     short *ndata;
 1373     
 1374     if (isample_type == st_ascii)
 1375     {
 1376     /* Guess the size */
 1377     if ((offset != 0) || (length != 0))
 1378     {
 1379         fprintf(stderr,"Load ascii wave: doesn't support offets and lengths\n");
 1380         return misc_read_error;
 1381     }
 1382     
 1383     ts.seek_end();
 1384     guess = (int)(1.2*ts.tell()/7)+10; /* rough guess of the num of samps */
 1385     ts.seek(0);
 1386     *data = walloc(short, guess);
 1387     i=0;
 1388     while (!ts.eof())
 1389     {
 1390         samp = atoi(ts.get().string());
 1391         if (i == guess)
 1392         {
 1393         ndata = walloc(short,(int)(guess*1.2));
 1394         memmove(ndata,*data,guess*sizeof(short));
 1395         wfree(*data);
 1396         *data = ndata;
 1397         guess = (int)(guess*1.2);
 1398         }
 1399         if (samp < -32768)
 1400         {
 1401         fprintf(stderr,"Load ascii wave: sample %d underflow clipping\n",
 1402             i);
 1403         (*data)[i] = -32768;
 1404         }
 1405         else if (samp > 32767)
 1406         {
 1407         fprintf(stderr,"Load ascii wave: sample %d overflow clipping\n",
 1408             i);
 1409         (*data)[i] = 32767;
 1410         }
 1411         else
 1412         (*data)[i] = (short)samp;
 1413         i++;
 1414     }
 1415     data_length = i;
 1416     }
 1417     else
 1418     {
 1419     ts.seek_end();
 1420     sample_width = get_word_size(isample_type);
 1421     samps = ts.tell()/sample_width;
 1422     
 1423     if (length == 0)
 1424         data_length = samps - offset;
 1425     else
 1426         data_length = length;
 1427     
 1428     file_data = walloc(unsigned char, data_length * sample_width *inc);
 1429     ts.seek(offset*sample_width*inc);
 1430     if ((int)ts.fread(file_data,sample_width,data_length) != data_length)
 1431         return misc_read_error;
 1432     
 1433     *data = convert_raw_data(file_data,data_length,isample_type,ibo);
 1434     }
 1435     
 1436     *num_samples = data_length/inc;
 1437     *sample_rate = isample_rate;
 1438     *num_channels = inc;
 1439     *sample_type = st_short;
 1440     *word_size = 2;
 1441     *bo = EST_NATIVE_BO;
 1442     
 1443     return format_ok;
 1444 }
 1445 
 1446 enum EST_write_status save_wave_raw(FILE *fp, const short *data, 
 1447                     int offset,
 1448                     int num_samples, int num_channels, 
 1449                     int sample_rate,
 1450                     enum EST_sample_type_t sample_type, int bo)   
 1451 {
 1452     (void)sample_rate;
 1453     
 1454     return save_raw_data(fp,data,offset,num_samples,num_channels,
 1455              sample_type,bo);
 1456 }
 1457 
 1458 /***********************************************************************/
 1459 /*                                                                     */
 1460 /* end of file type specific functions                                 */
 1461 /*                                                                     */
 1462 /***********************************************************************/
 1463