kaldi-holder.cc
Go to the documentation of this file.
1 // util/kaldi-holder.cc
2 
3 // Copyright 2009-2011 Microsoft Corporation
4 // 2016 Xiaohui Zhang
5 
6 // See ../../COPYING for clarification regarding multiple authors
7 //
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 //
12 // http://www.apache.org/licenses/LICENSE-2.0
13 //
14 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 // MERCHANTABLITY OR NON-INFRINGEMENT.
18 // See the Apache 2 License for the specific language governing permissions and
19 // limitations under the License.
20 
21 #include "util/kaldi-holder.h"
22 #include "matrix/kaldi-matrix.h"
23 
24 namespace kaldi {
25 
26 // Parse matrix range specifier in form r1:r2,c1:c2
27 // where any of those four numbers can be missing. In those
28 // cases, the missing number is set either to 0 (for r1 or c1)
29 // or the value of parameter rows -1 or columns -1 (which
30 // represent the dimensions of the original matrix) for missing
31 // r2 or c2, respectively.
32 // Examples of valid ranges: 0:39,: or :,:3 or :,5:10
33 bool ParseMatrixRangeSpecifier(const std::string &range,
34  const int rows, const int cols,
35  std::vector<int32> *row_range,
36  std::vector<int32> *col_range) {
37  if (range.empty()) {
38  KALDI_ERR << "Empty range specifier.";
39  return false;
40  }
41  std::vector<std::string> splits;
42  SplitStringToVector(range, ",", false, &splits);
43  if (!((splits.size() == 1 && !splits[0].empty()) ||
44  (splits.size() == 2 && !splits[0].empty() && !splits[1].empty()))) {
45  KALDI_ERR << "Invalid range specifier for matrix: " << range;
46  return false;
47  }
48 
49  bool status = true;
50 
51  if (splits[0] != ":")
52  status = SplitStringToIntegers(splits[0], ":", false, row_range);
53 
54  if (splits.size() == 2 && splits[1] != ":") {
55  status = status && SplitStringToIntegers(splits[1], ":", false, col_range);
56  }
57  if (row_range->size() == 0) {
58  row_range->push_back(0);
59  row_range->push_back(rows - 1);
60  }
61  if (col_range->size() == 0) {
62  col_range->push_back(0);
63  col_range->push_back(cols - 1);
64  }
65 
66  // Length tolerance of 3 -- 2 to account for edge effects when
67  // frame-length is 25ms and frame-shift is 10ms, and 1 for rounding effects
68  // since segments are usually retained up to 2 decimal places.
69  int32 length_tolerance = 3;
70  if (!(status && row_range->size() == 2 && col_range->size() == 2 &&
71  row_range->at(0) >= 0 && row_range->at(0) <= row_range->at(1) &&
72  row_range->at(1) < rows + length_tolerance &&
73  col_range->at(0) >=0 &&
74  col_range->at(0) <= col_range->at(1) && col_range->at(1) < cols)) {
75  KALDI_ERR << "Invalid range specifier: " << range
76  << " for matrix of size " << rows
77  << "x" << cols;
78  return false;
79  }
80 
81  if (row_range->at(1) >= rows)
82  KALDI_WARN << "Row range " << row_range->at(0) << ":" << row_range->at(1)
83  << " goes beyond the number of rows of the "
84  << "matrix " << rows;
85  return status;
86 }
87 
88 bool ExtractObjectRange(const GeneralMatrix &input, const std::string &range,
89  GeneralMatrix *output) {
90  // We just inspect input's type and forward to the correct implementation
91  // if available. For kSparseMatrix, we do just fairly inefficient conversion
92  // to a full matrix.
93  Matrix<BaseFloat> output_mat;
94  if (input.Type() == kFullMatrix) {
95  const Matrix<BaseFloat> &in = input.GetFullMatrix();
96  ExtractObjectRange(in, range, &output_mat);
97  } else if (input.Type() == kCompressedMatrix) {
98  const CompressedMatrix &in = input.GetCompressedMatrix();
99  ExtractObjectRange(in, range, &output_mat);
100  } else {
101  KALDI_ASSERT(input.Type() == kSparseMatrix);
102  // NOTE: this is fairly inefficient, so if this happens to be bottleneck
103  // it should be re-implemented more efficiently.
104  Matrix<BaseFloat> input_mat;
105  input.GetMatrix(&input_mat);
106  ExtractObjectRange(input_mat, range, &output_mat);
107  }
108  output->Clear();
109  output->SwapFullMatrix(&output_mat);
110  return true;
111 }
112 
113 template<class Real>
114 bool ExtractObjectRange(const CompressedMatrix &input, const std::string &range,
115  Matrix<Real> *output) {
116  std::vector<int32> row_range, col_range;
117 
118  if (!ParseMatrixRangeSpecifier(range, input.NumRows(), input.NumCols(),
119  &row_range, &col_range)) {
120  KALDI_ERR << "Could not parse range specifier \"" << range << "\".";
121  }
122 
123  int32 row_size = std::min(row_range[1], input.NumRows() - 1)
124  - row_range[0] + 1,
125  col_size = col_range[1] - col_range[0] + 1;
126 
127  output->Resize(row_size, col_size, kUndefined);
128  input.CopyToMat(row_range[0], col_range[0], output);
129  return true;
130 }
131 
132 // template instantiation
133 template bool ExtractObjectRange(const CompressedMatrix &, const std::string &,
134  Matrix<float> *);
135 template bool ExtractObjectRange(const CompressedMatrix &, const std::string &,
136  Matrix<double> *);
137 
138 template<class Real>
139 bool ExtractObjectRange(const Matrix<Real> &input, const std::string &range,
140  Matrix<Real> *output) {
141  std::vector<int32> row_range, col_range;
142 
143  if (!ParseMatrixRangeSpecifier(range, input.NumRows(), input.NumCols(),
144  &row_range, &col_range)) {
145  KALDI_ERR << "Could not parse range specifier \"" << range << "\".";
146  }
147 
148  int32 row_size = std::min(row_range[1], input.NumRows() - 1)
149  - row_range[0] + 1,
150  col_size = col_range[1] - col_range[0] + 1;
151  output->Resize(row_size, col_size, kUndefined);
152  output->CopyFromMat(input.Range(row_range[0], row_size,
153  col_range[0], col_size));
154  return true;
155 }
156 
157 // template instantiation
158 template bool ExtractObjectRange(const Matrix<double> &, const std::string &,
159  Matrix<double> *);
160 template bool ExtractObjectRange(const Matrix<float> &, const std::string &,
161  Matrix<float> *);
162 
163 template<class Real>
164 bool ExtractObjectRange(const Vector<Real> &input, const std::string &range,
165  Vector<Real> *output) {
166  if (range.empty()) {
167  KALDI_ERR << "Empty range specifier.";
168  return false;
169  }
170  std::vector<std::string> splits;
171  SplitStringToVector(range, ",", false, &splits);
172  if (!((splits.size() == 1 && !splits[0].empty()))) {
173  KALDI_ERR << "Invalid range specifier for vector: " << range;
174  return false;
175  }
176  std::vector<int32> index_range;
177  bool status = true;
178  if (splits[0] != ":")
179  status = SplitStringToIntegers(splits[0], ":", false, &index_range);
180 
181  if (index_range.size() == 0) {
182  index_range.push_back(0);
183  index_range.push_back(input.Dim() - 1);
184  }
185 
186  // Length tolerance of 3 -- 2 to account for edge effects when
187  // frame-length is 25ms and frame-shift is 10ms, and 1 for rounding effects
188  // since segments are usually retained up to 2 decimal places.
189  int32 length_tolerance = 3;
190  if (!(status && index_range.size() == 2 &&
191  index_range[0] >= 0 && index_range[0] <= index_range[1] &&
192  index_range[1] < input.Dim() + length_tolerance)) {
193  KALDI_ERR << "Invalid range specifier: " << range
194  << " for vector of size " << input.Dim();
195  return false;
196  }
197 
198  if (index_range[1] >= input.Dim())
199  KALDI_WARN << "Range " << index_range[0] << ":" << index_range[1]
200  << " goes beyond the vector dimension " << input.Dim();
201  int32 size = std::min(index_range[1], input.Dim() - 1) - index_range[0] + 1;
202  output->Resize(size, kUndefined);
203  output->CopyFromVec(input.Range(index_range[0], size));
204  return true;
205 }
206 
207 // template instantiation
208 template bool ExtractObjectRange(const Vector<double> &, const std::string &,
209  Vector<double> *);
210 template bool ExtractObjectRange(const Vector<float> &, const std::string &,
211  Vector<float> *);
212 
213 bool ExtractRangeSpecifier(const std::string &rxfilename_with_range,
214  std::string *data_rxfilename,
215  std::string *range) {
216  if (rxfilename_with_range.empty() ||
217  rxfilename_with_range[rxfilename_with_range.size()-1] != ']')
218  KALDI_ERR << "ExtractRangeRspecifier called wrongly.";
219  std::vector<std::string> splits;
220  SplitStringToVector(rxfilename_with_range, "[", false, &splits);
221  if (splits.size() == 2 && !splits[0].empty() && splits[1].size() > 1) {
222  *data_rxfilename = splits[0];
223  range->assign(splits[1], 0, splits[1].size()-1);
224  return true;
225  }
226  return false;
227 }
228 
229 } // end namespace kaldi
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
This class is a wrapper that enables you to store a matrix in one of three forms: either as a Matrix<...
void GetMatrix(Matrix< BaseFloat > *mat) const
Outputs the contents as a matrix.
MatrixIndexT NumCols() const
Returns number of columns (or zero for empty matrix).
Definition: kaldi-matrix.h:67
bool SplitStringToIntegers(const std::string &full, const char *delim, bool omit_empty_strings, std::vector< I > *out)
Split a string (e.g.
Definition: text-utils.h:68
const CompressedMatrix & GetCompressedMatrix() const
Returns the contents as a compressed matrix.
kaldi::int32 int32
const Matrix< BaseFloat > & GetFullMatrix() const
Returns the contents as a Matrix<BaseFloat>.
void Resize(MatrixIndexT length, MatrixResizeType resize_type=kSetZero)
Set vector to a specified size (can be zero).
void CopyFromMat(const MatrixBase< OtherReal > &M, MatrixTransposeType trans=kNoTrans)
Copy given matrix. (no resize is done).
void CopyFromVec(const VectorBase< Real > &v)
Copy data from another vector (must match own size).
bool ExtractObjectRange(const GeneralMatrix &input, const std::string &range, GeneralMatrix *output)
GeneralMatrix is always of type BaseFloat.
Definition: kaldi-holder.cc:88
GeneralMatrixType Type() const
Returns the type of the matrix: kSparseMatrix, kCompressedMatrix or kFullMatrix.
void SplitStringToVector(const std::string &full, const char *delim, bool omit_empty_strings, std::vector< std::string > *out)
Split a string using any of the single character delimiters.
Definition: text-utils.cc:63
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_WARN
Definition: kaldi-error.h:150
MatrixIndexT Dim() const
Returns the dimension of the vector.
Definition: kaldi-vector.h:64
A class representing a vector.
Definition: kaldi-vector.h:406
MatrixIndexT NumRows() const
Returns number of rows (or zero for emtpy matrix).
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
MatrixIndexT NumRows() const
Returns number of rows (or zero for empty matrix).
Definition: kaldi-matrix.h:64
void SwapFullMatrix(Matrix< BaseFloat > *mat)
Swaps the with the given Matrix.
SubMatrix< Real > Range(const MatrixIndexT row_offset, const MatrixIndexT num_rows, const MatrixIndexT col_offset, const MatrixIndexT num_cols) const
Return a sub-part of matrix.
Definition: kaldi-matrix.h:202
void Resize(const MatrixIndexT r, const MatrixIndexT c, MatrixResizeType resize_type=kSetZero, MatrixStrideType stride_type=kDefaultStride)
Sets matrix to a specified size (zero is OK as long as both r and c are zero).
bool ExtractRangeSpecifier(const std::string &rxfilename_with_range, std::string *data_rxfilename, std::string *range)
MatrixIndexT NumCols() const
Returns number of columns (or zero for emtpy matrix).
void CopyToMat(MatrixBase< Real > *mat, MatrixTransposeType trans=kNoTrans) const
Copies contents to matrix.
bool ParseMatrixRangeSpecifier(const std::string &range, const int rows, const int cols, std::vector< int32 > *row_range, std::vector< int32 > *col_range)
Definition: kaldi-holder.cc:33
SubVector< Real > Range(const MatrixIndexT o, const MatrixIndexT l)
Returns a sub-vector of a vector (a range of elements).
Definition: kaldi-vector.h:94