Logo Search packages:      
Sourcecode: speech-tools version File versions  Download package

EST_Track.cc

/*************************************************************************/
/*                                                                       */
/*                Centre for Speech Technology Research                  */
/*                     University of Edinburgh, UK                       */
/*                    Copyright (c) 1994,1995,1996                       */
/*                        All Rights Reserved.                           */
/*                                                                       */
/*  Permission is hereby granted, free of charge, to use and distribute  */
/*  this software and its documentation without restriction, including   */
/*  without limitation the rights to use, copy, modify, merge, publish,  */
/*  distribute, sublicense, and/or sell copies of this work, and to      */
/*  permit persons to whom this work is furnished to do so, subject to   */
/*  the following conditions:                                            */
/*   1. The code must retain the above copyright notice, this list of    */
/*      conditions and the following disclaimer.                         */
/*   2. Any modifications must be clearly marked as such.                */
/*   3. Original authors' names are not deleted.                         */
/*   4. The authors' names are not used to endorse or promote products   */
/*      derived from this software without specific prior written        */
/*      permission.                                                      */
/*                                                                       */
/*  THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK        */
/*  DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING      */
/*  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT   */
/*  SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE     */
/*  FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    */
/*  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN   */
/*  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,          */
/*  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF       */
/*  THIS SOFTWARE.                                                       */
/*                                                                       */
/*************************************************************************/
/*                                                                       */
/*                       Author :  Paul Taylor                           */
/*                       Date   :  April 1994                            */
/* -------------------------------------------------------------------   */
/*                      EST_Track Class source file                      */
/*                                                                       */
/*************************************************************************/

#include <fstream.h>
#include <iostream.h>
#include <math.h>
#include "EST_unix.h"
#include "EST_Track.h"
#include "EST_string_aux.h"
#include "EST_TrackFile.h"
#include "EST_error.h"

const int EST_Track::default_sample_rate=16000; // occasionally needed for xmg files
const float EST_Track::default_frame_shift=0.005; // default frame spacing.

const EST_String DEF_FILE_TYPE = "est";

00055 EST_Track::EST_Track()
{
    default_vals();
}

00060 EST_Track::EST_Track(const EST_Track &a)
{ 
    default_vals();
    copy(a);
}

00066 EST_Track::EST_Track(int n_frames, int n_channels)
{
    default_vals();
    p_values.resize(n_frames, n_channels);
    p_times.resize(n_frames);
    p_is_val.resize(n_frames);
    p_channel_names.resize(n_channels);

    p_aux.resize(n_frames, 1);
    p_aux_names.resize(1);

    char d = 0;
    p_is_val.fill(d);
}

EST_Track::EST_Track(int n_frames, EST_TrackMap &map)
{
  int n_channels = map.last_channel()+1;

  default_vals();
  p_values.resize(n_frames, n_channels);
  p_times.resize(n_frames);
  p_is_val.resize(n_frames);
  p_channel_names.resize(n_channels);
  char d = 0;
  p_is_val.fill(d);
  assign_map(map);
}

00095 EST_Track::~EST_Track(void)
{
  //  clear_features();
}

void EST_Track::default_channel_names()
{
    for (int i = 0; i < num_channels(); ++i)
      set_channel_name("track" + itoString(i), i);
}

void EST_Track::default_vals(void)
{
    p_equal_space = FALSE;
    p_single_break = FALSE;
    p_values.resize(0, 0);
    p_times.resize(0);
    p_is_val.resize(0);
    p_aux.resize(0, 0);
    p_aux_names.resize(0);
    p_channel_names.resize(0);
    p_map = NULL;
    p_t_offset=0;
    
    init_features();
}

00122 int EST_Track::track_break(int i) const // does location i hold a break?
{
    return (p_is_val(i));
}    

00127 void EST_Track::set_break(int i) // make location i hold a break
{
    if (i > num_frames())
      cerr << "Requested setting of break value of the end of the array\n";
    
    p_is_val[i] = 1;
}    


00136 void EST_Track::set_value(int i) // make location i hold a value
{
    p_is_val[i] = 0;
}    

const EST_String EST_Track::channel_name(int i, const EST_ChannelNameMap &map, int strings_override) const
{
    (void)map;
    (void)strings_override;
    return p_channel_names(i);
}    

/* OLD ENUM VERSION 

const EST_String EST_Track::channel_name(int i, const EST_ChannelNameMap &map, int strings_override) const
{
    EST_ChannelType type = channel_unknown;
    
    if (strings_override && p_channel_names(i) != "")
      return p_channel_names(i);
    else if (p_map!=NULL && ((type = p_map->channel_type(i)) != channel_unknown))
    {
      const char *name = map.name(type);
      if (!name)
          name  = EST_default_channel_names.name(type);
      if (name != NULL)
        return EST_String(name);
      return "unnamed_channel" + itoString(type);
    }
    else if (!strings_override && p_channel_names(i) != "")
      return p_channel_names(i);
    else 
      return "track" + itoString(i);
}    
*/
00171 void EST_Track::set_channel_name(const EST_String &fn, int i)
{
    p_channel_names[i] = fn;
}    

