Loading...
Searching...
No Matches
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>
#include <iostream>
#include <cmath>
#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";
EST_Track::EST_Track()
{
default_vals();
}
EST_Track::EST_Track(const EST_Track &a)
{
default_vals();
copy(a);
}
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);
}
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();
}
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;
}
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);
}
*/
void EST_Track::set_channel_name(const EST_String &fn, int i)
{
p_channel_names[i] = fn;
}
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;
}
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);
}
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 = p->next())
{
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);
}
}
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 = p->next(), ++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;
}
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 = p->next(), ++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();
float old_end = end();
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(j, k) = a(i, k);
p_times[j] = old_end + 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(k, j) = a(k, i);
return *this;
}
EST_Track &EST_Track::operator=(const EST_Track& a)
{
copy(a);
return *this;
}
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;
}
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)
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;
}
int EST_Track::index(float x) const
{
if (equal_space())
{
float s = shift();
int f = (int)( (x-t(0))/s+0.5 ); //don't assume track starts at t=0.0
if (f<0)
f=0;
else if (f>= num_frames())
f=num_frames()-1;
return f;
}
else if (num_frames() > 1) //if single frame, return that index (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;
}
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;
}
}
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 supplied to change from one
type to another. Not all conversions are currently
supported however.
*/
float EST_Track::end() const
{
if (num_frames() == 0)
return 0.0;
else
return (p_times(prev_non_break(num_frames())));
}
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));
}
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 */
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 */
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;
}
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();
}
}
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
}
void EST_Track::fill_time( float t, int start )
{
unsigned int nframes = num_frames();
for( unsigned int i=0; i<nframes; ++i )
p_times.a_no_check(i) = t * (float) (i + start);
}
void EST_Track::fill_time( float t, float startt )
{
unsigned int nframes = num_frames();
for( unsigned int i=0; i<nframes; ++i )
p_times.a_no_check(i) = startt + (t * (float)i);
}
void EST_Track::fill_time( const EST_Track &t )
{
unsigned int nframes = num_frames();
for( unsigned int i=0; i<nframes; ++i )
p_times.a_no_check(i) = t.t(i);
}
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;
}
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);
}
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
}
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);
}
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);
}
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);
}
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;
}
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;
}
void EST_Track::copy_sub_track_out( EST_Track &st, const EST_FVector& frame_times ) const
{
int f_len = frame_times.length();
int nchans = num_channels();
st.resize( f_len, nchans );
for( int i=0; i<f_len; ++i ){
int source_index = index(frame_times(i));
st.p_times.a(i) = p_times.a( source_index );
st.p_is_val.a(i) = p_is_val.a( source_index );
for( int c=0; c<nchans; c++ )
st.p_values.a(i,c) = p_values.a(source_index,c);
}
st.copy_setup( *this );
st.set_equal_space( false ); //might not be true, but it's a better default
// st.p_aux = p_aux;
// st.p_aux_names = p_aux_names;
}
void EST_Track::copy_sub_track_out( EST_Track &st, const EST_IVector& frame_indices ) const
{
int f_len = frame_indices.length();
int nchans = num_channels();
st.resize( f_len, nchans );
int last_index = num_frames()-1;
for( int i=0; i<f_len; ++i ){
int source_index = frame_indices(i);
if( source_index <= last_index ){
st.p_times.a(i) = p_times.a( source_index );
st.p_is_val.a(i) = p_is_val.a( source_index );
for( int c=0; c<nchans; c++ )
st.p_values.a(i,c) = p_values.a(source_index,c);
}
}
st.copy_setup( *this );
st.set_equal_space( false ); //might not be true, but it's a better default
// st.p_aux = p_aux;
// st.p_aux_names = p_aux_names;
}
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);
}
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);
}
EST_read_status EST_Track::load(EST_TokenStream &ts, float ishift, float startt)
{
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, startt);
if (stat != read_format_error)
{
if (stat == read_ok)
set_file_type(t);
break;
}
}
return stat;
}
EST_read_status EST_Track::load(const EST_String filename, float ishift, float startt)
{
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, startt);
if (stat == read_ok)
{
set_file_type(t);
break;
}
else if (stat == read_error)
break;
}
return stat;
}
EST_read_status EST_Track::load(const EST_String filename, const EST_String type, float ishift, float startt)
{
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, startt);
}
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
EST_FMatrix
Definition EST_FMatrix.h:56
EST_FVector
Definition EST_FMatrix.h:114
EST_String
Definition EST_String.h:70
EST_String::before
EST_String before(int pos, int len=0) const
Part before position.
Definition EST_String.h:286
EST_String::contains
int contains(const char *s, int pos=-1) const
Does it contain this substring?
Definition EST_String.h:375
EST_String::after
EST_String after(int pos, int len=1) const
Part after pos+len.
Definition EST_String.h:318
EST_String::matches
int matches(const char *e, int pos=0) const
Exactly match this string?
Definition EST_String.cc:652
EST_TList::append
void append(const T &item)
add item onto end of list
Definition EST_TList.h:191
EST_TMatrix::a_no_check
INLINE const T & a_no_check(int row, int col) const
const access with no bounds check, care recommend
Definition EST_TMatrix.h:184
EST_TSimpleMatrix::resize
void resize(int rows, int cols, int set=1)
resize matrix
Definition EST_TSimpleMatrix.cc:86
EST_TSimpleVector::resize
void resize(int n, int set=1)
resize vector
Definition EST_TSimpleVector.cc:70
EST_TVector::resize
void resize(int n, int set=1)
Definition EST_TVector.cc:196
EST_TVector::length
INLINE int length() const
number of items in vector.
Definition EST_TVector.h:252
EST_TVector::error_return
static T * error_return
Definition EST_TVector.h:230
EST_TVector::fill
void fill(const T &v)
Fill entire array will value <parameter>v</parameter>.
Definition EST_TVector.cc:105
EST_TokenStream
Definition EST_Token.h:235
EST_TrackMap
Definition EST_TrackMap.h:63
EST_TrackMap::P
EST_THandle< EST_TrackMap, EST_TrackMap > P
Table of type to position pairs.
Definition EST_TrackMap.h:82
EST_Track::IPointer_f
Definition EST_Track.h:745
EST_Track
Definition EST_Track.h:89
EST_Track::copy_sub_track
void copy_sub_track(EST_Track &st, int start_frame=0, int nframes=EST_ALL, int start_chan=0, int nchans=EST_ALL) const
Definition EST_Track.cc:1136
EST_Track::channel_position
int channel_position(const char *name, int offset=0) const
Definition EST_Track.cc:392
EST_Track::set_channel_name
void set_channel_name(const EST_String &name, int channel)
set the name of the channel.
Definition EST_Track.cc:166
EST_Track::load
EST_read_status load(const EST_String name, float ishift=0.0, float startt=0.0)
Definition EST_Track.cc:1309
EST_Track::track_break
int track_break(int i) const
return true if frame i is a break
Definition EST_Track.h:633
EST_Track::t
float & t(int i=0)
return time position of frame i
Definition EST_Track.h:477
EST_Track::val
int val(int i) const
return true if frame i is a value
Definition EST_Track.cc:539
EST_Track::save
EST_write_status save(const EST_String name, const EST_String EST_filetype="")
Definition EST_Track.cc:1230
EST_Track::a
float & a(int i, int c=0)
Definition EST_Track.cc:1022
EST_Track::num_aux_channels
int num_aux_channels() const
return number of auxiliary channels in track
Definition EST_Track.h:659
EST_Track::next_non_break
int next_non_break(int i) const
Definition EST_Track.cc:629
EST_Track::copy_setup
void copy_setup(const EST_Track &a)
copy everything but data
Definition EST_Track.cc:202
EST_Track::~EST_Track
~EST_Track()
default destructor
Definition EST_Track.cc:95
EST_Track::index_below
int index_below(float x) const
return the frame index before time t
Definition EST_Track.cc:518
EST_Track::sub_track
void sub_track(EST_Track &st, int start_frame=0, int nframes=EST_ALL, int start_chan=0, int nchans=EST_ALL)
Definition EST_Track.cc:1097
EST_Track::EST_Track
EST_Track()
Default constructor.
Definition EST_Track.cc:55
EST_Track::empty
int empty() const
returns true if no values are set in the frame
Definition EST_Track.cc:1035
EST_Track::equal_space
bool equal_space() const
return true if track has equal (i.e. fixed) frame spacing *‍/
Definition EST_Track.h:669
EST_Track::start
float start() const
return time of first value in track
Definition EST_Track.cc:591
EST_Track::set_value
void set_value(int i)
set frame i to be a value
Definition EST_Track.cc:131
EST_Track::resize_aux
void resize_aux(EST_StrList &map, bool preserve=1)
Definition EST_Track.cc:311
EST_Track::num_channels
int num_channels() const
return number of channels in track
Definition EST_Track.h:656
EST_Track::num_frames
int num_frames() const
return number of frames in track
Definition EST_Track.h:650
EST_Track::end
float end() const
return time of last value in track
Definition EST_Track.cc:584
EST_Track::index
int index(float t) const
return the frame index nearest time t
Definition EST_Track.cc:470
EST_Track::a_no_check
float & a_no_check(int i, int c=0)
Definition EST_Track.h:419
EST_Track::channel
void channel(EST_FVector &cv, int n, int startf=0, int nf=EST_ALL)
Definition EST_Track.h:214
EST_Track::change_type
void change_type(float nshift, bool single_break)
REDO.
Definition EST_Track.cc:653
EST_Track::sample
void sample(float shift)
Definition EST_Track.cc:671
EST_Track::resize
void resize(int num_frames, int num_channels, bool preserve=1)
Definition EST_Track.cc:211
EST_Track::a
float & a(float t, int c=0, EST_InterpType interp=it_nearest)
Definition EST_Track.cc:437
EST_Track::name
EST_String name() const
name of track - redundant use access to features
Definition EST_Track.h:195
EST_Track::fill_time
void fill_time(float t, int start=1)
Definition EST_Track.cc:786
EST_Track::set_aux_channel_name
void set_aux_channel_name(const EST_String &name, int channel)
set the name of the auxiliary channel.
Definition EST_Track.cc:171
EST_Track::shift
float shift() const
Definition EST_Track.cc:599
EST_Track::prev_non_break
int prev_non_break(int i) const
Definition EST_Track.cc:644
EST_Track::frame
void frame(EST_FVector &fv, int n, int startf=0, int nf=EST_ALL)
Definition EST_Track.h:209
EST_Track::rm_excess_breaks
void rm_excess_breaks()
Definition EST_Track.cc:810
EST_Track::set_break
void set_break(int i)
set frame i to be a break
Definition EST_Track.cc:122
EST_Track::single_break
bool single_break() const
Definition EST_Track.h:672
EST_Val
Definition EST_Val.h:70