feature-sdc-test.cc
Go to the documentation of this file.
1 // feat/feature-sdc-test.cc
2 
3 // Copyright 2014 David Snyder
4 
5 // See ../../COPYING for clarification regarding multiple authors
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 // http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
15 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
16 // MERCHANTABLITY OR NON-INFRINGEMENT.
17 // See the Apache 2 License for the specific language governing permissions and
18 // limitations under the License.
19 
20 
21 #include <iostream>
22 
23 #include "feat/feature-mfcc.h"
24 #include "base/kaldi-math.h"
26 #include "feat/wave-reader.h"
27 
28 using namespace kaldi;
29 
30 static void UnitTestCompareWithDeltaFeatures(Matrix<BaseFloat> &raw_features, int32 window) {
31  std::cout << "=== UnitTestSDCCompareWithDeltaFeatures() ===\n";
32  DeltaFeaturesOptions deltas_opts;
33  deltas_opts.window = window;
34  ShiftedDeltaFeaturesOptions shifted_deltas_opts;
35  shifted_deltas_opts.window = window;
36  Matrix<BaseFloat> deltas_features;
37  Matrix<BaseFloat> shifted_deltas_features;
38  ComputeDeltas(deltas_opts,
39  raw_features,
40  &deltas_features);
41  ComputeShiftedDeltas(shifted_deltas_opts,
42  raw_features,
43  &shifted_deltas_features);
44 
45  int32 dd_num_rows = deltas_features.NumRows();
46  int32 sdc_num_rows = shifted_deltas_features.NumRows();
47  int32 num_features = raw_features.NumCols();
48 
49  // Number of rows will be equal, but not
50  // columns, in general.
51  KALDI_ASSERT(dd_num_rows == sdc_num_rows);
52 
53  // The raw mfcc features and the first first-order delta features
54  // will be identical in the SDC and Delta-Deltas.
55  for (int32 i = 0; i < dd_num_rows; i++) {
56  for (int32 j = 0; j < 2 * num_features; j++) {
57  BaseFloat a = deltas_features(i, j), b = shifted_deltas_features(i, j);
58  KALDI_ASSERT(std::abs(b - a) < 0.001);
59  }
60  }
61 }
62 
63 static void UnitTestParams(Matrix<BaseFloat> &raw_features, int32 window,
64  int32 shift, int32 n_blocks) {
65  std::cout << "=== UnitTestSDCParams() ===\n";
66  ShiftedDeltaFeaturesOptions shifted_deltas_opts;
67  shifted_deltas_opts.window = window;
68  shifted_deltas_opts.num_blocks = n_blocks;
69  shifted_deltas_opts.block_shift = shift;
70 
71  Matrix<BaseFloat> shifted_deltas_features;
72  ComputeShiftedDeltas(shifted_deltas_opts,
73  raw_features,
74  &shifted_deltas_features);
75 
76  int32 raw_num_cols = raw_features.NumCols();
77  int32 sdc_num_rows = shifted_deltas_features.NumRows();
78  int32 sdc_num_cols = shifted_deltas_features.NumCols();
79 
80  KALDI_ASSERT(sdc_num_cols == raw_num_cols * (n_blocks + 1));
81 
82  /* For every coefficient in the raw feature vector a
83  delta is calculated and appended to the new feature vector,
84  as is done normally in a delta-deltas computation.
85  In addition, n_blocks delta in advance are also appended.
86  Somewhere in advance of the current position, say at
87  t + l these additional delta are the first order deltas
88  at that position (t + l). The following code works out a
89  mapping from these additional deltas to where they would
90  appear in a delta-deltas computation and verfies these
91  values' equality. */
92  for (int32 i = 0; i < sdc_num_rows; i++) {
93  for (int32 j = 2 * raw_num_cols; j < sdc_num_cols; j += raw_num_cols) {
94  for (int32 k = 0; k < raw_num_cols; k++) {
95  int32 row = i + (j/raw_num_cols - 1) * shift;
96  if (row < sdc_num_rows) {
97  BaseFloat a = shifted_deltas_features(i, j + k);
98  BaseFloat b = shifted_deltas_features(row, raw_num_cols + k);
99  KALDI_ASSERT(std::abs(a - b) < 0.001);
100  }
101  }
102  }
103  }
104 }
105 
106 static void UnitTestEndEffects(Matrix<BaseFloat> &raw_features, int32 window,
107  int32 shift, int32 n_blocks) {
108  std::cout << "=== UnitTestSDCEndEffects() ===\n";
109  ShiftedDeltaFeaturesOptions shifted_deltas_opts;
110  shifted_deltas_opts.window = window;
111  shifted_deltas_opts.num_blocks = n_blocks;
112  shifted_deltas_opts.block_shift = shift;
113 
114  Matrix<BaseFloat> shifted_deltas_features;
115  ComputeShiftedDeltas(shifted_deltas_opts,
116  raw_features,
117  &shifted_deltas_features);
118  int32 raw_num_cols = raw_features.NumCols();
119  int32 sdc_num_rows = shifted_deltas_features.NumRows();
120  int32 sdc_num_cols = shifted_deltas_features.NumCols();
121 
122  // If the entire window is out-of-bounds the delta should be zero.
123  for (int32 i = sdc_num_rows - n_blocks + 1; i < sdc_num_rows; i++) {
124  for (int32 j = 2 * raw_num_cols; j < sdc_num_cols; j += raw_num_cols) {
125  for (int32 k = 0; k < raw_num_cols; k++) {
126  if (i + (j/raw_num_cols - 1) * shift - window/2 > sdc_num_rows)
127  KALDI_ASSERT(shifted_deltas_features(i, j + k) <= 0.00001);
128  }
129  }
130  }
131 }
132 
133 int main() {
134  std::ifstream is("test_data/test.wav", std::ios_base::binary);
135  WaveData wave;
136  wave.Read(is);
137  KALDI_ASSERT(wave.Data().NumRows() == 1);
138  SubVector<BaseFloat> waveform(wave.Data(), 0);
139 
140  // mfcc with default configuration...
141  MfccOptions op;
142  op.frame_opts.dither = 0.0;
143  op.frame_opts.preemph_coeff = 0.0;
144  op.frame_opts.window_type = "hamming";
145  op.frame_opts.remove_dc_offset = false;
146  op.frame_opts.round_to_power_of_two = true;
147  op.mel_opts.low_freq = 0.0;
148  op.use_energy = false;
149  Mfcc mfcc(op);
150  Matrix<BaseFloat> raw_features;
151  mfcc.Compute(waveform, 1.0, &raw_features);
152 
153  try {
154  for (int32 window = 1; window < 4; window++) {
155  UnitTestCompareWithDeltaFeatures(raw_features, window);
156  for (int32 shift = 1; shift < 10; shift++) {
157  for (int32 n_blocks = 1; n_blocks < 20; n_blocks += 3) {
158  UnitTestParams(raw_features, window, shift, n_blocks);
159  UnitTestEndEffects(raw_features, window, shift, n_blocks);
160  }
161  }
162  }
163  return 0;
164  } catch (const std::exception &e) {
165  static_cast<void>(e);
166  return 1;
167  }
168 
169 }
170 
void Read(std::istream &is)
Read() will throw on error.
Definition: wave-reader.cc:272
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
void Compute(const VectorBase< BaseFloat > &wave, BaseFloat vtln_warp, Matrix< BaseFloat > *output)
MatrixIndexT NumCols() const
Returns number of columns (or zero for empty matrix).
Definition: kaldi-matrix.h:67
MfccOptions contains basic options for computing MFCC features.
Definition: feature-mfcc.h:38
static void UnitTestParams(Matrix< BaseFloat > &raw_features, int32 window, int32 shift, int32 n_blocks)
kaldi::int32 int32
const Matrix< BaseFloat > & Data() const
Definition: wave-reader.h:124
float BaseFloat
Definition: kaldi-types.h:29
static void UnitTestCompareWithDeltaFeatures(Matrix< BaseFloat > &raw_features, int32 window)
FrameExtractionOptions frame_opts
Definition: feature-mfcc.h:39
void ComputeShiftedDeltas(const ShiftedDeltaFeaturesOptions &delta_opts, const MatrixBase< BaseFloat > &input_features, Matrix< BaseFloat > *output_features)
This class&#39;s purpose is to read in Wave files.
Definition: wave-reader.h:106
int main()
#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 ComputeDeltas(const DeltaFeaturesOptions &delta_opts, const MatrixBase< BaseFloat > &input_features, Matrix< BaseFloat > *output_features)
static void UnitTestEndEffects(Matrix< BaseFloat > &raw_features, int32 window, int32 shift, int32 n_blocks)
This templated class is intended for offline feature extraction, i.e.
Represents a non-allocating general vector which can be defined as a sub-vector of higher-level vecto...
Definition: kaldi-vector.h:501