00176 void EST_Track::set_aux_channel_name(const EST_String &fn, int i)
{
    p_aux_names[i] = fn;
}    

ostream& operator << (ostream& s, const EST_Track &tr)
{
    int i, j;
    for (i = 0; i < tr.num_frames(); ++i)
    {
      s << tr.t(i);
      for (j = 0; j < tr.num_channels(); ++j)
          s << "\t" << tr(i, j);
      for (j = 0; j < tr.num_aux_channels(); ++j)
          s << "\t" << tr.aux(i, j);
      s << "\t" << !tr.track_break(i) << endl;
    }
    return s;
}

void EST_Track::copy(const EST_Track& a)
{
    copy_setup(a);
    p_values = a.p_values;
    p_times = a.p_times;
    p_is_val = a.p_is_val;
    p_t_offset = a.p_t_offset;
    p_aux = a.p_aux;
    p_aux_names = a.p_aux_names;
}

00207 void EST_Track::copy_setup(const EST_Track& a)
{
    p_equal_space = a.p_equal_space;
    p_single_break = a.p_single_break;
    p_channel_names = a.p_channel_names;
    p_map = a.p_map;
    copy_features(a);
}    

00216 void EST_Track::resize(int new_num_frames, int new_num_channels, bool set)
{
    int old_num_frames = num_frames();

    if (new_num_frames<0)
      new_num_frames = num_frames();

    if (new_num_channels<0)
      new_num_channels = num_channels();

    p_channel_names.resize(new_num_channels);

    // this ensures the new channels have a default name
    if (new_num_channels > num_channels())
      for (int i = num_channels(); i < new_num_channels; ++i)
          set_channel_name("track_" + itoString(i), i);

    p_values.resize(new_num_frames, new_num_channels, set);
    p_times.resize(new_num_frames, set);
    p_is_val.resize(new_num_frames, set);

    p_aux.resize(new_num_frames, num_aux_channels(), set);
  
    // Its important that any new vals get set to 0
    for (int i = old_num_frames; i < num_frames(); ++i)
      p_is_val.a_no_check(i) = 0;

}

static void map_to_channels(EST_StrList &channel_map, 
                 EST_StrList &channel_names)
{
    EST_Litem *p;
    EST_String b, type, first, last;
    int n_f, n_l;

    for (p = channel_map.head(); p; p = next(p))
    {
      b = channel_map(p);
      if (b.matches("$", 0))
      {
          // do this backwards as types may have "_" in them
          b = b.after("$");
          if (!b.contains("-"))
          {
            cerr<<"Ill formed coefficient range in map: " << b << "\n";
            return;
          }
          type = b.before("-");
          first = b.after("-");

          if (!first.contains("+"))
          {
            cerr<<"Ill formed coefficient range in map: "<<first<<"\n";
            return;
          }

          last = first.after("+");
          first = first.before("+");
            
          n_f = Stringtoi(first);
          n_l = Stringtoi(last);

          for (int i = n_f; i < n_l; ++i)
            channel_names.append(type + "_" + itoString(i));
          channel_names.append(type + "_N");
      }
      else
          channel_names.append(b);
    }
}

00288 void EST_Track::resize(int new_num_frames, EST_StrList &new_channels, bool set)
{
    EST_StrList x;
    map_to_channels(new_channels, x);
    int i;
    EST_Litem *p;

    int new_num_channels;
    new_num_channels = x.length();

    if (new_num_frames<0)
      new_num_frames = num_frames();


    p_channel_names.resize(new_num_channels);
    // this ensures the new channels have a default name

    for (i = 0, p = x.head(); p ; p = next(p), ++i)
      set_channel_name(x(p), i);

    p_values.resize(new_num_frames, new_num_channels, set);
    p_times.resize(new_num_frames, set);
    p_is_val.resize(new_num_frames, set);
  
//  for (int i = 0; i < new_num_frames; ++i)
//    p_is_val.a_no_check(i) = 1;
}

00316 void EST_Track::resize_aux(EST_StrList &new_aux_channels, bool set)
{
    int i;
    EST_Litem *p;

    int new_num_channels;
    new_num_channels = new_aux_channels.length();

    p_aux_names.resize(new_num_channels);

    // this ensures the new channels have a default name
    for (i = 0, p = new_aux_channels.head(); p ; p = next(p), ++i)
      set_aux_channel_name(new_aux_channels(p), i);

    p_aux.resize(num_frames(), new_num_channels, set);
}

