Audacity  3.0.3
FormatClassifier.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  FormatClassifier.cpp
6 
7  Philipp Sibler
8 
9 ******************************************************************//*******************************************************************/
20 #include "FormatClassifier.h"
21 
22 #include <stdint.h>
23 #include <cmath>
24 #include <cfloat>
25 #include <vector>
26 #include <cstdio>
27 
28 #include <wx/defs.h>
29 
30 #include "sndfile.h"
31 
32 FormatClassifier::FormatClassifier(const char* filename) :
33  mReader(filename),
34  mMeter(cSiglen)
35 {
36  // Define the classification classes
37  for ( auto endianness : {
40  } )
41  for ( auto format : {
48  } )
49  mClasses.push_back( { format, endianness } );
50 
51  // Build feature vectors
52  mMonoFeat = Floats{ mClasses.size() };
53  mStereoFeat = Floats{ mClasses.size() };
54 
55 #ifdef FORMATCLASSIFIER_SIGNAL_DEBUG
56  // Build a debug writer
57  char dfile [1024];
58  sprintf(dfile, "%s.sig", filename);
59  mpWriter = std::make_unique<DebugWriter>(dfile);
60 #endif
61 
62  // Run it
63  Run();
64 
65 #ifdef FORMATCLASSIFIER_SIGNAL_DEBUG
66  for (unsigned int n = 0; n < mClasses.size(); n++)
67  {
68  wxPrintf("Class [%i] Machine [%i]: Mono: %3.7f Stereo: %3.7f\n", mClasses[n].format, mClasses[n].endian, mMonoFeat[n], mStereoFeat[n]);
69  }
70 #endif
71 
72 }
73 
75 {
76 }
77 
79 {
80  return mResultFormat;
81 }
82 
84 {
85  int format = SF_FORMAT_RAW;
86 
87  switch(mResultFormat.format)
88  {
90  format |= SF_FORMAT_PCM_S8;
91  break;
93  format |= SF_FORMAT_PCM_16;
94  break;
96  format |= SF_FORMAT_PCM_32;
97  break;
99  format |= SF_FORMAT_PCM_U8;
100  break;
102  format |= SF_FORMAT_FLOAT;
103  break;
105  format |= SF_FORMAT_DOUBLE;
106  break;
107  default:
108  format |= SF_FORMAT_PCM_16;
109  break;
110  }
111 
112  switch(mResultFormat.endian)
113  {
115  format |= SF_ENDIAN_LITTLE;
116  break;
118  format |= SF_ENDIAN_BIG;
119  break;
120  }
121 
122  return format;
123 }
124 
126 {
127  return mResultChannels;
128 }
129 
131 {
132  // Calc the mono feature vector
133  for (unsigned int n = 0; n < mClasses.size(); n++)
134  {
135  // Read the signal
136  ReadSignal(mClasses[n], 1);
137 #ifdef FORMATCLASSIFIER_SIGNAL_DEBUG
138  mpWriter->WriteSignal(mSigBuffer, cSiglen);
139 #endif
140 
141  // Do some simple preprocessing
142  // Remove DC offset
143  float smean = Mean(mSigBuffer.get(), cSiglen);
144  Sub(mSigBuffer.get(), smean, cSiglen);
145  // Normalize to +- 1.0
146  Abs(mSigBuffer.get(), mAuxBuffer.get(), cSiglen);
147  float smax = Max(mAuxBuffer.get(), cSiglen);
148  Div(mSigBuffer.get(), smax, cSiglen);
149 
150  // Now actually fill the feature vector
151  // Low to high band power ratio
152  float pLo = mMeter.CalcPower(mSigBuffer.get(), 0.15f, 0.3f);
153  float pHi = mMeter.CalcPower(mSigBuffer.get(), 0.45f, 0.1f);
154  mMonoFeat[n] = pLo / pHi;
155  }
156 
157  // Calc the stereo feature vector
158  for (unsigned int n = 0; n < mClasses.size(); n++)
159  {
160  // Read the signal
161  ReadSignal(mClasses[n], 2);
162 #ifdef FORMATCLASSIFIER_SIGNAL_DEBUG
163  mpWriter->WriteSignal(mSigBuffer, cSiglen);
164 #endif
165 
166  // Do some simple preprocessing
167  // Remove DC offset
168  float smean = Mean(mSigBuffer.get(), cSiglen);
169  Sub(mSigBuffer.get(), smean, cSiglen);
170  // Normalize to +- 1.0
171  Abs(mSigBuffer.get(), mAuxBuffer.get(), cSiglen);
172  float smax = Max(mAuxBuffer.get(), cSiglen);
173  Div(mSigBuffer.get(), smax, cSiglen);
174 
175  // Now actually fill the feature vector
176  // Low to high band power ratio
177  float pLo = mMeter.CalcPower(mSigBuffer.get(), 0.15f, 0.3f);
178  float pHi = mMeter.CalcPower(mSigBuffer.get(), 0.45f, 0.1f);
179  mStereoFeat[n] = pLo / pHi;
180  }
181 
182  // Get the results
183  size_t midx, sidx;
184  float monoMax = Max(mMonoFeat.get(), mClasses.size(), &midx);
185  float stereoMax = Max(mStereoFeat.get(), mClasses.size(), &sidx);
186 
187  if (monoMax > stereoMax)
188  {
189  mResultChannels = 1;
190  mResultFormat = mClasses[midx];
191  }
192  else
193  {
194  mResultChannels = 2;
195  mResultFormat = mClasses[sidx];
196  }
197 
198 }
199 
201 {
202  size_t actRead = 0;
203  unsigned int n = 0;
204 
205  mReader.Reset();
206 
207  // Do a dummy read of 1024 bytes to skip potential header information
209 
210  do
211  {
212  actRead = mReader.ReadSamples(mRawBuffer.get(), cSiglen, stride, format.format, format.endian);
213 
214  if (n == 0)
215  {
217  }
218  else
219  {
220  if (actRead == cSiglen)
221  {
223 
224  // Integrate signals
225  Add(mSigBuffer.get(), mAuxBuffer.get(), cSiglen);
226 
227  // Do some dummy reads to break signal coherence
228  mReader.ReadSamples(mRawBuffer.get(), n + 1, stride, format.format, format.endian);
229  }
230  }
231 
232  n++;
233 
234  } while ((n < cNumInts) && (actRead == cSiglen));
235 
236 }
237 
239 {
240  switch(format.format)
241  {
243  ToFloat((int8_t*) in, out, cSiglen);
244  break;
246  ToFloat((int16_t*) in, out, cSiglen);
247  break;
249  ToFloat((int32_t*) in, out, cSiglen);
250  break;
252  ToFloat((uint8_t*) in, out, cSiglen);
253  break;
255  ToFloat((uint16_t*) in, out, cSiglen);
256  break;
258  ToFloat((uint32_t*) in, out, cSiglen);
259  break;
261  ToFloat((float*) in, out, cSiglen);
262  break;
264  ToFloat((double*) in, out, cSiglen);
265  break;
266  }
267 }
268 
269 void FormatClassifier::Add(float* in1, float* in2, size_t len)
270 {
271  for (unsigned int n = 0; n < len; n++)
272  {
273  in1[n] += in2[n];
274  }
275 }
276 
277 void FormatClassifier::Sub(float* in, float subt, size_t len)
278 {
279  for (unsigned int n = 0; n < len; n++)
280  {
281  in[n] -= subt;
282  }
283 }
284 
285 void FormatClassifier::Div(float* in, float div, size_t len)
286 {
287  for (unsigned int n = 0; n < len; n++)
288  {
289  in[n] /= div;
290  }
291 }
292 
293 
294 void FormatClassifier::Abs(float* in, float* out, size_t len)
295 {
296  for (unsigned int n = 0; n < len; n++)
297  {
298  if (in[n] < 0.0f)
299  {
300  out[n] = -in[n];
301  }
302  else
303  {
304  out[n] = in[n];
305  }
306  }
307 }
308 
309 float FormatClassifier::Mean(float* in, size_t len)
310 {
311  float mean = 0.0f;
312 
313  for (unsigned int n = 0; n < len; n++)
314  {
315  mean += in[n];
316  }
317 
318  mean /= len;
319 
320  return mean;
321 }
322 
323 float FormatClassifier::Max(float* in, size_t len)
324 {
325  size_t dummyidx;
326  return Max(in, len, &dummyidx);
327 }
328 
329 float FormatClassifier::Max(float* in, size_t len, size_t* maxidx)
330 {
331  float max = -FLT_MAX;
332  *maxidx = 0;
333 
334  for (unsigned int n = 0; n < len; n++)
335  {
336  if (in[n] > max)
337  {
338  max = in[n];
339  *maxidx = n;
340  }
341  }
342 
343  return max;
344 }
345 
346 template<class T> void FormatClassifier::ToFloat(T* in, float* out, size_t len)
347 {
348  for(unsigned int n = 0; n < len; n++)
349  {
350  out[n] = (float) in[n];
351  }
352 }
MachineEndianness::Little
@ Little
Definition: MultiFormatReader.h:22
FormatClassifier::Sub
void Sub(float *in, float subt, size_t len)
Definition: FormatClassifier.cpp:277
FormatClassifier::Abs
void Abs(float *in, float *out, size_t len)
Definition: FormatClassifier.cpp:294
FormatClassifier::mStereoFeat
Floats mStereoFeat
Definition: FormatClassifier.h:89
FormatClassifier::mSigBuffer
Floats mSigBuffer
Definition: FormatClassifier.h:84
FormatClassifier::Div
void Div(float *in, float div, size_t len)
Definition: FormatClassifier.cpp:285
MultiFormatReader::ReadSamples
size_t ReadSamples(void *buffer, size_t len, MultiFormatReader::FormatT format, MachineEndianness::EndiannessT end)
Definition: MultiFormatReader.cpp:67
FormatClassifier::GetResultChannels
unsigned GetResultChannels()
Definition: FormatClassifier.cpp:125
FormatClassifier::ConvertSamples
void ConvertSamples(void *in, float *out, FormatClassT format)
Definition: FormatClassifier.cpp:238
FormatClassifier::FormatClassT::format
MultiFormatReader::FormatT format
Definition: FormatClassifier.h:64
FormatClassifier::FormatClassT
Definition: FormatClassifier.h:63
FormatClassifier::mMeter
SpecPowerCalculation mMeter
Definition: FormatClassifier.h:78
MultiFormatReader::Uint8
@ Uint8
Definition: MultiFormatReader.h:61
MultiFormatReader::Double
@ Double
Definition: MultiFormatReader.h:65
FormatClassifier::Max
float Max(float *in, size_t len)
Definition: FormatClassifier.cpp:323
MultiFormatReader::Uint16
@ Uint16
Definition: MultiFormatReader.h:62
FormatClassifier::Mean
float Mean(float *in, size_t len)
Definition: FormatClassifier.cpp:309
MultiFormatReader::Int32
@ Int32
Definition: MultiFormatReader.h:60
FormatClassifier::FormatClassifier
FormatClassifier(const char *filename)
Definition: FormatClassifier.cpp:32
FormatClassifier::Add
void Add(float *in1, float *in2, size_t len)
Definition: FormatClassifier.cpp:269
FormatClassifier::mMonoFeat
Floats mMonoFeat
Definition: FormatClassifier.h:88
SpecPowerCalculation::CalcPower
float CalcPower(float *sig, float fc, float bw)
Definition: SpecPowerMeter.cpp:39
FormatClassifier::ToFloat
void ToFloat(T *in, float *out, size_t len)
Definition: FormatClassifier.cpp:346
MultiFormatReader::Int16
@ Int16
Definition: MultiFormatReader.h:59
FormatClassifier::mReader
MultiFormatReader mReader
Definition: FormatClassifier.h:77
FormatClassifier::GetResultFormat
FormatClassT GetResultFormat()
Definition: FormatClassifier.cpp:78
MultiFormatReader::Float
@ Float
Definition: MultiFormatReader.h:64
MachineEndianness::Big
@ Big
Definition: MultiFormatReader.h:23
FormatClassifier.h
FormatClassifier::cSiglen
static const size_t cSiglen
Definition: FormatClassifier.h:73
format
int format
Definition: ExportPCM.cpp:56
FormatClassifier::ReadSignal
void ReadSignal(FormatClassT format, size_t stride)
Definition: FormatClassifier.cpp:200
MultiFormatReader::Uint32
@ Uint32
Definition: MultiFormatReader.h:63
FormatClassifier::FormatClassT::endian
MachineEndianness::EndiannessT endian
Definition: FormatClassifier.h:65
FormatClassifier::mResultFormat
FormatClassT mResultFormat
Definition: FormatClassifier.h:91
FormatClassifier::mClasses
FormatVectorT mClasses
Definition: FormatClassifier.h:76
FormatClassifier::~FormatClassifier
~FormatClassifier()
Definition: FormatClassifier.cpp:74
FormatClassifier::mAuxBuffer
Floats mAuxBuffer
Definition: FormatClassifier.h:85
FormatClassifier::mRawBuffer
ArrayOf< uint8_t > mRawBuffer
Definition: FormatClassifier.h:86
FormatClassifier::cNumInts
static const size_t cNumInts
Definition: FormatClassifier.h:74
FormatClassifier::Run
void Run()
Definition: FormatClassifier.cpp:130
MultiFormatReader::Reset
void Reset()
Definition: MultiFormatReader.cpp:59
FormatClassifier::GetResultFormatLibSndfile
int GetResultFormatLibSndfile()
Definition: FormatClassifier.cpp:83
ArrayOf< float >
MultiFormatReader::Int8
@ Int8
Definition: MultiFormatReader.h:58
FormatClassifier::mResultChannels
unsigned mResultChannels
Definition: FormatClassifier.h:92