CLAM-Development  1.4.0
CepstralTransform.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #include "CepstralTransform.hxx"
23 #include "OSDefines.hxx"
24 #include "Assert.hxx"
25 #include "ProcessingFactory.hxx"
26 
27 namespace CLAM
28 {
29 namespace Hidden
30 {
31  static const char* metadata[] = {
32  "key", "CepstralTransform",
33  "category", "Analysis",
34  "description", "CepstralTransform",
35  0
36  };
37  static FactoryRegistrator<ProcessingFactory, CepstralTransform> reg = metadata;
38 }
39 
41 {
42  AddAll();
43  UpdateData();
44  SetNumMelCoefficients(20);
45  SetNumCepstrumCoefficients(20);
46  SetUseBase10(false);
47 }
48 
50  : mIn("Mel Spectrum", this)
51  , mOut("Mel Cepstrum", this)
52 {
54 }
55 
57  : mIn("Mel Spectrum", this)
58  , mOut("Mel Cepstrum", this)
59 {
60  Configure( cfg );
61 }
62 
64 {
65  CopyAsConcreteConfig( mConfig, cfg );
66 
67  mLogBuffer.Resize(mConfig.GetNumMelCoefficients());
68  mLogBuffer.SetSize(mConfig.GetNumMelCoefficients());
69 
70  return true;
71 }
72 
74 {
75  const MelSpectrum & spectrum = mIn.GetData();
76  MelCepstrum & cepstrum = mOut.GetData();
77  bool ok = Do(spectrum, cepstrum);
78  mIn.Consume();
79  mOut.Produce();
80  return ok;
81 }
82 
84 {
85  return true;
86 }
87 
88 bool CepstralTransform::Do( const MelSpectrum& melSpec, MelCepstrum& melCeps )
89 {
90  if ( !AbleToExecute() ) return false; // object was disabled
91 
92  const DataArray& melCoeffs = melSpec.GetCoefficients();
93  DataArray& cepstrumCoeffs = melCeps.GetCoefficients();
94  const TSize numMelCoefficients = melCoeffs.Size();
95  const TSize numCepstrumCoeffs = mConfig.GetNumCepstrumCoefficients();
96 
97  if ( cepstrumCoeffs.Size() < numCepstrumCoeffs )
98  {
99  cepstrumCoeffs.Resize(numCepstrumCoeffs);
100  cepstrumCoeffs.SetSize(numCepstrumCoeffs);
101  }
102 
103  melCeps.SetCenterTime(melSpec.GetCenterTime());
104  melCeps.SetLowCutoff(melSpec.GetLowCutoff());
105  melCeps.SetHighCutoff(melSpec.GetHighCutoff());
106 
107  /* Take the logarithm of the Mel spectrum. NOTE: What is the
108  significance of log vs. log10? */
109  const TData melFloor = 1.0;
110  const bool useBase10 = mConfig.GetUseBase10();
111 
112  if ( mLogBuffer.Size()!=numMelCoefficients)
113  {
114  // TODO: This has realtime penalty
115  mLogBuffer.Resize(numMelCoefficients);
116  mLogBuffer.SetSize(numMelCoefficients);
117  }
118  for (TIndex i=0; i<numMelCoefficients; i++) {
119  if (melCoeffs[i] < melFloor)
120  mLogBuffer[i] = useBase10 ? log10(melFloor) : log(melFloor);
121  else
122  mLogBuffer[i] = useBase10 ? log10(melCoeffs[i]) : log(melCoeffs[i]);
123  }
124 
125  /* Take the DCT of the logarithm. */
126  const TData piord = PI / (TData)numMelCoefficients;
127  const TData scale = sqrt(2.0/(TData)numMelCoefficients);
128 
129  // Compute N-1 last coefficients.
130  TData freq = 0;
131  for (TIndex i=1; i<numCepstrumCoeffs; i++)
132  {
133  freq = i*piord;
134  cepstrumCoeffs[i] = 0.0;
135  for (TIndex j=0; j<numMelCoefficients; j++)
136  cepstrumCoeffs[i] += mLogBuffer[j] * cos(freq*(j+1 - 0.5));
137  cepstrumCoeffs[i] *= scale;
138  }
139 
140  // Compute first coefficient.
141  for (TIndex j=0; j<numMelCoefficients; j++)
142  cepstrumCoeffs[0] += mLogBuffer[j];
143  cepstrumCoeffs[0] *= scale;
144 
145 
146  /* NOTE: How about implementing cepstral liftering from HTK? Probably not. */
147 
148  return true;
149 }
150 
151 }
152