EST_Track& EST_Track::operator+=(const EST_Track &a) // add to existing track
{
    int i, j, k;
    
    if (num_frames() == 0)    // i.e. no existing EST_Track to add to
    {
      *this = a;
      return *this;
    }
    
    if (a.num_channels() != num_channels())
    {
      cerr << "Error: Tried to add " << a.num_channels() << 
          " channel EST_Track to "<<num_channels() << " channel EST_Track\n";
      return *this;
    }
    
    int old_num = num_frames();
    this->resize(a.num_frames()+ this->num_frames(), this->num_channels());
    for (i = 0, j = old_num; i < a.num_frames(); ++i, ++j)
    {
      for (k = 0; k < num_channels(); ++k)
          p_values.a_no_check(k, j) = a(i, k);
      p_times[j] = a.t(i);
      p_is_val[j] = a.p_is_val(i);
    }
    
    return *this;
}

EST_Track& EST_Track::operator|=(const EST_Track &a)
{                       // add to existing track in parallel
    int i, j, k;
    
    if (num_channels() == 0)  // i.e. no existing EST_Track to add to
    {
      *this = a;
      return *this;
    }
    
    if (a.num_frames() != num_frames())
    {
      cerr << "Error: Tried to add " << a.num_frames() << 
          " channel EST_Track to "<<num_frames()<< " channel EST_Track\n";
      return *this;
    }
    
    int old_num = num_channels();
    this->resize(a.num_frames(), this->num_channels() + a.num_channels());
    for (i = 0, j = old_num; i < a.num_channels(); ++i, ++j)
      for (k = 0; k < num_frames(); ++k)
          p_values.a_no_check(j, k) = a(k, i);
    
    return *this;
}

EST_Track &EST_Track::operator=(const EST_Track& a)
{
    copy(a);
    return *this;
}    


00396 int EST_Track::channel_position(const char *name, int offset) const
{
    int c;
    
    for (c=0; c<num_channels(); c++)
      if (channel_name(c) == name)
          return c+offset;
    
    return -1;
}

00407 float &EST_Track::a(int i, const char *name, int offset)
{ 
    int c;
    
    for (c=0; c<num_channels(); c++)
      if (channel_name(c) == name)
          return p_values.a_no_check(i, c+offset);
    
    cerr << "no channel '" << name << "'\n";
    return *(p_values.error_return);
}

EST_Val &EST_Track::aux(int i, const char *name)
{ 
    for (int c = 0; c < num_aux_channels(); c++)
      if (aux_channel_name(c) == name)
          return p_aux.a_no_check(i, c);
    
    cerr << "no auxiliary channel '" << name << "' found\n";
    return *(p_aux.error_return);
}

EST_Val &EST_Track::aux(int i, int c)
{ 
    return p_aux(i, c);
}

EST_Val &EST_Track::aux(int i, int c) const
{ 
    return ((EST_Track *)this)->aux(i,c);
}

#define EPSILON (0.0001)

00441 float &EST_Track::a(float t, int c, EST_InterpType interp)
{
    static float ia = 0.0;
    
    if (interp == it_nearest)
      return p_values.a_no_check(index(t), c);
    else if (interp == it_linear)
    {
      int i = index_below(t);
      if (i < 0)
          return a(0,c);
      
      float n = a(i,c), n1 = a(i+1,c);
      float tn = p_times(i), tn1 = p_times(i+1);
      ia = n + (n1-n)*(t-tn)/(tn1-tn);
      return ia;
    }
    else if (interp == it_linear_nz)
    {
      int i = index_below(t);
      if (i < 0)
          return a(0,c);
      
      float n = a(i,c), n1 = a(i+1,c);
      if (fabs(n) < EPSILON || fabs(n1) < EPSILON)
          return p_values.a_no_check(index(t), c);
      float tn = p_times(i), tn1 = p_times(i+1);
      ia = n + (n1-n)*(t-tn)/(tn1-tn);
      return ia;
    }
    return ia;
}

00474 int EST_Track::index(float x) const
{
    if (equal_space())
    {
      float s = shift();
      int f = (int)(x/s+0.5);
      if (f<0)
          f=0;
      else if (f>= num_frames())
          f=num_frames()-1;
      return f;
    }
    else if (num_frames() > 0)
    {
      int bst, bmid, bend;
      bst = 1;
      bend = num_frames();
      if (x < p_times.a_no_check(bst))
          bmid=bst;
      if (x >= p_times.a_no_check(bend-1))
          bmid=bend-1;
      else
      {
          while (1)
          {
            bmid = bst + (bend-bst)/2;
            if (bst == bmid)
                break;
            else if (x < p_times.a_no_check(bmid))
            {
                if (x >= p_times.a_no_check(bmid-1))
                  break;
                bend = bmid;
            }
            else
                bst = bmid;
          }
      }
      if (fabs(x - p_times.a_no_check(bmid)) < 
          fabs(x - p_times.a_no_check(bmid-1)))
          return bmid;
      else
          return bmid - 1;
    }
    
    return num_frames() -1;
}

