00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00036
00037
00038 #include <string>
00039 #include <iostream>
00040 #include <math.h>
00041
00042 #include "zplVecLib.h"
00043
00044 #include "FEAPI.h"
00045 #include "FEAPIExamplePluginSpectral.h"
00046 #include "FEAPIEntryPoints.h"
00047
00048 #ifndef FLT_MAX
00049 #define FLT_MAX 3.402823466e+38F
00050 #endif
00051
00052 #define kDefaultNumOfResults 8
00053 #define kDefaultRollOff 0.85F
00054
00056 #define _MY_MAJOR_VERSION 0x00000000
00057 #define _MY_MINOR_VERSION 0x00000000
00058 #define _MY_SUB_VERSION 0x00000001
00059
00060
00061
00062 #define _MY_PLUGIN_NAME "Spectral"
00063 #define _MY_PLUGIN_VENDOR "zplane.development"
00064 #define _MY_PLUGIN_DESCRIPTION "This PlugIn calculates the spectral features Flux, Rolloff, Centroid and Spread."
00065 #define _MY_PLUGIN_COPYRIGHT "(c) 2005 by zplane.development"
00066 #define _MY_PLUGIN_ID "zplSpectral"
00067
00068
00069
00070 #define kFeatureName "Relative number of Zero-Crossings"
00071 #define kFeatureUnit "-"
00072 #define kFeatureDescription "The number of zero crossings in the analysis block divided by the analysis block length"
00073 #define kFeatureRangeMin 0.0F
00074 #define kFeatureRangeMax 1.0F
00075 #define kFeatureIsQuantized -1 // value is not quantized
00076
00077
00078 enum SpectralParameters_t
00079 {
00080 kParamBlockSize = 0,
00081 kParamHopSize = 1,
00082 kParamChannelMode = 2,
00083 kParamWindowType = 3,
00084 kParamLowFreqBound = 4,
00085
00086 kNumParameters
00087 };
00088
00089 enum SpectralFeatures_t
00090 {
00091 kFeatureFlux = 0,
00092 kFeatureRolloff = 1,
00093 kFeatureCentroid = 2,
00094 kFeatureSpread = 3,
00095
00096 kNumFeatures
00097 };
00098
00099 static const FEAPI_ParameterDescription_t SpectralParameterDescription[kNumParameters] =
00100 {
00101
00102 {"Analysis Block Length", "Frames", "Length of analysis window for one result", 4, (float)((1<<30)-1), 1024, 4, false},
00103 {"Analysis Hop-Size", "ms", "Distance between two analysis block beginnings", 1, (float)((1<<30)-1), 10, -1, false},
00104 {"Individual Channels or Sum Channel", "", "Determines wether the calculation should be done on the sum of all input channels ('0') or on each individual channel ('1')", 0, 1, 0, 1, false},
00105 {"FFT Window", "", "Window Type for FFT analysis (0: rectangular, 1: hanning, 2: hamming, 3: blackman)", 0, 3, 1, 1, false},
00106 {"Low Frequency Cutoff", "Hz", "Only take into account frequencies above this frequency", 0, (float)((1<<30)-1), 0, -1, true},
00107
00108 };
00109
00110 static const FEAPI_SignalDescription_t SpectralFeatureDescription[kNumFeatures] =
00111 {
00112
00113 {"Spectral Flux", "", "/sqrt{/sum_{/forall k}{(X(n)-X(n-1))^2}}, n = block index, k = frequency index, X = abs spectrum", 0, (float)((1<<30)-1), -4, 0},
00114 {"Spectral Rolloff", "", "Defined as frequency f_K, given that 0.85/sum_{/forall k}{X_k} == /sum_0^K{X_k}, k = frequency index, X = abs spectrum", 0, (float)((1<<30)-1), -1, 0},
00115 {"Spectral Centroid", "", "C=/frac{/sum_{/forall k}{/log_2(0.001f_k}P}{/sum_{/forall k}{P}}, k = frequency index, P = power spectrum", -(float)((1<<30)-1),(float)((1<<30)-1), -1, 0},
00116 {"Spectrum Spread", "", "/frac{/sum_{/forall k}{(/log_2(0.001f_k}-C)^2 P}{/sum_{/forall k}{P}}, k = frequency index, P = power spectrum, C = spectral centroid", 0, (float)((1<<30)-1), -1, 0},
00117
00118 };
00119
00120 static INLINE int sfRollOffIdx (const float *pfSpectrum, int iLength)
00121 {
00122 float fSum = 0,
00123 fOverallSum = 0;
00124 int i;
00125
00126 for (i = 0; i < iLength; i++)
00127 fOverallSum += pfSpectrum[i];
00128
00129 fOverallSum *= kDefaultRollOff;
00130 i = 0;
00131 while (fSum < fOverallSum)
00132 {
00133 fSum += pfSpectrum[i];
00134 i++;
00135 }
00136
00137 return i;
00138 }
00139
00140 static INLINE float sfFlux (const float *pfSpectrum, float *pfOldSpectrum, int iStartIdx, int iLength)
00141 {
00142 float fSum = 0;
00143 int i;
00144
00145 zplfRealSub_I (pfOldSpectrum, (float*)pfSpectrum, iLength);
00146 zplfRealMul_I (pfOldSpectrum, pfOldSpectrum, iLength);
00147 for (i = iStartIdx; i < iLength; i++)
00148 fSum += pfOldSpectrum[i];
00149
00150 return sqrtf (fSum);
00151 }
00152
00153 static INLINE float sfCentroid (const float *pfSpectrum, float *pfLogFreqs, float fOverallSum, int iStartIdx, int iLength)
00154 {
00155 float fSum = 0;
00156 int i;
00157
00158 if (fOverallSum < 1e-30)
00159 return 0;
00160
00161 zplfRealMul_I (pfLogFreqs, (float*)pfSpectrum, iLength);
00162 for (i = iStartIdx; i < iLength; i++)
00163 fSum += pfLogFreqs[i];
00164
00165 return (fSum / fOverallSum);
00166 }
00167
00168 static INLINE float sfSpread (const float *pfSpectrum, float *pfLogFreqs, float fCentroid, float fOverallSum, int iStartIdx, int iLength)
00169 {
00170 float fSum = 0;
00171 int i;
00172
00173 if (fOverallSum < 1e-30)
00174 return 0;
00175
00176 zplfRealAddC_I (pfLogFreqs, -fCentroid, iLength);
00177 zplfRealMul_I (pfLogFreqs, pfLogFreqs, iLength);
00178 zplfRealMul_I (pfLogFreqs, (float*)pfSpectrum, iLength);
00179 for (i = iStartIdx; i < iLength; i++)
00180 fSum += pfLogFreqs[i];
00181
00182 return sqrtf (fSum / fOverallSum);
00183 }
00184
00185 CSpectralFeatures::CSpectralFeatures () : CFeatureExtractBase()
00186 {
00187
00188 zplVecLibDispatcher ();
00189
00190 m_ppCRingBuffer = 0;
00191 m_ppResults = 0;
00192 m_pfProcessBuffer = 0;
00193 m_ptLocalTimeStamp = 0;
00194 m_pfParameters = 0;
00195 m_pFFTInstance = 0;
00196 m_ppfFFTHistory = 0;
00197 m_pfHelpBuffer = 0;
00198 m_pfLogFreqs = 0;
00199 m_iMPEG7SetZero = 0;
00200
00201 m_iSizeOfResultBuffer = kDefaultNumOfResults;
00202
00203
00204 m_cPluginName = _MY_PLUGIN_NAME;
00205 m_cPluginVendor = _MY_PLUGIN_VENDOR;
00206 m_cPluginDescription = _MY_PLUGIN_DESCRIPTION;
00207 m_cPluginId = _MY_PLUGIN_ID;
00208 m_cPluginCopyRight = _MY_PLUGIN_COPYRIGHT;
00209
00210
00211 m_iMajorVersion = _MY_MAJOR_VERSION;
00212 m_iMinorVersion = _MY_MINOR_VERSION;
00213 m_iSubVersion = _MY_SUB_VERSION;
00214
00215 m_pfParameters = new float [kNumParameters];
00216 for (int i = 0; i < kNumParameters; i++)
00217 m_pfParameters[i] = SpectralParameterDescription[i].fDefaultValue;
00218 }
00219
00220
00221 CSpectralFeatures::~CSpectralFeatures ()
00222 {
00223 int iCh;
00224 if (m_ppCRingBuffer)
00225 {
00226 for (iCh = 0; iCh < this->GetPluginNumOfInputs (); iCh++)
00227 {
00228 if (m_ppCRingBuffer[iCh])
00229 delete m_ppCRingBuffer[iCh];
00230 m_ppCRingBuffer[iCh] = 0;
00231 }
00232 delete [] m_ppCRingBuffer;
00233 m_ppCRingBuffer = 0;
00234 }
00235 if (m_ppResults)
00236 {
00237 for (iCh = 0; iCh < this->GetPluginNumOfResults (); iCh++)
00238 {
00239 if (m_ppResults[iCh])
00240 delete [] m_ppResults[iCh];
00241 m_ppResults[iCh] = 0;
00242 }
00243 delete [] m_ppResults;
00244 m_ppResults = 0;
00245 }
00246 if (m_ptLocalTimeStamp)
00247 delete [] m_ptLocalTimeStamp;
00248 m_ptLocalTimeStamp = 0;
00249
00250 if (m_pfParameters)
00251 delete [] m_pfParameters;
00252 m_pfParameters = 0;
00253
00254 zplfFree (m_pfProcessBuffer);
00255 zplfFree (m_pfHelpBuffer);
00256 zplfFree (m_pfLogFreqs);
00257 if (m_ppfFFTHistory)
00258 {
00259 for (iCh = 0; iCh < this->GetPluginNumOfResults ()/kNumFeatures; iCh++)
00260 zplfFree (m_ppfFFTHistory[iCh]);
00261
00262 delete [] m_ppfFFTHistory;
00263 m_ppfFFTHistory = 0;
00264 }
00265 zplfFFTDestroyInstance (m_pFFTInstance);
00266 }
00267
00268
00269 FEAPI_Error_t CSpectralFeatures::InitializePlugin (float fInputSampleRate,
00270 int iNumberOfAudioChannels,
00271 int iHostApiMajorVersion,
00272 FEAPI_UserData_t *pstUserData)
00273 {
00274 FEAPI_Error_t rErr;
00275 int iCh;
00276
00277
00278 if (m_ppCRingBuffer)
00279 {
00280 for (iCh = 0; iCh < this->GetPluginNumOfInputs ()/kNumFeatures; iCh++)
00281 {
00282 if (m_ppCRingBuffer[iCh])
00283 delete m_ppCRingBuffer[iCh];
00284 m_ppCRingBuffer[iCh] = 0;
00285 }
00286 delete [] m_ppCRingBuffer;
00287 m_ppCRingBuffer = 0;
00288 }
00289 if (m_ppResults)
00290 {
00291 for (iCh = 0; iCh < this->GetPluginNumOfResults (); iCh++)
00292 {
00293 if (m_ppResults[iCh])
00294 delete [] m_ppResults[iCh];
00295 m_ppResults[iCh] = 0;
00296 }
00297 delete [] m_ppResults;
00298 m_ppResults = 0;
00299 }
00300 if (m_ptLocalTimeStamp)
00301 delete [] m_ptLocalTimeStamp;
00302 m_ptLocalTimeStamp = 0;
00303 zplfFree (m_pfProcessBuffer);
00304 zplfFree (m_pfHelpBuffer);
00305 zplfFree (m_pfLogFreqs);
00306 if (m_ppfFFTHistory)
00307 {
00308 for (iCh = 0; iCh < this->GetPluginNumOfResults ()/kNumFeatures; iCh++)
00309 zplfFree (m_ppfFFTHistory[iCh]);
00310
00311 delete [] m_ppfFFTHistory;
00312 m_ppfFFTHistory = 0;
00313 }
00314
00315 rErr = CFeatureExtractBase::InitializePlugin ( fInputSampleRate,
00316 iNumberOfAudioChannels,
00317 iHostApiMajorVersion,
00318 pstUserData);
00319
00320 if (rErr != FEAPI_kNoError)
00321 return rErr;
00322
00323
00324 char acChannelStr[FEAPI_kMaxDescriptionLength];
00325 for (int h = 0; h < iNumberOfAudioChannels; ++h)
00326 {
00327 sprintf(acChannelStr, "Channel: %d", h);
00328 SetPluginInputPinInfo(CPin::SetIndex(h)
00329 .SetName(acChannelStr)
00330 .SetUnit("")
00331 .SetDescription(acChannelStr)
00332 .SetRangeMin(-1.0f)
00333 .SetRangeMax(1.0f)
00334 .SetSampleRate(fInputSampleRate)
00335 );
00336 }
00337
00338
00339 for (int i = 0; i < kNumParameters; ++i)
00340 {
00341 SetPluginParameterPinInfo(CPin::SetIndex(i)
00342 .SetName(SpectralParameterDescription[i].acName)
00343 .SetUnit(SpectralParameterDescription[i].acUnit)
00344 .SetDescription(SpectralParameterDescription[i].acDescription)
00345 .SetRangeMin(SpectralParameterDescription[i].fRangeMin)
00346 .SetRangeMax(SpectralParameterDescription[i].fRangeMax)
00347 .SetDefaultValue(SpectralParameterDescription[i].fDefaultValue)
00348 .SetQuantizedTo(SpectralParameterDescription[i].fQuantizedTo)
00349 .SetIsChangeableInRealTime(SpectralParameterDescription[i].bIsChangeableInRealTime)
00350 );
00351 }
00352
00353
00354 int iAllocLength = (m_pfParameters[kParamBlockSize] > m_pfParameters[kParamHopSize]/1000*fInputSampleRate)?
00355 (int)(m_pfParameters[kParamBlockSize] + .5F) : (int)(m_pfParameters[kParamHopSize]/1000*fInputSampleRate + .5F);
00356 m_pfProcessBuffer = zplfMalloc (iAllocLength);
00357 m_pfHelpBuffer = zplfMalloc ((iAllocLength)>>1);
00358 m_pfLogFreqs = zplfMalloc ((iAllocLength)>>1);
00359 m_ppCRingBuffer = new CRingBuffer<float>*[iNumberOfAudioChannels];
00360 for (iCh = 0; iCh < iNumberOfAudioChannels; iCh++)
00361 {
00362 m_ppCRingBuffer[iCh] = new CRingBuffer<float>(iAllocLength<<1);
00363 }
00364
00365
00366 char acDescription[FEAPI_kMaxDescriptionLength];
00367
00368 int iNumOfResults = kNumFeatures * ((m_pfParameters[kParamChannelMode] == 0) ? 1 : iNumberOfAudioChannels);
00369 if (m_pfParameters[kParamChannelMode] == 0)
00370 {
00371 for (iCh = 0; iCh < iNumOfResults; ++iCh)
00372 {
00373 sprintf(acDescription, "%s", SpectralFeatureDescription[iCh].acDescription);
00374 SetPluginResultPinInfo(CPin::SetIndex(iCh)
00375 .SetName(SpectralFeatureDescription[iCh].acName)
00376 .SetUnit(SpectralFeatureDescription[iCh].acUnit)
00377 .SetDescription(acDescription)
00378 .SetRangeMin(SpectralFeatureDescription[iCh].fRangeMin)
00379 .SetRangeMax(SpectralFeatureDescription[iCh].fRangeMax)
00380 .SetQuantizedTo(SpectralFeatureDescription[iCh].fQuantizedTo)
00381 .SetSampleRate(1000.0F / m_pfParameters[kParamHopSize])
00382 );
00383 }
00384 }
00385 else
00386 {
00387 for (iCh = 0; iCh < iNumOfResults; ++iCh)
00388 {
00389 sprintf(acDescription, "Channel: %d;", iCh/iNumberOfAudioChannels);
00390 strcat(acDescription, SpectralFeatureDescription[iCh/iNumberOfAudioChannels].acDescription);
00391 SetPluginResultPinInfo(CPin::SetIndex(iCh)
00392 .SetName(SpectralFeatureDescription[iCh/iNumberOfAudioChannels].acName)
00393 .SetUnit(SpectralFeatureDescription[iCh/iNumberOfAudioChannels].acUnit)
00394 .SetDescription(acDescription)
00395 .SetRangeMin(SpectralFeatureDescription[iCh/iNumberOfAudioChannels].fRangeMin)
00396 .SetRangeMax(SpectralFeatureDescription[iCh/iNumberOfAudioChannels].fRangeMax)
00397 .SetQuantizedTo(SpectralFeatureDescription[iCh/iNumberOfAudioChannels].fQuantizedTo)
00398 .SetSampleRate(1000.0F / m_pfParameters[kParamHopSize])
00399 );
00400 }
00401 }
00402 m_ppResults = new InternalResults_t*[iNumOfResults];
00403 m_ppfFFTHistory = new float*[iNumOfResults];
00404 m_ptLocalTimeStamp = new FEAPI_TimeStamp_t [iNumOfResults];
00405 for (iCh = 0; iCh < iNumOfResults; iCh++)
00406 {
00407 m_ppResults[iCh] = new InternalResults_t[m_iSizeOfResultBuffer];
00408 m_ppfFFTHistory[iCh] = zplfMalloc (((int)(m_pfParameters[kParamBlockSize]+.1F))>>1);
00409 zplfSetZero (m_ppfFFTHistory[iCh], ((int)(m_pfParameters[kParamBlockSize]+.1F))>>1);
00410 memset (m_ppResults[iCh], 0, sizeof (InternalResults_t) * m_iSizeOfResultBuffer);
00411 }
00412 memset (m_ptLocalTimeStamp, 0, sizeof(FEAPI_TimeStamp_t)*iNumberOfAudioChannels);
00413
00414 zplfFFTDestroyInstance (m_pFFTInstance);
00415 zplfFFTCreateInstance (m_pFFTInstance, (int)(m_pfParameters[kParamBlockSize] + .1F),1, CzplfFFT_If::_Fft_Windows_ ((int)(m_pfParameters[kParamWindowType] + .1F)));
00416
00417
00418 m_iMPEG7SetZero = this->CalcFreqTable ();
00419
00420 return FEAPI_kNoError;
00421 }
00422
00423 FEAPI_Error_t CSpectralFeatures::SetPluginParameter (int iParameterIndex, float fValue)
00424 {
00425 if ((iParameterIndex >= this->GetPluginNumOfParameters ()) || (iParameterIndex < 0))
00426 return FEAPI_kUnspecifiedError;
00427
00428 if ((fValue < SpectralParameterDescription[iParameterIndex].fRangeMin) || (fValue > SpectralParameterDescription[iParameterIndex].fRangeMax))
00429 return FEAPI_kUnspecifiedError;
00430
00431 m_pfParameters[iParameterIndex] = fValue;
00432
00433 if ((iParameterIndex == kParamBlockSize) && ((int)(fValue) != Int2PowTwo ((int)fValue)))
00434 return FEAPI_kUnspecifiedError;
00435
00436
00437 if (iParameterIndex != kParamLowFreqBound)
00438 this->InitializePlugin (m_fSampleRate, this->GetPluginNumOfInputs (), 1, 0);
00439
00440 return FEAPI_kNoError;
00441 }
00442
00443
00444 float CSpectralFeatures::GetPluginParameter (int iParameterIndex)
00445 {
00446 if ((iParameterIndex >= this->GetPluginNumOfParameters ()) || (iParameterIndex < 0))
00447 return FEAPI_kUnspecifiedError;
00448
00449 return m_pfParameters[iParameterIndex];
00450 }
00451
00452
00453 int CSpectralFeatures::GetPluginResultLatency (int iResultIndex)
00454 {
00455 return (int)(m_pfParameters[kParamBlockSize]);
00456 }
00457
00458
00459 FEAPI_Error_t CSpectralFeatures::ProcessPluginDone ()
00460 {
00461 int iNumProcessChannels = this->GetPluginNumOfResults ()/kNumFeatures,
00462 iProcessBlockSize = (int)(m_pfParameters[kParamBlockSize]),
00463 iProcessBufSize = (m_pfParameters[kParamBlockSize] > m_pfParameters[kParamHopSize]/1000*m_fSampleRate)? (int)(m_pfParameters[kParamBlockSize] + .5F) : (int)(m_pfParameters[kParamHopSize]/1000*m_fSampleRate + .5F),
00464 iStartIdx = (int)(m_pfParameters[kParamLowFreqBound] / m_fSampleRate * iProcessBlockSize),
00465 iSamplesInBuffer = m_ppCRingBuffer[0]->GetSamplesInBuffer ();
00466
00467 for (int iCh = 0; iCh < iNumProcessChannels; iCh++)
00468 {
00469 float fSum = 0,
00470 fResult;
00471
00472
00473 m_ppCRingBuffer[iCh]->GetPostInc (m_pfProcessBuffer, iSamplesInBuffer);
00474 memset (&m_pfProcessBuffer[iSamplesInBuffer], 0, sizeof(float)*(iProcessBufSize - iSamplesInBuffer));
00475
00476
00477 m_ptLocalTimeStamp[iCh] = m_ptLocalTimeStamp[iCh] - iSamplesInBuffer/m_fSampleRate;
00478
00479
00480 m_pFFTInstance->zplfFFT (m_pfProcessBuffer, m_pfProcessBuffer);
00481
00482
00483 zplfCompAbs (m_pfProcessBuffer, m_pfProcessBuffer, iProcessBlockSize>>1);
00484
00486
00487 fResult = sfRollOffIdx (&m_pfProcessBuffer[iStartIdx], (iProcessBlockSize>>1)-iStartIdx) * m_fSampleRate / iProcessBlockSize;
00488 this->WriteResult (kFeatureRolloff * iNumProcessChannels + iCh, fResult, m_ptLocalTimeStamp[iCh]);
00489
00490
00491 fResult = sfFlux (m_pfProcessBuffer, m_ppfFFTHistory[iCh], iStartIdx, iProcessBlockSize>>1);
00492 this->WriteResult (kFeatureFlux * iNumProcessChannels + iCh, fResult, m_ptLocalTimeStamp[iCh]);
00493
00494
00495 memcpy (m_ppfFFTHistory[iCh], m_pfProcessBuffer, sizeof(float)*(iProcessBlockSize>>1));
00496
00497
00498 zplfRealMul_I (m_pfProcessBuffer, m_pfProcessBuffer, iProcessBlockSize>>1);
00499
00500
00501 for (int j = iStartIdx; j < iProcessBlockSize>>1; j++)
00502 fSum += m_pfProcessBuffer[j];
00503
00504
00505 memcpy (m_pfHelpBuffer, m_pfLogFreqs, sizeof(float)*(iProcessBlockSize>>1));
00506 fResult = sfCentroid (m_pfProcessBuffer, m_pfHelpBuffer, fSum, iStartIdx, iProcessBlockSize>>1);
00507 this->WriteResult (kFeatureCentroid * iNumProcessChannels + iCh, fResult, m_ptLocalTimeStamp[iCh]);
00508
00509
00510 memcpy (m_pfHelpBuffer, m_pfLogFreqs, sizeof(float)*(iProcessBlockSize>>1));
00511 fResult = sfSpread (m_pfProcessBuffer, m_pfHelpBuffer, fResult, fSum, iStartIdx, iProcessBlockSize>>1);
00512 this->WriteResult (kFeatureSpread * iNumProcessChannels + iCh, fResult, m_ptLocalTimeStamp[iCh]);
00513 }
00514
00515 return FEAPI_kNoError;
00516 }
00517
00518 FEAPI_Error_t CSpectralFeatures::ProcessPlugin (const float **ppfInputBuffer, const FEAPI_TimeStamp_t *ptTimeStamps, int iNumberOfFrames)
00519 {
00520 bool bDownmixToMono = (m_pfParameters[kParamChannelMode] == 0)? true : false;
00521 int iCh,
00522 iIdx,
00523 iProcessBlockSize = (int)(m_pfParameters[kParamBlockSize]),
00524 iHopSize = (int)(m_pfParameters[kParamHopSize]*0.001F * m_fSampleRate + .1F),
00525 iFramesRequired = (m_pfParameters[kParamBlockSize] > iHopSize) ? (int)(m_pfParameters[kParamBlockSize]) : iHopSize,
00526 iStartIdx = (int)(m_pfParameters[kParamLowFreqBound] / m_fSampleRate * iProcessBlockSize),
00527 iNumFramesLeft = iNumberOfFrames,
00528 iNumInputChannels = this->GetPluginNumOfInputs (),
00529 iNumProcessChannels = this->GetPluginNumOfResults ()/kNumFeatures,
00530 iSamplesInBuffer = 0;
00531
00532 if (!m_bIsInitialized)
00533 return FEAPI_kUnspecifiedError;
00534
00535
00536 if (ptTimeStamps)
00537 {
00538 for (iCh = 0; iCh < iNumInputChannels; iCh++)
00539 m_ptLocalTimeStamp[iCh] = ptTimeStamps[iCh] + iNumberOfFrames/m_fSampleRate;
00540 }
00541 else
00542 {
00543 for (iCh = 0; iCh < iNumInputChannels; iCh++)
00544 m_ptLocalTimeStamp[iCh] += iNumberOfFrames/m_fSampleRate;
00545 }
00546
00547
00548
00549 while (m_ppCRingBuffer[0]->GetSamplesInBuffer () + iNumFramesLeft >= iFramesRequired)
00550 {
00551
00552 if (bDownmixToMono)
00553 {
00554 int iLength = (iHopSize < iNumFramesLeft) ? iHopSize : iNumFramesLeft;
00555 iNumProcessChannels = 1;
00556
00557 memcpy (m_pfProcessBuffer, &ppfInputBuffer[0][iNumberOfFrames - iNumFramesLeft], sizeof(float) * iLength);
00558 for (iCh = 1; iCh < iNumInputChannels; iCh++)
00559 {
00560 const float *pfBuffer = &ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft];
00561
00562 for (iIdx = 0; iIdx < iLength; iIdx++)
00563 m_pfProcessBuffer[iIdx] += pfBuffer[iIdx];
00564 }
00565
00566
00567 for (iIdx = 0; iIdx < iLength; iIdx++)
00568 m_pfProcessBuffer[iIdx] *= 1.0F/iNumInputChannels;
00569
00570 m_ppCRingBuffer[0]->PutPostInc (m_pfProcessBuffer, iLength);
00571 }
00572 else
00573 {
00574 for (iCh = 0; iCh < iNumInputChannels; iCh++)
00575 m_ppCRingBuffer[iCh]->PutPostInc (&ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft], (iHopSize < iNumFramesLeft) ? iHopSize : iNumFramesLeft);
00576 }
00577
00578
00579 iNumFramesLeft -= (iHopSize < iNumFramesLeft) ? iHopSize : iNumFramesLeft;
00580
00581
00582 iSamplesInBuffer = m_ppCRingBuffer[0]->GetSamplesInBuffer ();
00583
00584
00585 if (iSamplesInBuffer < iProcessBlockSize)
00586 continue;
00587
00588
00589 for (iCh = 0; iCh < iNumProcessChannels; iCh++)
00590 {
00591 int j;
00592 float fSum = 0,
00593 fResult;
00594
00595
00596 m_ptLocalTimeStamp[iCh] = ptTimeStamps[iCh] + iNumberOfFrames/m_fSampleRate - (iSamplesInBuffer+iNumFramesLeft)/m_fSampleRate;
00597
00598
00599 m_ppCRingBuffer[iCh]->GetOff (m_pfProcessBuffer, iProcessBlockSize, 0);
00600 m_ppCRingBuffer[iCh]->SetReadPos (m_ppCRingBuffer[iCh]->GetReadPos () + iHopSize);
00601
00602
00603 m_pFFTInstance->zplfFFT (m_pfProcessBuffer, m_pfProcessBuffer);
00604
00605
00606 zplfCompAbs (m_pfProcessBuffer, m_pfProcessBuffer, iProcessBlockSize>>1);
00607
00608
00609 fResult = sfRollOffIdx (&m_pfProcessBuffer[iStartIdx], (iProcessBlockSize>>1)-iStartIdx) * m_fSampleRate / iProcessBlockSize;
00610 this->WriteResult (kFeatureRolloff * iNumProcessChannels + iCh, fResult, m_ptLocalTimeStamp[iCh]);
00611
00612
00613 fResult = sfFlux (m_pfProcessBuffer, m_ppfFFTHistory[iCh], iStartIdx, iProcessBlockSize>>1);
00614 this->WriteResult (kFeatureFlux * iNumProcessChannels + iCh, fResult, m_ptLocalTimeStamp[iCh]);
00615
00616
00617 memcpy (m_ppfFFTHistory[iCh], m_pfProcessBuffer, sizeof(float)*(iProcessBlockSize>>1));
00618
00619
00620 zplfRealMul_I (m_pfProcessBuffer, m_pfProcessBuffer, (iProcessBlockSize>>1));
00621
00622
00623 for (j = 0; j < m_iMPEG7SetZero+1; j++)
00624 fSum += m_pfProcessBuffer[j];
00625 for (j = 0; j < m_iMPEG7SetZero; j++)
00626 m_pfProcessBuffer[j] = 0.0F;
00627 m_pfProcessBuffer[m_iMPEG7SetZero] = fSum;
00628
00629
00630 fSum = 0;
00631 for (j = iStartIdx; j < iProcessBlockSize>>1; j++)
00632 fSum += m_pfProcessBuffer[j];
00633
00634
00635 memcpy (m_pfHelpBuffer, m_pfLogFreqs, sizeof(float)*(iProcessBlockSize>>1));
00636 fResult = sfCentroid (m_pfProcessBuffer, m_pfHelpBuffer, fSum, iStartIdx, iProcessBlockSize>>1);
00637 this->WriteResult (kFeatureCentroid * iNumProcessChannels + iCh, fResult, m_ptLocalTimeStamp[iCh]);
00638
00639
00640 memcpy (m_pfHelpBuffer, m_pfLogFreqs, sizeof(float)*(iProcessBlockSize>>1));
00641 fResult = sfSpread (m_pfProcessBuffer, m_pfHelpBuffer, fResult, fSum, iStartIdx, iProcessBlockSize>>1);
00642 this->WriteResult (kFeatureSpread * iNumProcessChannels + iCh, fResult, m_ptLocalTimeStamp[iCh]);
00643
00644
00645 m_ptLocalTimeStamp[iCh] = m_ptLocalTimeStamp[iCh] + iHopSize/m_fSampleRate;
00646 }
00647 }
00648
00649
00650 if (iNumFramesLeft > 0)
00651 {
00652
00653 if (bDownmixToMono)
00654 {
00655
00656 memcpy (m_pfProcessBuffer, &ppfInputBuffer[0][iNumberOfFrames - iNumFramesLeft], sizeof(float) * iNumFramesLeft);
00657 for (iCh = 1; iCh < iNumInputChannels; iCh++)
00658 {
00659 const float *pfBuffer = &ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft];
00660
00661 for (iIdx = 0; iIdx < iNumFramesLeft; iIdx++)
00662 m_pfProcessBuffer[iIdx] += pfBuffer[iIdx];
00663 }
00664
00665 for (iIdx = 0; iIdx < iHopSize; iIdx++)
00666 m_pfProcessBuffer[iIdx] *= 1.0F/iNumInputChannels;
00667
00668 m_ppCRingBuffer[0]->PutPostInc (m_pfProcessBuffer, iNumFramesLeft);
00669 }
00670 else
00671 {
00672 for (iCh = 0; iCh < iNumInputChannels; iCh++)
00673 m_ppCRingBuffer[iCh]->PutPostInc (&ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft], iNumFramesLeft);
00674 }
00675 }
00676
00677 return FEAPI_kNoError;
00678 }
00679
00680 int CSpectralFeatures::GetPluginSizeOfResult (int iResultIndex)
00681 {
00682 if ((iResultIndex >= this->GetPluginNumOfResults ()) || (iResultIndex < 0))
00683 return -1;
00684
00685 if (m_ppResults[iResultIndex][0].bHoldsResult == true)
00686 return 1;
00687 else
00688 return 0;
00689 }
00690
00691
00692 FEAPI_Error_t CSpectralFeatures::GetPluginResult (int iResultIndex, float *pfResult, FEAPI_TimeStamp_t *ptTimeStamp)
00693 {
00694 if ((iResultIndex >= this->GetPluginNumOfResults ()) || (iResultIndex < 0))
00695 return FEAPI_kUnspecifiedError;
00696
00697 if (m_ppResults[iResultIndex][0].bHoldsResult == false)
00698 return FEAPI_kUnspecifiedError;
00699
00700 pfResult[0] = m_ppResults[iResultIndex][0].fResult;
00701 ptTimeStamp[0] = m_ppResults[iResultIndex][0].tTimeStamp;
00702
00703 memmove (&m_ppResults[iResultIndex][0], &m_ppResults[iResultIndex][1], (m_iSizeOfResultBuffer - 1)*sizeof(InternalResults_t));
00704 m_ppResults[iResultIndex][m_iSizeOfResultBuffer-1].bHoldsResult = false;
00705
00706 return FEAPI_kNoError;
00707 }
00708
00709
00710 FEAPI_Error_t CSpectralFeatures::ResetPlugin ()
00711 {
00712 for (int iCh = 0; iCh < this->GetPluginNumOfInputs (); iCh++)
00713 {
00714 m_ppCRingBuffer[iCh]->Reset ();
00715 m_ptLocalTimeStamp[iCh] = 0;
00716 }
00717 return FEAPI_kNoError;
00718 }
00719
00720
00721 float CSpectralFeatures::GetPluginProperty ( FEAPI_PluginProperty_t ePluginProperty)
00722 {
00723 switch (ePluginProperty)
00724 {
00725 case FEAPI_kMinSampleRate:
00726 {
00727 return 1;
00728 }
00729 case FEAPI_kMaxSampleRate:
00730 {
00731 return 1e38F;
00732 }
00733 case FEAPI_kMinChannels:
00734 {
00735 return 1;
00736 }
00737 case FEAPI_kMaxChannels:
00738 {
00739 return (float)((1<<30)-1);
00740 }
00741 case FEAPI_kMinFrameSize:
00742 {
00743 return 1;
00744 }
00745 case FEAPI_kMaxFrameSize:
00746 {
00747 return (float)((1<<30)-1);
00748 }
00749 case FEAPI_kOptFrameSize:
00750 {
00751 return floorf(m_pfParameters[kParamHopSize] * 0.001F * m_fSampleRate + .1F);
00752 }
00753 default:
00754 {
00755
00756 return -1;
00757 }
00758 }
00759 return -1;
00760 }
00761
00762 void CSpectralFeatures::WriteResult (int iResultIdx, float fValue, FEAPI_TimeStamp_t tTimeStamp)
00763 {
00764 int iCurrentIdx = 0;
00765
00766 ZASSERT (!m_ppResults);
00767
00768 for (iCurrentIdx = 0; iCurrentIdx < m_iSizeOfResultBuffer; iCurrentIdx++)
00769 {
00770 ZASSERT (!m_ppResults[iCurrentIdx]);
00771 if (m_ppResults[iResultIdx][iCurrentIdx].bHoldsResult == false)
00772 break;
00773 }
00774 if (iCurrentIdx == m_iSizeOfResultBuffer)
00775 {
00776
00777 m_iSizeOfResultBuffer <<= 1;
00778 for (int i = 0; i < this->GetPluginNumOfResults (); i++)
00779 {
00780 InternalResults_t *pTmp = new InternalResults_t[m_iSizeOfResultBuffer];
00781 memcpy (pTmp, m_ppResults[i], (m_iSizeOfResultBuffer>>1) * sizeof(InternalResults_t));
00782 memset (&pTmp[(m_iSizeOfResultBuffer>>1)], 0, (m_iSizeOfResultBuffer>>1) * sizeof(InternalResults_t));
00783 delete [] m_ppResults[i];
00784 m_ppResults[i] = 0;
00785 m_ppResults[i] = pTmp;
00786 }
00787 }
00788
00789 m_ppResults[iResultIdx][iCurrentIdx].bHoldsResult = true;
00790 m_ppResults[iResultIdx][iCurrentIdx].fResult = fValue;
00791 m_ppResults[iResultIdx][iCurrentIdx].tTimeStamp = tTimeStamp;
00792
00793 return;
00794 }
00795
00796 int CSpectralFeatures::CalcFreqTable ()
00797 {
00798
00799
00800 int i,
00801 iProcessBlockSize = (((int)(m_pfParameters[kParamBlockSize]+.1F))>>1),
00802 iStartIdx = (int)floorf ( 62.5F * (iProcessBlockSize<<1) / m_fSampleRate)+1;
00803 float fInvLog2 = 1.0F / logf(2.0F),
00804 fInvBlockSize = 1.0F / (iProcessBlockSize<<1);
00805
00806 for (i = 0; i < iStartIdx; i++)
00807 m_pfLogFreqs[i] = fInvLog2 * logf (31.25F*0.001F);
00808
00809 for (i = iStartIdx; i < iProcessBlockSize; i++)
00810 m_pfLogFreqs[i] = fInvLog2 * logf (i * m_fSampleRate * 0.001F * fInvBlockSize);
00811
00812 return iStartIdx-1;
00813 }
00814
00816
00817 #ifdef __cplusplus
00818 extern "C" {
00819 #endif
00820
00821 FEAPI_ENTRY_POINTS(CSpectralFeatures)
00822
00823 #ifdef __cplusplus
00824 }
00825 #endif
00826
00827