"Fossies" - the Fresh Open Source Software Archive

Member "speech_tools/speech_class/EST_Wave.cc" (24 Oct 2017, 16431 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.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 :  Paul Taylor and Alan Black                      */
   34 /*             Date   :  May 1996                                        */
   35 /*-----------------------------------------------------------------------*/
   36 /*            EST_Wave Class source file                                 */
   37 /*                                                                       */
   38 /*=======================================================================*/
   39 
   40 #include <iostream>
   41 #include <cstdlib>
   42 #include <cstdio>
   43 #include <cmath>
   44 #include <cstring>
   45 #include "EST_cutils.h"
   46 #include "EST_Wave.h"
   47 #include "EST_wave_utils.h"
   48 #include "EST_wave_aux.h"
   49 #include "EST_TNamedEnum.h"
   50 #include "EST_WaveFile.h"
   51 
   52 #include "EST_Track.h"
   53 
   54 #include "waveP.h"
   55 
   56 #define sgn(x) (x>0?1:x?-1:0)
   57 
   58 const EST_String DEF_FILE_TYPE = "riff";
   59 const EST_String DEF_SAMPLE_TYPE = "short";
   60 
   61 const int EST_Wave::default_sample_rate=16000;
   62 
   63 EST_Wave::EST_Wave()
   64 {
   65     default_vals();
   66 }
   67 
   68 EST_Wave::EST_Wave(const EST_Wave &w)
   69 {
   70     default_vals();
   71     copy(w);
   72 }
   73 
   74 EST_Wave::EST_Wave(int n, int c, int sr)
   75 {
   76   default_vals(n,c);
   77   set_sample_rate(sr);
   78 }
   79 
   80 EST_Wave::EST_Wave(int samps, int chans,
   81            short *memory, int offset, int sample_rate, 
   82            int free_when_destroyed)
   83 {
   84   default_vals();
   85   p_values.set_memory(memory, offset, samps, chans, free_when_destroyed);
   86   set_sample_rate(sample_rate);
   87 }
   88 
   89 void EST_Wave::default_vals(int n, int c) 
   90 {
   91   // real defaults
   92   p_values.resize(n,c);
   93   p_sample_rate = default_sample_rate;
   94 
   95   init_features();
   96 }
   97 
   98 void EST_Wave::free_wave()
   99 {
  100   if (!p_values.p_sub_matrix)
  101     p_values.resize(0,0);
  102   clear_features();
  103 }
  104 
  105 EST_Wave::~EST_Wave()
  106 {
  107   free_wave();
  108 }
  109 
  110 void EST_Wave::copy_setup(const EST_Wave &w)
  111 {
  112     p_sample_rate = w.p_sample_rate;
  113     copy_features(w);
  114 }
  115 
  116 void EST_Wave::copy_data(const EST_Wave &w)
  117 {
  118     p_values.copy(w.p_values);
  119 }
  120 
  121 void EST_Wave::copy(const EST_Wave &w)
  122 {
  123     copy_setup(w);
  124 
  125     copy_data(w);
  126 }
  127 
  128 short &EST_Wave::a(int i, int channel)
  129 {
  130   if (i<0 || i>= num_samples())
  131     {
  132       cerr << "Attempt to access sample " << i << " of a " << num_samples() << " sample wave.\n";
  133       if (num_samples()>0)
  134     return *(p_values.error_return);
  135     }
  136 
  137   if (channel<0 || channel>= num_channels())
  138     {
  139       cerr << "Attempt to access channel " << channel << " of a " << num_channels() << " channel wave.\n";
  140       if (num_samples()>0)
  141     return *(p_values.error_return);
  142     }
  143 
  144   return p_values.a_no_check(i,channel);
  145 }
  146 
  147 short EST_Wave::a(int i, int channel) const
  148 {
  149   return ((EST_Wave *)this)->a(i,channel);
  150 }
  151 
  152 short &EST_Wave::a_safe(int i, int channel)
  153 {
  154     static short out_of_bound_value = 0;
  155 
  156     if ((i < 0) || (i >= num_samples()))
  157     {   // need to give them something but they might have changed it
  158     // so reinitialise it to 0 first
  159     out_of_bound_value = 0;
  160     return out_of_bound_value;
  161     }
  162     else
  163     return a_no_check(i,channel);
  164 }
  165 
  166 void EST_Wave::fill(short v, int channel)
  167 {
  168     if (channel == EST_ALL)
  169     {
  170     if (v == 0)  // this is *much* more efficient and common
  171         memset(values().memory(),0,num_samples()*num_channels()*2);
  172         else
  173         p_values.fill(v);
  174     }
  175     else 
  176       for (int i = 0; i < num_samples(); ++i)
  177     p_values.a_no_check(i,channel) = v;
  178 }
  179 
  180 EST_read_status EST_Wave::load(const EST_String filename, 
  181                    int offset, int length,
  182                    int rate)
  183 {
  184     EST_read_status stat = read_error;
  185     EST_TokenStream ts;
  186 
  187     if ((ts.open(filename)) == -1)
  188     {
  189     cerr << "Wave load: can't open file \"" << filename << "\"" << endl;
  190     return stat;
  191     }
  192 
  193     stat = load(ts,offset,length,rate);
  194     ts.close();
  195     return stat;
  196 }
  197 
  198 EST_read_status EST_Wave::load(EST_TokenStream &ts,
  199                    int offset, int length,
  200                    int rate)
  201 {
  202     EST_read_status stat = read_error;
  203     int pos = ts.tell();
  204     
  205     for(int n=0; n< EST_WaveFile::map.n() ; n++)
  206     {
  207     EST_WaveFileType t = EST_WaveFile::map.token(n);
  208     
  209     if (t == wff_none)
  210         continue;
  211     
  212     EST_WaveFile::Info *info = &(EST_WaveFile::map.info(t));
  213     
  214     if (! info->recognise)
  215         continue;
  216     
  217     EST_WaveFile::Load_TokenStream * l_fun =info->load;
  218     
  219     if (l_fun == NULL)
  220         continue;
  221 
  222     ts.seek(pos);
  223     stat = (*l_fun)(ts, *this, 
  224             rate, st_short, EST_NATIVE_BO, 1,
  225             offset, length);
  226     
  227     if (stat == read_ok)
  228     {
  229         set_file_type(EST_WaveFile::map.value(t));
  230         break;
  231     }
  232     else if (stat == read_error)
  233         break;
  234     }
  235     
  236     return stat;
  237 }
  238 
  239 EST_read_status EST_Wave::load(const EST_String filename, 
  240                    const EST_String type, 
  241                    int offset, int length,
  242                    int rate)
  243 {
  244     EST_read_status stat = read_error;
  245     EST_TokenStream ts;
  246 
  247     if (filename == "-")
  248     ts.open(stdin,FALSE);
  249     else if ((ts.open(filename)) == -1)
  250     {
  251     cerr << "Wave load: can't open file \"" << filename << "\"" << endl;
  252     return stat;
  253     }
  254 
  255     stat = load(ts,type,offset,length,rate);
  256     ts.close();
  257     return stat;
  258 }
  259 
  260 EST_read_status EST_Wave::load(EST_TokenStream &ts,
  261                    const EST_String type, 
  262                    int offset, int length,
  263                    int rate)
  264 {
  265     EST_WaveFileType t = EST_WaveFile::map.token(type);
  266 
  267     if (t == wff_none)
  268     {
  269     cerr << "Unknown Wave file type " << type << endl;
  270     return read_error;
  271     }
  272 
  273     EST_WaveFile::Load_TokenStream * l_fun = EST_WaveFile::map.info(t).load;
  274     
  275     if (l_fun == NULL)
  276     {
  277     cerr << "Can't load waves to files type " << type << endl;
  278     return read_error;
  279     }
  280     
  281     set_file_type(EST_WaveFile::map.value(t));
  282     return (*l_fun)(ts, *this,
  283             rate, st_short, EST_NATIVE_BO, 1,
  284             offset, length);
  285    
  286 }
  287 
  288 EST_read_status EST_Wave::load_file(const EST_String filename, 
  289              const EST_String type, int sample_rate,
  290              const EST_String stype, int bov, int nc, int offset,
  291              int length)
  292 {
  293     EST_read_status stat = read_error;
  294     EST_TokenStream ts;
  295 
  296     if (filename == "-")
  297     ts.open(stdin,FALSE);
  298     else if ((ts.open(filename)) == -1)
  299     {
  300     cerr << "Wave load: can't open file \"" << filename << "\"" << endl;
  301     return stat;
  302     }
  303 
  304     stat = load_file(ts,type,sample_rate,stype,bov,nc,offset,length);
  305     ts.close();
  306     return stat;
  307 }
  308 
  309 EST_read_status EST_Wave::load_file(EST_TokenStream &ts,
  310              const EST_String type, int sample_rate,
  311              const EST_String stype, int bov, int nc, int offset,
  312              int length)
  313 
  314 {
  315   EST_WaveFileType t = EST_WaveFile::map.token(type);
  316 
  317   EST_sample_type_t values_type = EST_sample_type_map.token(stype);
  318 
  319   if (t == wff_none)
  320     {
  321       cerr << "Unknown Wave file type " << type << endl;
  322       return read_error;
  323     }
  324 
  325   EST_WaveFile::Load_TokenStream * l_fun = EST_WaveFile::map.info(t).load;
  326     
  327   if (l_fun == NULL)
  328     {
  329       cerr << "Can't load waves to files type " << type << endl;
  330       return read_error;
  331     }
  332     
  333   return (*l_fun)(ts, *this,
  334           sample_rate, values_type, bov, nc,
  335           offset, length);
  336     
  337 }    
  338 
  339 void EST_Wave::sub_wave(EST_Wave &sw, 
  340             int offset, int num,
  341             int start_c, int nchan)
  342 {
  343   if (num == EST_ALL)
  344     num = num_samples()-offset;
  345   if (nchan == EST_ALL)
  346     nchan = num_channels()-start_c;
  347 
  348   p_values.sub_matrix(sw.p_values, offset, num, start_c, nchan);
  349   sw.set_sample_rate(sample_rate());
  350 }
  351 
  352 EST_write_status EST_Wave::save(const EST_String filename, 
  353                  const EST_String type)
  354 {
  355     FILE *fp;
  356 
  357     if (filename == "-")
  358     fp = stdout;
  359     else if ((fp = fopen(filename,"wb")) == NULL)
  360     {
  361     cerr << "Wave save: can't open output file \"" <<
  362         filename << "\"" << endl;
  363     return write_fail;
  364     }
  365 
  366     EST_write_status r = save(fp,type);
  367     if (fp != stdout)
  368     fclose(fp);
  369     return r;
  370 }
  371 
  372 EST_write_status EST_Wave::save(FILE *fp, const EST_String type)
  373 {
  374     EST_String save_type = (type == "") ? DEF_FILE_TYPE : type;
  375 
  376     EST_WaveFileType t = EST_WaveFile::map.token(save_type);
  377 
  378     if (t == wff_none)
  379     {
  380     cerr << "Wave: unknown filetype in saving " << save_type << endl;
  381     return write_fail;
  382     }
  383     
  384     EST_WaveFile::Save_TokenStream * s_fun = EST_WaveFile::map.info(t).save;
  385     
  386     if (s_fun == NULL)
  387     {
  388     cerr << "Can't save waves to files type " << save_type << endl;
  389     return write_fail;
  390     }
  391     
  392     return (*s_fun)(fp, *this, st_short, EST_NATIVE_BO);
  393 }
  394 
  395 EST_write_status EST_Wave::save_file(const EST_String filename,
  396                      EST_String ftype,
  397                      EST_String stype, int obo)
  398 {
  399     FILE *fp;
  400 
  401     if (filename == "-")
  402     fp = stdout;
  403     else if ((fp = fopen(filename,"wb")) == NULL)
  404     {
  405     cerr << "Wave save: can't open output file \"" <<
  406         filename << "\"" << endl;
  407     return write_fail;
  408     }
  409 
  410     EST_write_status r = save_file(fp,ftype,stype,obo);
  411     if (fp != stdout)
  412     fclose(fp);
  413     return r;
  414 }
  415 
  416 EST_write_status EST_Wave::save_file(FILE *fp,
  417                      EST_String ftype,
  418                      EST_String stype, int obo)
  419 {
  420     EST_WaveFileType t = EST_WaveFile::map.token(ftype);
  421     EST_sample_type_t sample_type = EST_sample_type_map.token(stype);
  422 
  423     if (t == wff_none)
  424       {
  425     cerr << "Unknown Wave file type " << ftype << endl;
  426     return write_fail;
  427       }
  428 
  429     EST_WaveFile::Save_TokenStream * s_fun = EST_WaveFile::map.info(t).save;
  430     
  431     if (s_fun == NULL)
  432     {
  433     cerr << "Can't save waves to files type " << ftype << endl;
  434     return write_fail;
  435     }
  436     
  437     return (*s_fun)(fp, *this, sample_type, obo);
  438     
  439 }
  440 
  441 void EST_Wave::resample(int new_freq)
  442 {
  443     // Resample wave to new sample rate
  444     if (new_freq != p_sample_rate)
  445     {
  446     if (p_values.rateconv(p_sample_rate, new_freq) != 0)
  447         cerr << "rateconv: failed to convert from " << p_sample_rate <<
  448         " to " << new_freq << "\n";
  449     else
  450         set_sample_rate(new_freq);
  451     }
  452     
  453 }
  454 
  455 void EST_Wave::compress(float mu, float lim)
  456 {
  457     int x;
  458  
  459     for (int i = 0; i < num_samples(); ++i)
  460     {
  461         for (int j = 0; j< num_channels(); ++j)
  462         {
  463             x = a_no_check(i,j);
  464             a_no_check(i,j) = lim * (sgn(x)*(log(1+(mu/lim)*abs(x))/log(1+mu)));
  465         }
  466     }    
  467 }  
  468 
  469 void EST_Wave::rescale(float gain, int normalize)
  470 {
  471     int ns;
  472     float factor = gain;
  473     float nsf;
  474     
  475     if (normalize)
  476     {
  477     int max = 0;
  478     for (int i = 0; i < num_samples(); ++i)
  479       for (int j = 0; j < num_channels(); ++j)
  480         if (abs(a_no_check(i,j)) > max)
  481         max = abs(a_no_check(i,j));
  482     if (fabs(max/32766.0-gain) < 0.001)
  483         return; /* already normalized */
  484     else
  485         factor *= 32766.0/(float)max;
  486     }
  487     
  488     for (int i = 0; i < num_samples(); ++i)
  489       for (int j = 0; j < num_channels(); ++j)
  490     {
  491             if (factor == 1.0)
  492                 ns = a_no_check(i,j);  // avoid float fluctuations
  493             else if (factor == -1.0)
  494                 ns = -a_no_check(i,j);  // avoid float fluctuations
  495             else
  496             {
  497                 nsf = (float)a_no_check(i,j) * factor;
  498                 if (nsf < 0.0)
  499                     ns = (int)(nsf - 0.5);
  500                 else
  501                     ns = (int)(nsf + 0.5);
  502             }
  503       if (ns < -32766)
  504         a_no_check(i,j)= -32766;
  505       else if (ns > 32766)
  506         a_no_check(i,j)= 32766;
  507       else
  508         a_no_check(i,j)= ns;
  509     }
  510 }
  511 
  512 void EST_Wave::rescale( const EST_Track &fc )
  513 {
  514   int ns, start_sample, end_sample;
  515   float target1, target2, increment, factor, nsf;
  516   
  517   int fc_length = fc.length();
  518   int _num_channels = num_channels();
  519 
  520   cerr << ((int)(fc.t(fc_length-1) * p_sample_rate)) << endl;
  521 
  522   if( ((int)(fc.t(fc_length-1) * p_sample_rate)) > num_samples() )
  523     EST_error( "Factor contour track exceeds waveform length (%d samples)",
  524          (fc.t(fc_length-1) * p_sample_rate) - num_samples() );
  525 
  526   start_sample = static_cast<unsigned int>( fc.t( 0 )*p_sample_rate );
  527   target1 = fc.a(0,0); // could use separate channels for each waveform channel
  528 
  529   for ( int k = 1; k<fc_length; ++k ){
  530     end_sample   = static_cast<unsigned int>( fc.t( k )*p_sample_rate );
  531     target2 = fc.a(k);
  532     
  533     increment = (target2-target1)/(end_sample-start_sample+1);
  534   
  535     factor = target1;
  536     for( int i=start_sample; i<end_sample; ++i, factor+=increment )
  537       for( int j=0; j<_num_channels; ++j ){
  538             if (factor == 1.0)
  539                 ns = a_no_check(i,j);  // avoid float fluctuations
  540             else if (factor == -1.0)
  541                 ns = -a_no_check(i,j);  // avoid float fluctuations
  542             else
  543             {
  544                 nsf = (float)a_no_check(i,j) * factor;
  545                 if (nsf < 0.0)
  546                     ns = (int)(nsf - 0.5);
  547                 else
  548                     ns = (int)(nsf + 0.5);
  549             }
  550           if (ns < -32766)
  551               a_no_check(i,j)= -32766;
  552           else if (ns > 32766)
  553               a_no_check(i,j)= 32766;
  554           else
  555               a_no_check(i,j)= ns;
  556       }
  557     start_sample = end_sample;
  558     target1 = target2;
  559   }
  560 }
  561 
  562 
  563 
  564 EST_Wave &EST_Wave::operator =(const EST_Wave &w)
  565 {
  566     copy(w);
  567     return *this;
  568 }
  569 
  570 EST_Wave &EST_Wave::operator +=(const EST_Wave &w)
  571 {
  572     EST_Wave w2;
  573     const EST_Wave *toadd = &w;
  574 
  575     if (w.num_channels() != num_channels())
  576     {
  577     cerr << "Cannot concatenate waveforms with differing numbers of channels\n";
  578     return *this;
  579     }
  580 
  581     if (p_sample_rate != w.sample_rate())
  582     {
  583     w2 = w;
  584     w2.resample(p_sample_rate);
  585     toadd= &w2;
  586     }
  587 
  588     p_values.add_rows(toadd->p_values);
  589 
  590     return *this;
  591 }
  592 
  593 // add wave p_values to existing wave in parallel to create multi-channel wave.
  594 EST_Wave &EST_Wave::operator |=(const EST_Wave &wi)
  595 {
  596     int i, k;
  597     EST_Wave w = wi; // to allow resampling of const
  598 
  599     w.resample(p_sample_rate);  // far too difficult otherwise
  600 
  601     int o_channels = num_channels();
  602     int r_channels = num_channels()+w.num_channels();
  603     int r_samples = Gof(num_samples(), w.num_samples());
  604 
  605     resize(r_samples, r_channels);
  606 
  607     for (k = 0; k < w.num_channels(); ++k)
  608     for (i=0; i < w.num_samples(); i++)
  609         a(i,k+o_channels) += w.a(i, k);
  610 
  611     return *this;
  612 }
  613 
  614 ostream& operator << (ostream& p_values, const EST_Wave &sig)
  615 {
  616     for (int i = 0; i < sig.num_samples(); ++i)
  617     p_values << sig(i) << "\n";
  618     
  619     return p_values;
  620 }
  621 
  622 int operator != (EST_Wave a, EST_Wave b)
  623    { (void)a; (void)b; return 1; }
  624 int operator == (EST_Wave a, EST_Wave b)
  625   {  (void)a; (void)b; return 0; }