00522 int EST_Track::index_below(float x) const
{
    if (equal_space())
    {
      float s = shift();
      int f = (int)(x/s);
      if (f<0)
          f=0;
      else if (f>= num_frames())
          f=num_frames()-1;
      return f;
    }
    else
    {
      for (int i = 1; i < num_frames(); ++i)
          if (x <= p_times.a_no_check(i))
            return i - 1;
      return num_frames()-1;
    }
}

00543 int EST_Track::val(int i) const
{
    return !p_is_val(i);
}
/*
   "p_equal_space" indicates whether the x-axis values are evenly spaced
   (FIXED) or spaced arbitrarily (VARI).
   
   "p_single_break" describes the break format. F0 contours are seldom
   continuous - often breaks occur due to unvoicing etc. These are a
   marked  in the data arrays by break values, "i_break" for ints
   and "f_break" for floats. The "p_single_break" channel specifies whether
   a break is represented by a single break value, or as a break
   value for every frame. eg
   (SINGLE)
   800  100
   810  105
   BREAK BREAK
   850  130
   860  135
   or
   (MANY)
   800  100
   810  105
   820 BREAK
   830 BREAK
   840 BREAK
   850  130
   860  135
   
   In the MANY case, only the y value is specified as a break, in the
   SINGLE case the x value may or may not be specified as a break. For
   this reason, when checking for breaks, it is useful to only rely
   on the y value being set to the i_break value. Not that if the single_break
   is MANY and the equal_space is FIXED, you dont really need x-axis
   values.
   
   Different functions naturally work better on different representations
   and that is why all these different types are supported. A
   general function mod_cont() is upplied to change from one
   type to another. Not all conversions are currently
   supported however.
   
   */

00588 float EST_Track::end() const
{
    if (num_frames() == 0)
      return 0.0;
    else
      return (p_times(prev_non_break(num_frames())));
}
00595 float EST_Track::start() const
{
    if (num_frames() == 0)
      return 0.0;
    else
      return (track_break(0) ? p_times(next_non_break(0)) : p_times(0));
}

00603 float EST_Track::shift() const
{
    int j1 = 0;
    int j2 = 0;
    
    if (!p_equal_space)
      EST_error("Tried to take shift from non-fixed contour\n");

    do
    {
      j1 = next_non_break(++j1);
      j2 = next_non_break(j1);
      //    cout << "j1:" << j1 << " j2:" << j2 << endl;
    }
    while ((j2 != 0) && (j2 != (j1 +1)));
    
    if (j2 == 0)
    {
      if (num_frames() > 1)
          return p_times(1) - p_times(0);
      else
          EST_error("Couldn't determine shift size\n");         

    }
    return (p_times(j2) - p_times(j1));
}

/* tries to find the next value that isnt a break. Dont really
   know what to do on a fail, so just return 0 */

00633 int EST_Track::next_non_break(int j) const
{
    int i = j;
    for (++i; i < num_frames(); ++i)
    {
      //    cout << "i: " << i << " " << value[i] << endl;
      if (!track_break(i))
          return i;
    }
    
    return 0;
}

/* give the current point, returns the previous non-break */

00648 int EST_Track::prev_non_break(int j) const
{
    int i = j;
    for (--i; i >= 0 ; --i)
      if (!track_break(i))
          return i;
    return 0;
}

00657 void EST_Track::change_type(float nshift, bool single_break)
{
    if (nshift != 0.0)
    {
      if (!p_equal_space || nshift != shift())
          sample(nshift);
      p_equal_space = TRUE;
    }
    
    if (single_break != p_single_break)
    {
      if (!p_single_break)
          pad_breaks();
      else 
          rm_excess_breaks();
    }
}

00675 void EST_Track::sample(float f_interval)
{
    EST_FVector new_times;
    EST_FMatrix new_values;
    EST_CVector new_is_break;
    int i, j, n;
    
    n = (int) rint(((end())/ f_interval));
    
    new_times.resize(n);
    new_values.resize(n, num_channels());
    new_is_break.resize(n);
    
    // REORG - can this be replaced with fill_time()?
    for (i = 0; i < n; ++i)
      new_times[i] = (float) ((i + 1) * f_interval);
    
    for (i = 0; i < n; ++i)
    {
      new_is_break[i] = !interp_value(new_times(i), f_interval);
      for (j = 0; j < num_channels(); ++j)
          new_values(i, j) = !new_is_break(i) ? interp_amp(new_times(i), j, f_interval): 0.0;
    }
    
    p_times = new_times;
    p_values = new_values;
    p_is_val = new_is_break;
    p_single_break = FALSE;
    p_equal_space = TRUE;
}

float EST_Track::interp_amp(float x, int c, float fl)
{
    int i;
    float x1, x2, y1, y2, m;
    
    for (i = 0; i < num_frames(); ++i)
      if ((p_times(i) + (fl / 2.0))> x)
          break;
    
    if (i == num_frames())
      return p_values.a_no_check(i - 1,c);
    if (i == 0)
      return p_values.a_no_check(0, c);
    
    if (track_break(i) && track_break(i - 1))
      return 0.0;
    
    if (track_break(i))
      return p_values.a_no_check(i - 1, c);
    
    else if (track_break(i - 1))
      return p_values.a_no_check(i, c);
    
    x1 = p_times(i - 1);
    y1 = p_values.a_no_check(i - 1, c);
    x2 = p_times(i);
    y2 = p_values.a_no_check(i, c);
    
    m =  (y2 - y1) / (x2 -x1);
    return ((x - x1) * m) + y1;
}           

int EST_Track::interp_value(float x, float fl)
{
    int i;
    int p, n;
    float cf;
    
    if (p_equal_space)
      cf = shift();
    else
      cf = estimate_shift(x);
    
    for (i = 0; i < num_frames(); ++i)
      if ((p_times(i) + (fl / 2.0))> x)
          break;
    // This was:    
    //    for (i = 0; i < num_frames(); ++i)
    //      if (p_times[i] > x)
    //          break;
    
    if (i == 0)               // must be a break for the first value. (can't have i -1).
      return FALSE;
    
    if ((!track_break(i)) && (!track_break(i -1)))
      return TRUE;
    
    p = prev_non_break(i);
    n = next_non_break(i);
    
    if ((x < p_times(p) + (cf / 2.0)) || (x > p_times(n) - (cf / 2.0)))
      return TRUE;            // rounding at edges
    
    return FALSE;
}

float EST_Track::estimate_shift(float x)
{
    int i, j;
    for (j = 0; j < num_frames(); ++j)
      if (p_times(j) > x)
          break;
    
    for (i = j; i > 0; --i)
      if ((!track_break(i)) && (!track_break(i - 1)))
          return p_times(i) - p_times(i - 1);
    
    for (i = j; i < num_frames() - 1; ++i)
      if ((!track_break(i)) && (!track_break(i + 1)))
          return p_times(i + 1) - p_times(i);
    
    return 5.0;               // default value
}

00790 void EST_Track::fill_time(float t, int start)
{
    for (int i = 0; i < num_frames(); ++i)
      p_times.a_no_check(i) = t * (float) (i + start);
}

00796 void EST_Track::fill_time(EST_Track &t)
{
    for (int i = 0; i < num_frames(); ++i)
      p_times.a_no_check(i) = t.t(i);
}

00802 void EST_Track::rm_excess_breaks()
{
    int i, j, k;
    EST_FVector new_times;
    EST_CVector new_is_break;
    EST_FMatrix new_values;
    
    new_values.resize(num_channels(), num_frames());
    new_times.resize(num_frames());
    new_is_break.resize(num_frames());
    
    for (i = 0; track_break(i); ++i); //rm leading breaks
    
    for (j = 0; i < num_frames(); ++i, ++j)
    {
      for (k = 0; k < num_channels(); ++k)
          new_values(j, k) = p_values.a_no_check(i, k);
      new_times[j] = p_times(i);
      new_is_break[j] = p_is_val(i);
      while ((!new_is_break(j)) && (!val(i + 1)))
          ++i;
    }
    p_times = new_times;
    p_values = new_values;
    p_is_val = new_is_break;
    for (--j; track_break(j); --j) // "rm" trailing breaks
      ;
    p_times.resize(num_frames());
    p_values.resize(num_frames(), num_channels());
    p_is_val.resize(num_frames());
    
    p_single_break = TRUE;
}    

void EST_Track::rm_trailing_breaks()
{
    if (num_frames() <=0 )
      return;
    int start, end;

    for (start = 0; start < num_frames(); ++start)
      if (!track_break(start))
          break;

    for(end=num_frames(); end>0; end--)
      if (!track_break(end-1))
          break;

    if (start==0 && end==num_frames())
      return;
    
    for (int i=start, j = 0; i < end; ++i, ++j)
    {
      p_times[j] = p_times(i);
      for (int k = 0; k < num_channels(); k++)
          a_no_check(j, k) = a_no_check(i, k);
      p_is_val[j] = p_is_val(i);
    }

    p_values.resize(end-start, EST_CURRENT, 1);
    
    p_times.resize(num_frames());
    p_is_val.resize(num_frames());
}    

void EST_Track::add_trailing_breaks()
{
    int i, j, k;
    EST_FVector new_times;
    EST_FMatrix new_values;
    int new_num = num_frames();
    
    if (!track_break(0))
      new_num++;
    if (!track_break(num_frames() - 1))
      new_num++;
    
    if (new_num == num_frames()) /*ie trailing breaks already there */
      return;
    
    new_times.resize(new_num);
    new_values.resize(num_channels(), new_num);
    
    j = 0;
    if (!track_break(j))
      set_break(j);
    
    for (i = 0; i < num_frames(); ++i, ++j)
    {
      new_times[j] = p_times(i);
      for (k = 0; k < num_channels(); ++k)
          new_values(j, k) = p_values.a_no_check(i, k);
    }
    
    if (!track_break(num_frames() - 1))
      set_break(j);
    
    p_times = new_times;
    p_values = new_values;
    p_times.resize(num_frames());
    p_values.resize(num_frames(), num_channels());
}    

void EST_Track::pad_breaks()
{
    if (!p_single_break)
      return;
    
    if (!p_equal_space)
      EST_error("pad_breaks: Can only operate on fixed data\n");
    
    EST_FVector new_times;
    EST_FMatrix new_values;
    EST_CVector new_is_break;
    int i, j, k, n;
    
    n = (int)(((end())/ shift()) + 1.0);
    int s = int(start()/ shift());
    
    for (i = 0; i < n; ++i)
    {
      new_times[i] = (float) (i * shift());
      for (k = 0; k < num_channels(); ++k)
          new_values(k, i) = 0.0;
      new_is_break[i] = 0;
    }
    
    for (i = 0, j = s; j < n; ++i, ++j)
    {
      if (track_break(i))
      {
          for (; new_times(j) < p_times(i + 1); ++j);
          --j;
      }
      else
      {
          new_is_break[j] = 1;
          for (k = 0; k < num_channels(); ++k)
            new_values(j, k) = p_values.a_no_check(i, k);
      }
    }
    new_is_break[j] = 1;
    for (k = 0; k < num_channels(); ++k)
      new_values(j, k) = p_values.a_no_check(i, k);
    
    p_times = new_times;
    p_values = new_values;
    p_is_val = new_is_break;
    
    p_times.resize(num_frames());
    p_is_val.resize(num_frames());
    p_values.resize(num_frames(), num_channels());
    
    p_single_break = FALSE;
}    

static bool bounds_check(const EST_Track &t, int f, int c, int set)
{
  const char *what = set? "set" : "access";

  if (f<0 || f >= t.num_frames())
    {
      cerr << "Attempt to " << what << " frame " << f << " of " << t.num_frames() << " frame track\n";
      return FALSE;
    }
  if (c<0 || c >= t.num_channels())
    {
      cerr << "Attempt to " << what << " channel " << c << " of " << t.num_channels() << " channel track\n";
      return FALSE;
    }

return TRUE;
}

static bool bounds_check(const EST_Track &t, 
                   int f, int nf,
                   int c, int nc,
                   int set)
{
  const char *what = set? "set" : "access";

  if (nf>0)
    {
      if (f<0 || f >= t.num_frames())
      {
        cerr << "Attempt to " << what << " frame " << f << " of " << t.num_frames() << " frame track\n";
        return FALSE;
      }
      if (f+nf-1 >= t.num_frames())
      {
        cerr << "Attempt to " << what << " frame " << f+nf-1 << " of " << t.num_frames() << " frame track\n";
        return FALSE;
      }
    }

  if (nc>0)
    {
      if (c<0 || c >= t.num_channels())
      {
        cerr << "Attempt to " << what << " channel " << c << " of " << t.num_channels() << " channel track\n";
        return FALSE;
      }
      if (c+nc-1 >= t.num_channels())
      {
        cerr << "Attempt to " << what << " channel " << c+nc-1 << " of " << t.num_channels() << " channel track\n";
        return FALSE;
      }
    }

return TRUE;
}

01014 float &EST_Track::a(int i, int c)
{
  if (!bounds_check(*this, i,c,0))
      return *(p_values.error_return);

  return p_values.a_no_check(i,c);
}

float EST_Track::a(int i, int c) const
{
  return ((EST_Track *)this)->a(i,c);
}

01027 int EST_Track::empty() const
{
    int i, num;
    
    for (i = num = 0; i < num_frames(); ++i)
      if (val(i))
          return 0;           // i.e. false
    
    return 1;                 // i.e. true
}

01038 void EST_Track::channel(EST_FVector &cv, const char * name, int startf, int nf)
{
    int n;
    if ((n = channel_position(name)) == -1)
    {
      cerr << "No such channel " << name << endl;
      return;
    }
    channel(cv, n, startf, nf);
}

01049 void EST_Track::sub_track(EST_Track &st,
                    int start_frame, int nframes,
                    const EST_String &start_chan_name, int nchans)
{
    int start_chan;
    if (start_chan_name == "")
      start_chan = 0;

    if ((start_chan = channel_position(start_chan_name)) == -1)
      EST_error("sub_track: No such channel %s\n", 
              (const char *)start_chan_name);

    sub_track(st, start_frame, nframes, start_chan, nchans);
}

01064 void EST_Track::sub_track(EST_Track &st,
                    int start_frame, int nframes,
                    const EST_String &start_chan_name,
                    const EST_String &end_chan_name) 
{
    int start_chan, end_chan, nchans=0;

    if ((start_chan = channel_position(start_chan_name)) == -1)
      EST_error("sub_track: No such channel %s\n", 
              (const char *)start_chan_name);

    if (end_chan_name == "")
      nchans = EST_ALL;
    else
    {
      if ((end_chan = channel_position(end_chan_name)) == -1)
          EST_error("sub_track: No such channel %s\n", 
                  (const char*)end_chan_name);
      else
          nchans = end_chan - start_chan + 1;
    }

    sub_track(st, start_frame, nframes, start_chan, nchans);
}

01089 void EST_Track::sub_track(EST_Track &st,
                    int start_frame, int nframes,
                    int start_chan, int nchans)
{
  if (nframes <0)
    nframes = num_frames() - start_frame;
  if (nchans <0)
    nchans = num_channels() - start_chan;

  if (!bounds_check(*this, start_frame, nframes, start_chan, nchans, 0))
    return;

  p_values.sub_matrix(st.p_values, start_frame, nframes, start_chan, nchans);

  p_times.sub_vector(st.p_times, start_frame, nframes);

  p_is_val.sub_vector(st.p_is_val, start_frame, nframes);

  p_channel_names.sub_vector(st.p_channel_names,   start_chan, nchans);

  // All auxiliary information is included. These are effectively
  // pointer statements

  p_aux.sub_matrix(st.p_aux, start_frame, nframes, 0, EST_ALL);
  p_aux_names.sub_vector(st.p_aux_names, 0, EST_ALL);

  st.p_t_offset = p_t_offset;
  
  st.p_equal_space = p_equal_space;
  st.p_single_break = p_single_break;
  st.copy_features(*this);

  if (p_map!=0)
    st.p_map = new EST_TrackMap(p_map, start_chan, EST_TM_REFCOUNTED);
  else
    st.p_map = NULL;
}


01128 void EST_Track::copy_sub_track(EST_Track &st,
                         int start_frame, int nframes,
                         int start_chan, int nchans) const
{
  if (nframes <0)
    nframes = num_frames() - start_frame;
  if (nchans <0)
    nchans = num_channels() - start_chan;

  if (!bounds_check(*this, start_frame, nframes, start_chan, nchans, 0))
    return;

  st.resize(nframes, nchans);

  for (int ff=0; ff<nframes; ff++)
    {
      st.p_times.a(ff) = p_times.a(ff+start_frame);
      st.p_is_val.a(ff) = p_is_val.a(ff+start_frame);
      for (int c=0; c<nchans; c++)
      st.p_values.a(ff,c) = p_values.a(ff+start_frame,c+start_chan);
    }

  for (int c=0; c<nchans; c++)
    st.p_channel_names.a(c) = p_channel_names.a(c+start_chan);

  st.p_aux = p_aux;
  st.p_aux_names = p_aux_names;

  st.p_equal_space = p_equal_space;
  st.p_single_break = p_single_break;

  st.copy_features(*this);

  if (p_map!=0)
    st.p_map = new EST_TrackMap(p_map, start_chan, EST_TM_REFCOUNTED);
  else
    st.p_map = NULL;
}

01167 EST_write_status EST_Track::save(const EST_String filename, 
                         const EST_String type)
{
    EST_String save_type = (type == "") ? DEF_FILE_TYPE : type;

    EST_TrackFileType t = EST_TrackFile::map.token(save_type);
    
    if (t == tff_none)
    {
      cerr << "Unknown Track file type " << save_type << endl;
      return write_fail;
    }
    
    EST_TrackFile::Save_File * s_fun = EST_TrackFile::map.info(t).save;
    
    if (s_fun == NULL)
    {
      cerr << "Can't save tracks to files type " << save_type << endl;
      return write_fail;
    }
    
    return (*s_fun)(filename, *this);
}

01191 EST_write_status EST_Track::save(FILE *fp, const EST_String type)
{
    EST_TrackFileType t = EST_TrackFile::ts_map.token(type);
    
    if (t == tff_none)
    {
      cerr << "Unknown Track file type " << type << endl;
      return write_fail;
    }
    
    EST_TrackFile::Save_TokenStream * s_fun = 
      EST_TrackFile::ts_map.info(t).save;
    
    if (s_fun == NULL)
    {
      cerr << "Can't save tracks to files type " << type << endl;
      return write_fail;
    }
    return (*s_fun)(fp, *this);
}

01212 EST_read_status EST_Track::load(EST_TokenStream &ts, float ishift)
{
    EST_read_status stat = read_error;
    
    for (int n = 0; n < EST_TrackFile::ts_map.n(); n++)
    {
      EST_TrackFileType t = EST_TrackFile::ts_map.token(n);
      
      if (t == tff_none)
          continue;

      EST_TrackFile::TS_Info *info = &(EST_TrackFile::ts_map.info(t));
      
      if (! info->recognise)
          continue;
      
      EST_TrackFile::Load_TokenStream * l_fun =info->load;
      
      if (l_fun == NULL)
          continue;
      
      stat = (*l_fun)(ts, *this, ishift);
      
      if (stat != read_format_error)
        {
          if (stat == read_ok)
            set_file_type(t);
          break;
        }
    }
    
    return stat;
}

01246 EST_read_status EST_Track::load(const EST_String filename, float ishift)
{
    EST_read_status stat = read_error;
    
    for(int n=0; n< EST_TrackFile::map.n() ; n++)
    {
      EST_TrackFileType t = EST_TrackFile::map.token(n);
      
      if (t == tff_none)
          continue;
      
      
      EST_TrackFile::Info *info = &(EST_TrackFile::map.info(t));
      
      if (! info->recognise)
          continue;
      
      EST_TrackFile::Load_File * l_fun =info->load;
      
      if (l_fun == NULL)
          continue;
      
      stat = (*l_fun)(filename, *this, ishift);
      
      if (stat == read_ok)
      {
          set_file_type(t);
          break;
      }
      else if (stat == read_error)
          break;
    }
    
    return stat;
}

01282 EST_read_status EST_Track::load(const EST_String filename, const EST_String type, float ishift)
{
    EST_TrackFileType t = EST_TrackFile::map.token(type);
    
    if (t == tff_none)
    {
      cerr << "Unknown Track file type " << type << endl;
      return read_error;
    }
    
    EST_TrackFile::Load_File * l_fun = EST_TrackFile::map.info(t).load;
    
    if (l_fun == NULL)
    {
      cerr << "Can't load tracks from file type" << type << endl;
      return read_error;
    }
    
    set_file_type(t);
    return (*l_fun)(filename, *this, ishift);
}

EST_write_status EST_Track::save_channel_names(const EST_String filename)
{
    FILE *file;
    
    if ((file=fopen(filename, "wb"))==NULL)
      return write_fail;
    
    for(int c=0; c<num_channels(); c++)
      fprintf(file, "%s\n", (const char *)channel_name(c));
    
    fclose(file);
    
    return write_ok;
}

EST_read_status EST_Track::load_channel_names(const EST_String filename)
{
    FILE *file;
    static const int buffer_length = 100;
    char buffer[buffer_length];
    
    if ((file=fopen(filename, "rb"))==NULL)
      return misc_read_error;
    
    for(int c=0; c<num_channels(); c++)
    {
      if (!fgets(buffer, buffer_length, file))
          break;
      
      buffer[strlen(buffer)-1] = '\0';
      set_channel_name(buffer, c);
    }
    
    
    fclose(file);
    
    return format_ok;
}

/* code from here down should be deleted once tracp mapping is modified */


float &EST_Track::a(float t, EST_ChannelType type, EST_InterpType interp)
{ 
    short c = NO_SUCH_CHANNEL;
    
    if (p_map!=0 && (c = p_map->get(type)) != NO_SUCH_CHANNEL)
      return a(t, c, interp);
    else
    {
      cerr << "no channel '" << EST_default_channel_names.name(type) << "' = " << (int)type << "\n";
    }
    return *(p_values.error_return);
}


void EST_Track::assign_map(EST_TrackMap::P map)
{
    p_map = map;
}

void EST_Track::create_map(EST_ChannelNameMap &names)
{
    EST_TrackMap::P map = new EST_TrackMap(EST_TM_REFCOUNTED);
    
    for (int i = 0; i < num_channels(); i++)
    {
      EST_ChannelType type = names.token(p_channel_names(i));
      
      if (type != channel_unknown)
        map->set(type, i);
    }
    
    assign_map(map);
}


void EST_Track::resize(int new_num_frames, EST_TrackMap &map)
{
    resize(new_num_frames, map.last_channel()+1);
    assign_map(map);
}



int EST_Track::channel_position(EST_ChannelType type, int offset) const
{ 
    if (p_map!=0)
    {
      int p = (*p_map)(type);
      return (p!= NO_SUCH_CHANNEL)?(p+offset): NO_SUCH_CHANNEL;
    }
    return channel_position(EST_default_channel_names.name(type), offset);
}

float &EST_Track::a(int i, EST_ChannelType type, int offset)
{ 
    short c = NO_SUCH_CHANNEL;
    
    if (p_map!=0 && ((c = p_map->get(type)) != NO_SUCH_CHANNEL))
      return p_values.a_no_check(i, c+offset);
    else
    {
      cerr << "no channel '" << EST_default_channel_names.name(type) << "' = " << (int)type << "\n";
    }
    
    return *(p_values.error_return);
}

EST_Track::IPointer_f::IPointer_f()
{
  frame = new EST_Track();
}

EST_Track::IPointer_f::IPointer_f(const IPointer_f &p)
{
  frame=new EST_Track(*(p.frame));
}

EST_Track::IPointer_f::~IPointer_f()
{
  if (frame != NULL)
    {
      delete frame;
      frame=NULL;
    }
}


#if defined(INSTANTIATE_TEMPLATES)

Instantiate_TIterator_T(EST_Track, EST_Track::IPointer_f, EST_Track, Track_itt)

#endif

Generated by  Doxygen 1.6.0   Back to index