00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00024
00025
00026 #include <string>
00027 #include <iostream>
00028 #include <math.h>
00029
00030 #include "zplVecLib.h"
00031
00032 #include "FEAPI.h"
00033 #include "FEAPIExamplePluginLoudness.h"
00034 #include "FEAPIEntryPoints.h"
00035
00036 #ifndef FLT_MAX
00037 #define FLT_MAX 3.402823466e+38F
00038 #endif
00039
00041 #if !defined(_PI)
00042 #define _PI (float)(3.1415926535897932384626433832795)
00043 #endif
00044 #if !defined(_PI2)
00045 #define _PI2 (float)(1.570796326794897)
00046 #endif
00047 #if !defined(_PI4)
00048 #define _PI4 (float)(7.853981633974483e-001)
00049 #endif
00050 #if !defined(_2PI)
00051 #define _2PI (float)(6.283185307179586476925286766559)
00052 #endif
00053 #if !defined(_LN10)
00054 #define _LN10 (float)(2.30258509299405)
00055 #endif
00056 #if !defined(_INVLN10)
00057 #define _INVLN10 (float)(0.4342944819032518)
00058 #endif
00059 #if !defined(_10INVLN10)
00060 #define _10INVLN10 (float)(4.342944819032518)
00061 #endif
00062 #if !defined(_20INVLN10)
00063 #define _20INVLN10 (float)(8.685889638065035)
00064 #endif
00065 #if !defined(_INVLN2)
00066 #define _INVLN2 (float)(1.442695040888963)
00067 #endif
00068 #if !defined(_SQRT2)
00069 #define _SQRT2 (float)(1.4142135623730950488016887242097)
00070 #endif
00071 #if !defined(_INVSQRT2)
00072 #define _INVSQRT2 (float)(0.70710678118654752440084436210485)
00073 #endif
00074 #if !defined(_SQRT10)
00075 #define _SQRT10 (float)(3.162277660168380)
00076 #endif
00077 #if !defined(_SQRT3)
00078 #define _SQRT3 (float)(1.732050807568877)
00079 #endif
00080 #if !defined(_SQRT5)
00081 #define _SQRT5 (float)(2.236067977499790)
00082 #endif
00083 #if !defined(_SQRT4)
00084 #define _SQRT4 (float)(2.0)
00085 #endif
00086
00087 #define ZABS(a) (((a) > (0)) ? (a) : -(a))
00088
00089 #define ZMIN(a,b) (((a) < (b)) ? (a) : (b))
00090
00091 #define ZMAX(a,b) (((a) > (b)) ? (a) : (b))
00092
00093 #define ZSQR(a) (float)((a)*(a))
00094
00095 #define ZSQRT(a) (float)(sqrt(a))
00096
00097 #define ZPOW10(a) (float)(exp(_LN10*(a)))
00098
00099 #define SWAPINT(a,b) {zINT iTmp = (a); (a) = (b); (b) = (iTmp);}
00100
00101
00102
00103 #define kDefaultNumOfResults 8
00104 #define kDefaultRollOff 0.85F
00105
00107 #define _MY_MAJOR_VERSION 0x00000000
00108 #define _MY_MINOR_VERSION 0x00000000
00109 #define _MY_SUB_VERSION 0x00000001
00110
00111
00112
00113 #define _MY_PLUGIN_NAME "Loudness"
00114 #define _MY_PLUGIN_VENDOR "zplane.development"
00115 #define _MY_PLUGIN_DESCRIPTION "This PlugIn calculates the zwicker loundess per channel. "
00116 #define _MY_PLUGIN_COPYRIGHT "(c) 2005-2006 by zplane.development"
00117 #define _MY_PLUGIN_ID "zplLoudness"
00118
00119
00120
00121
00122 enum LoudnessParameters_t
00123 {
00124 kParamBlockSize = 0,
00125 kParamHopSize = 1,
00126 kParamChannelMode = 2,
00127 kParamWindowType = 3,
00128 kParamLowFreqBound = 4,
00129 kParamZeroPad = 5,
00130
00131 kNumParameters
00132 };
00133
00134 enum LoudnessFeatures_t
00135 {
00136 kLoudness1 = 0,
00137 kLoudness2 = 1,
00138
00139 kNumFeatures
00140 };
00141
00142 #define kReferenceLevel (.5F*_SQRT2/20e-6F)
00143
00144 #define kNumMidFreqs 28
00145 static const float fMidFreqs[kNumMidFreqs] =
00146 {
00147 25,
00148 31.5,
00149 40,
00150 50,
00151 63,
00152 80,
00153 100,
00154 125,
00155 160,
00156 200,
00157 250,
00158 315,
00159 400,
00160 500,
00161 630,
00162 800,
00163 1000,
00164 1250,
00165 1600,
00166 2000,
00167 2500,
00168 3150,
00169 4000,
00170 5000,
00171 6300,
00172 8000,
00173 10000,
00174 12500
00175 };
00176
00177 static const FEAPI_ParameterDescription_t LoudnessParameterDescription[kNumParameters] =
00178 {
00179
00180 {"Analysis Block Length", "Frames", "Length of analysis window for one result", 4, (float)((1<<30)-1), 32768, 4, false},
00181 {"Analysis Hop-Size", "ms", "Distance between two analysis block beginnings", 1, (float)((1<<30)-1), 10, -1, false},
00182 {"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},
00183 {"FFT Window", "", "Window Type for FFT analysis (0: rectangular, 1: hanning, 2: hamming, 3: blackman)", 0, 3, 1, 1, false},
00184 {"Low Frequency Cutoff", "Hz", "Only take into account frequencies above this frequency", 0, (float)((1<<30)-1), 0, -1, true},
00185 {"Zero Pad Factor", "", "Factor for zeropadding the FFT, has to be pow of two", 1, 256, 1, -1, false},
00186
00187 };
00188
00189 static const FEAPI_SignalDescription_t LoudnessFeatureDescription[kNumFeatures] =
00190 {
00191
00192 {"Loudness 1", "", "loudness roughly after DIN standard", 0, (float)((1<<30)-1), -1, 0},
00193 {"Loudness 2", "", "alternative loudness", 0, (float)((1<<30)-1), -1, 0},
00194
00195 };
00196
00197 static INLINE float loudFreq2Bark (float fFrequency, int iMode = 0)
00198 {
00199 float fBark;
00200
00201 switch (iMode)
00202 {
00203 default:
00204 case 0:
00205 fBark = 13.0F * atanf (0.00076F*fFrequency) + 3.5F * atanf (ZSQR(fFrequency/7500.0F));
00206 break;
00207 case 1:
00208 fBark = 13.3F * atanf (0.00075F*fFrequency);
00209 break;
00210 case 2:
00211 fFrequency /= 650;
00212 fBark = 7.0F * logf (fFrequency + sqrtf (ZSQR(fFrequency) + 1));
00213 break;
00214 }
00215 return fBark;
00216 }
00217
00218 static INLINE float loudBark2Freq (float fBark, int iMode = 1)
00219 {
00220 float fFrequency;
00221
00222 switch (iMode)
00223 {
00224 default:
00225 case 1:
00226 fFrequency = 4*1000.0F/3 * tan (fBark/13.3F);
00227 break;
00228 case 2:
00229 fFrequency = 650.0F * sinhf (fBark/7);
00230 break;
00231 }
00232 return fFrequency;
00233 }
00234
00235 static inline float loudIntPow (float a, int b)
00236 {
00237 if (b == 0)
00238 return 1;
00239 double dResult = a;
00240 while (--b > 0)
00241 dResult *= a;
00242 return (dResult < 1e-30f)? 0 : (float)dResult;
00243 }
00244
00245 CLoudness::CLoudness () : CFeatureExtractBase()
00246 {
00247
00248 zplVecLibDispatcher ();
00249
00250 m_ppCRingBuffer = 0;
00251 m_ppResults = 0;
00252 m_pfProcessBuffer = 0;
00253 m_pfHelpBuffer = 0;
00254 m_ptLocalTimeStamp = 0;
00255 m_pfParameters = 0;
00256 m_pFFTInstance = 0;
00257 m_pDINFreqBands = 0;
00258 m_iNumOfDINThirdBands = 0;
00259 m_iNumOfDINCritBands = 0;
00260 m_pfDINBandLevels = 0;
00261 m_iNumOfCritBands = 48;
00262 m_fRMSFullScaleLevel = kReferenceLevel;
00263
00264 m_bDiffuseFieldCorrected = false;
00265
00266
00267 m_iSizeOfResultBuffer = kDefaultNumOfResults;
00268
00269
00270 m_cPluginName = _MY_PLUGIN_NAME;
00271 m_cPluginVendor = _MY_PLUGIN_VENDOR;
00272 m_cPluginDescription = _MY_PLUGIN_DESCRIPTION;
00273 m_cPluginId = _MY_PLUGIN_ID;
00274 m_cPluginCopyRight = _MY_PLUGIN_COPYRIGHT;
00275
00276
00277 m_iMajorVersion = _MY_MAJOR_VERSION;
00278 m_iMinorVersion = _MY_MINOR_VERSION;
00279 m_iSubVersion = _MY_SUB_VERSION;
00280
00281 m_pfParameters = new float [kNumParameters];
00282 for (int i = 0; i < kNumParameters; i++)
00283 m_pfParameters[i] = LoudnessParameterDescription[i].fDefaultValue;
00284 }
00285
00286
00287 CLoudness::~CLoudness ()
00288 {
00289 int iCh;
00290 if (m_ppCRingBuffer)
00291 {
00292 for (iCh = 0; iCh < this->GetPluginNumOfInputs (); iCh++)
00293 {
00294 if (m_ppCRingBuffer[iCh])
00295 delete m_ppCRingBuffer[iCh];
00296 m_ppCRingBuffer[iCh] = 0;
00297 }
00298 delete [] m_ppCRingBuffer;
00299 m_ppCRingBuffer = 0;
00300 }
00301 if (m_ppResults)
00302 {
00303 for (iCh = 0; iCh < this->GetPluginNumOfResults (); iCh++)
00304 {
00305 if (m_ppResults[iCh])
00306 delete [] m_ppResults[iCh];
00307 m_ppResults[iCh] = 0;
00308 }
00309 delete [] m_ppResults;
00310 m_ppResults = 0;
00311 }
00312 if (m_ptLocalTimeStamp)
00313 delete [] m_ptLocalTimeStamp;
00314 m_ptLocalTimeStamp = 0;
00315
00316 if (m_pfParameters)
00317 delete [] m_pfParameters;
00318 m_pfParameters = 0;
00319
00320 zplfFree (m_pfProcessBuffer);
00321 zplfFree (m_pfHelpBuffer);
00322
00323 zplfFFTDestroyInstance (m_pFFTInstance);
00324 }
00325
00326
00327 FEAPI_Error_t CLoudness::InitializePlugin (float fInputSampleRate,
00328 int iNumberOfAudioChannels,
00329 int iHostApiMajorVersion,
00330 FEAPI_UserData_t *pstUserData)
00331 {
00332 FEAPI_Error_t rErr;
00333 int i,
00334 iCh,
00335 iBlockSize = (int)(m_pfParameters[kParamBlockSize]+.1F);
00336
00337
00338 if (m_ppCRingBuffer)
00339 {
00340 for (iCh = 0; iCh < this->GetPluginNumOfInputs (); iCh++)
00341 {
00342 if (m_ppCRingBuffer[iCh])
00343 delete m_ppCRingBuffer[iCh];
00344 m_ppCRingBuffer[iCh] = 0;
00345 }
00346 delete [] m_ppCRingBuffer;
00347 m_ppCRingBuffer = 0;
00348 }
00349 if (m_ppResults)
00350 {
00351 for (iCh = 0; iCh < this->GetPluginNumOfResults (); iCh++)
00352 {
00353 if (m_ppResults[iCh])
00354 delete [] m_ppResults[iCh];
00355 m_ppResults[iCh] = 0;
00356 }
00357 delete [] m_ppResults;
00358 m_ppResults = 0;
00359 }
00360 if (m_ptLocalTimeStamp)
00361 delete [] m_ptLocalTimeStamp;
00362 m_ptLocalTimeStamp = 0;
00363 if (m_pDINFreqBands)
00364 delete [] m_pDINFreqBands;
00365 m_pDINFreqBands = 0;
00366 zplfFree (m_pfProcessBuffer);
00367 zplfFree (m_pfHelpBuffer);
00368
00369 rErr = CFeatureExtractBase::InitializePlugin ( fInputSampleRate,
00370 iNumberOfAudioChannels,
00371 iHostApiMajorVersion,
00372 pstUserData);
00373
00374
00375 if (rErr != FEAPI_kNoError)
00376 return rErr;
00377
00378
00379 char acChannelStr[FEAPI_kMaxDescriptionLength];
00380 for (iCh = 0; iCh < iNumberOfAudioChannels; ++iCh)
00381 {
00382 sprintf(acChannelStr, "Channel: %d", iCh);
00383 SetPluginInputPinInfo(CPin::SetIndex(iCh)
00384 .SetName(acChannelStr)
00385 .SetUnit("")
00386 .SetDescription(acChannelStr)
00387 .SetRangeMin(-1.0f)
00388 .SetRangeMax(1.0f)
00389 .SetSampleRate(fInputSampleRate)
00390 );
00391 }
00392
00393
00394 for (i = 0; i < kNumParameters; ++i)
00395 {
00396 SetPluginParameterPinInfo(CPin::SetIndex(i)
00397 .SetName(LoudnessParameterDescription[i].acName)
00398 .SetUnit(LoudnessParameterDescription[i].acUnit)
00399 .SetDescription(LoudnessParameterDescription[i].acDescription)
00400 .SetRangeMin(LoudnessParameterDescription[i].fRangeMin)
00401 .SetRangeMax(LoudnessParameterDescription[i].fRangeMax)
00402 .SetDefaultValue(LoudnessParameterDescription[i].fDefaultValue)
00403 .SetQuantizedTo(LoudnessParameterDescription[i].fQuantizedTo)
00404 .SetIsChangeableInRealTime(LoudnessParameterDescription[i].bIsChangeableInRealTime)
00405 );
00406 }
00407
00408
00409 this->CalcFreqBounds ();
00410
00411
00412 m_pfHelpBuffer = zplfMalloc (iBlockSize);
00413 m_pfProcessBuffer = zplfMalloc (iBlockSize);
00414 m_ppCRingBuffer = new CRingBuffer<float>*[iNumberOfAudioChannels];
00415 for (iCh = 0; iCh < iNumberOfAudioChannels; iCh++)
00416 {
00417 m_ppCRingBuffer[iCh] = new CRingBuffer<float>(iBlockSize<<1);
00418 }
00419
00420
00421
00422 char acDescription[FEAPI_kMaxDescriptionLength];
00423
00424 int iNumOfResults = kNumFeatures * ((m_pfParameters[kParamChannelMode] == 0) ? 1 : iNumberOfAudioChannels);
00425 if (m_pfParameters[kParamChannelMode] == 0)
00426 {
00427 for (iCh = 0; iCh < iNumOfResults; ++iCh)
00428 {
00429 sprintf(acDescription, "%s", LoudnessFeatureDescription[iCh].acDescription);
00430 SetPluginResultPinInfo(CPin::SetIndex(iCh)
00431 .SetName(LoudnessFeatureDescription[iCh].acName)
00432 .SetUnit(LoudnessFeatureDescription[iCh].acUnit)
00433 .SetDescription(acDescription)
00434 .SetRangeMin(LoudnessFeatureDescription[iCh].fRangeMin)
00435 .SetRangeMax(LoudnessFeatureDescription[iCh].fRangeMax)
00436 .SetQuantizedTo(LoudnessFeatureDescription[iCh].fQuantizedTo)
00437 .SetSampleRate(1000.0F / m_pfParameters[kParamHopSize])
00438 );
00439 }
00440 }
00441 else
00442 {
00443 for (iCh = 0; iCh < iNumOfResults; ++iCh)
00444 {
00445 sprintf(acDescription, "Channel: %d;", iCh/iNumberOfAudioChannels);
00446 strcat(acDescription, LoudnessFeatureDescription[iCh/iNumberOfAudioChannels].acDescription);
00447 SetPluginResultPinInfo(CPin::SetIndex(iCh)
00448 .SetName(LoudnessFeatureDescription[iCh/iNumberOfAudioChannels].acName)
00449 .SetUnit(LoudnessFeatureDescription[iCh/iNumberOfAudioChannels].acUnit)
00450 .SetDescription(acDescription)
00451 .SetRangeMin(LoudnessFeatureDescription[iCh/iNumberOfAudioChannels].fRangeMin)
00452 .SetRangeMax(LoudnessFeatureDescription[iCh/iNumberOfAudioChannels].fRangeMax)
00453 .SetQuantizedTo(LoudnessFeatureDescription[iCh/iNumberOfAudioChannels].fQuantizedTo)
00454 .SetSampleRate(1000.0F / m_pfParameters[kParamHopSize])
00455 );
00456 }
00457 }
00458
00459 m_ppResults = new InternalResults_t*[iNumOfResults];
00460 m_ptLocalTimeStamp = new FEAPI_TimeStamp_t [iNumOfResults];
00461 for (iCh = 0; iCh < iNumOfResults; iCh++)
00462 {
00463 m_ppResults[iCh] = new InternalResults_t[m_iSizeOfResultBuffer];
00464 memset (m_ppResults[iCh], 0, sizeof (InternalResults_t) * m_iSizeOfResultBuffer);
00465 }
00466 memset (m_ptLocalTimeStamp, 0, sizeof(FEAPI_TimeStamp_t)*iNumberOfAudioChannels);
00467
00468 zplfFFTDestroyInstance (m_pFFTInstance);
00469 zplfFFTCreateInstance (m_pFFTInstance, iBlockSize, (int)(m_pfParameters[kParamZeroPad]+.1F), CzplfFFT_If::_Fft_Windows_ ((int)(m_pfParameters[kParamWindowType] + .1F)));
00470
00471
00472 m_pFFTInstance->zplfGetWindow (m_pfProcessBuffer);
00473 zplfRealMul_I (m_pfProcessBuffer, m_pfProcessBuffer, iBlockSize);
00474 m_fNormFactor = 0;
00475 for (i = 0; i < iBlockSize; i++)
00476 m_fNormFactor += m_pfProcessBuffer[i];
00477 m_fNormFactor = 1/m_fNormFactor/(20e-6F);
00478
00479 this->AllocHRTables ();
00480
00481 return FEAPI_kNoError;
00482 }
00483
00484 FEAPI_Error_t CLoudness::SetPluginParameter (int iParameterIndex, float fValue)
00485 {
00486 if ((iParameterIndex >= this->GetPluginNumOfParameters ()) || (iParameterIndex < 0))
00487 return FEAPI_kUnspecifiedError;
00488
00489 if ((fValue < LoudnessParameterDescription[iParameterIndex].fRangeMin) || (fValue > LoudnessParameterDescription[iParameterIndex].fRangeMax))
00490 return FEAPI_kUnspecifiedError;
00491
00492 m_pfParameters[iParameterIndex] = fValue;
00493
00494
00495 if (iParameterIndex != kParamLowFreqBound)
00496 this->InitializePlugin (m_fSampleRate, this->GetPluginNumOfInputs (), 1, 0);
00497
00498 return FEAPI_kNoError;
00499 }
00500
00501
00502 float CLoudness::GetPluginParameter (int iParameterIndex)
00503 {
00504 if ((iParameterIndex >= this->GetPluginNumOfParameters ()) || (iParameterIndex < 0))
00505 return FEAPI_kUnspecifiedError;
00506
00507 return m_pfParameters[iParameterIndex];
00508 }
00509
00510
00511 int CLoudness::GetPluginResultLatency (int iResultIndex)
00512 {
00513 return (int)m_pfParameters[kParamBlockSize];
00514 }
00515
00516
00517 FEAPI_Error_t CLoudness::ProcessPluginDone ()
00518 {
00520 return FEAPI_kNoError;
00521 }
00522
00523 FEAPI_Error_t CLoudness::ProcessPlugin (const float **ppfInputBuffer, const FEAPI_TimeStamp_t *ptTimeStamps, int iNumberOfFrames)
00524 {
00525 bool bDownmixToMono = (m_pfParameters[kParamChannelMode] == 0)? true : false;
00526 int iCh,
00527 iIdx,
00528 iProcessBlockSize = (int)(m_pfParameters[kParamBlockSize]),
00529 iHopSize = (int)(m_pfParameters[kParamHopSize]*0.001F * m_fSampleRate + .1F),
00530 iStartIdx = (int)(m_pfParameters[kParamLowFreqBound] / m_fSampleRate * iProcessBlockSize),
00531 iNumFramesLeft = iNumberOfFrames,
00532 iNumInputChannels = this->GetPluginNumOfInputs (),
00533 iNumProcessChannels = this->GetPluginNumOfResults (),
00534 iSamplesInBuffer = 0;
00535
00536 if (!m_bIsInitialized)
00537 return FEAPI_kUnspecifiedError;
00538
00539
00540 if (ptTimeStamps)
00541 {
00542 for (iCh = 0; iCh < iNumInputChannels; iCh++)
00543 m_ptLocalTimeStamp[iCh] = ptTimeStamps[iCh] + iNumberOfFrames/m_fSampleRate;
00544 }
00545 else
00546 {
00547 for (iCh = 0; iCh < iNumInputChannels; iCh++)
00548 m_ptLocalTimeStamp[iCh] += iNumberOfFrames/m_fSampleRate;
00549 }
00550
00551
00552 while (m_ppCRingBuffer[0]->GetSamplesInBuffer () + iNumFramesLeft >= iProcessBlockSize)
00553 {
00554
00555 if (bDownmixToMono)
00556 {
00557 int iLength = (iHopSize < iNumFramesLeft) ? iHopSize : iNumFramesLeft;
00558 iNumProcessChannels = 1;
00559
00560 memcpy (m_pfProcessBuffer, &ppfInputBuffer[0][iNumberOfFrames - iNumFramesLeft], sizeof(float) * iLength);
00561 for (iCh = 1; iCh < iNumInputChannels; iCh++)
00562 {
00563 const float *pfBuffer = &ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft];
00564
00565 for (iIdx = 0; iIdx < iLength; iIdx++)
00566 m_pfProcessBuffer[iIdx] += pfBuffer[iIdx];
00567 }
00568
00569
00570 for (iIdx = 0; iIdx < iLength; iIdx++)
00571 m_pfProcessBuffer[iIdx] *= 1.0F/iNumInputChannels;
00572
00573 m_ppCRingBuffer[0]->PutPostInc (m_pfProcessBuffer, iLength);
00574 }
00575 else
00576 {
00577 for (iCh = 0; iCh < iNumInputChannels; iCh++)
00578 m_ppCRingBuffer[iCh]->PutPostInc (&ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft], (iHopSize < iNumFramesLeft) ? iHopSize : iNumFramesLeft);
00579 }
00580
00581
00582 iNumFramesLeft -= (iHopSize < iNumFramesLeft) ? iHopSize : iNumFramesLeft;
00583
00584
00585 iSamplesInBuffer = m_ppCRingBuffer[0]->GetSamplesInBuffer ();
00586
00587
00588 if (iSamplesInBuffer < iProcessBlockSize)
00589 continue;
00590
00591
00592 for (iCh = 0; iCh < iNumProcessChannels; iCh++)
00593 {
00594 float fSum = 0;
00595
00596
00597 m_ppCRingBuffer[iCh]->GetOff (m_pfProcessBuffer, iProcessBlockSize, 0);
00598 m_ppCRingBuffer[iCh]->SetReadPos (m_ppCRingBuffer[iCh]->GetReadPos () + iHopSize);
00599
00600
00601 m_ptLocalTimeStamp[iCh] = ptTimeStamps[iCh] + iNumberOfFrames/m_fSampleRate - (iSamplesInBuffer+iNumFramesLeft)/m_fSampleRate;
00602
00603
00604 m_pFFTInstance->zplfFFT (m_pfProcessBuffer, m_pfProcessBuffer);
00605
00606
00607 zplfCompAbs (m_pfProcessBuffer, m_pfProcessBuffer, iProcessBlockSize>>1);
00608
00609
00610 zplfSetZero (&m_pfProcessBuffer[iProcessBlockSize>>1], iProcessBlockSize>>1);
00611
00612
00613 zplfRealMulC_I (m_pfProcessBuffer, m_fNormFactor * m_fRMSFullScaleLevel/kReferenceLevel, iProcessBlockSize>>1);
00614
00615
00616 zplfRealMul_I (m_pfProcessBuffer, m_pfProcessBuffer, iProcessBlockSize>>1);
00617
00618
00619 this->WriteResult (kLoudness1 * iNumProcessChannels + iCh, this->GetDinLoudness (), m_ptLocalTimeStamp[iCh]);
00620 this->WriteResult (kLoudness2 * iNumProcessChannels + iCh, this->GetHRLoudness (), m_ptLocalTimeStamp[iCh]);
00621 }
00622 }
00623
00624
00625 if (iNumFramesLeft > 0)
00626 {
00627
00628 if (bDownmixToMono)
00629 {
00630
00631 memcpy (m_pfProcessBuffer, &ppfInputBuffer[0][iNumberOfFrames - iNumFramesLeft], sizeof(float) * iNumFramesLeft);
00632 for (iCh = 1; iCh < iNumInputChannels; iCh++)
00633 {
00634 const float *pfBuffer = &ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft];
00635
00636 for (iIdx = 0; iIdx < iNumFramesLeft; iIdx++)
00637 m_pfProcessBuffer[iIdx] += pfBuffer[iIdx];
00638 }
00639
00640 for (iIdx = 0; iIdx < iHopSize; iIdx++)
00641 m_pfProcessBuffer[iIdx] *= 1.0F/iNumInputChannels;
00642
00643 m_ppCRingBuffer[0]->PutPostInc (m_pfProcessBuffer, iNumFramesLeft);
00644 }
00645 else
00646 {
00647 for (iCh = 0; iCh < iNumInputChannels; iCh++)
00648 m_ppCRingBuffer[iCh]->PutPostInc (&ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft], iNumFramesLeft);
00649 }
00650 }
00651
00652 return FEAPI_kNoError;
00653 }
00654
00655 int CLoudness::GetPluginSizeOfResult (int iResultIndex)
00656 {
00657 if ((iResultIndex >= this->GetPluginNumOfResults ()) || (iResultIndex < 0))
00658 return -1;
00659
00660 if (m_ppResults[iResultIndex][0].bHoldsResult == true)
00661 return 1;
00662 else
00663 return 0;
00664 }
00665
00666
00667 FEAPI_Error_t CLoudness::GetPluginResult (int iResultIndex, float *pfResult, FEAPI_TimeStamp_t *ptTimeStamp)
00668 {
00669 if ((iResultIndex >= this->GetPluginNumOfResults ()) || (iResultIndex < 0))
00670 return FEAPI_kUnspecifiedError;
00671
00672 if (m_ppResults[iResultIndex][0].bHoldsResult == false)
00673 return FEAPI_kUnspecifiedError;
00674
00675 pfResult[0] = m_ppResults[iResultIndex][0].fResult;
00676 ptTimeStamp[0] = m_ppResults[iResultIndex][0].tTimeStamp;
00677
00678 memmove (&m_ppResults[iResultIndex][0], &m_ppResults[iResultIndex][1], (m_iSizeOfResultBuffer - 1)*sizeof(InternalResults_t));
00679 m_ppResults[iResultIndex][m_iSizeOfResultBuffer-1].bHoldsResult = false;
00680
00681 return FEAPI_kNoError;
00682 }
00683
00684
00685 FEAPI_Error_t CLoudness::ResetPlugin ()
00686 {
00687 for (int iCh = 0; iCh < this->GetPluginNumOfInputs (); iCh++)
00688 {
00689 m_ppCRingBuffer[iCh]->Reset ();
00690 m_ptLocalTimeStamp[iCh] = 0;
00691 }
00692 return FEAPI_kNoError;
00693 }
00694
00695
00696 float CLoudness::GetPluginProperty ( FEAPI_PluginProperty_t ePluginProperty)
00697 {
00698 switch (ePluginProperty)
00699 {
00700 case FEAPI_kMinSampleRate:
00701 {
00702 return 1;
00703 }
00704 case FEAPI_kMaxSampleRate:
00705 {
00706 return 1e38F;
00707 }
00708 case FEAPI_kMinChannels:
00709 {
00710 return 1;
00711 }
00712 case FEAPI_kMaxChannels:
00713 {
00714 return (float)((1<<30)-1);
00715 }
00716 case FEAPI_kMinFrameSize:
00717 {
00718 return 1;
00719 }
00720 case FEAPI_kMaxFrameSize:
00721 {
00722 return (float)((1<<30)-1);
00723 }
00724 case FEAPI_kOptFrameSize:
00725 {
00726 return floorf(m_pfParameters[kParamHopSize] * 0.001F * m_fSampleRate + .1F);
00727 }
00728 default:
00729 {
00730
00731 return -1;
00732 }
00733 }
00734 return -1;
00735 }
00736
00737 void CLoudness::WriteResult (int iResultIdx, float fValue, FEAPI_TimeStamp_t tTimeStamp)
00738 {
00739 int iCurrentIdx = 0;
00740
00741 ZASSERT (!m_ppResults);
00742
00743 for (iCurrentIdx = 0; iCurrentIdx < m_iSizeOfResultBuffer; iCurrentIdx++)
00744 {
00745 ZASSERT (!m_ppResults[iCurrentIdx]);
00746 if (m_ppResults[iResultIdx][iCurrentIdx].bHoldsResult == false)
00747 break;
00748 }
00749 if (iCurrentIdx == m_iSizeOfResultBuffer)
00750 {
00751
00752 m_iSizeOfResultBuffer <<= 1;
00753 for (int i = 0; i < this->GetPluginNumOfResults (); i++)
00754 {
00755 InternalResults_t *pTmp = new InternalResults_t[m_iSizeOfResultBuffer];
00756 memcpy (pTmp, m_ppResults[i], (m_iSizeOfResultBuffer>>1) * sizeof(InternalResults_t));
00757 memset (&pTmp[(m_iSizeOfResultBuffer>>1)], 0, (m_iSizeOfResultBuffer>>1) * sizeof(InternalResults_t));
00758 delete [] m_ppResults[i];
00759 m_ppResults[i] = 0;
00760 m_ppResults[i] = pTmp;
00761 }
00762 }
00763
00764 m_ppResults[iResultIdx][iCurrentIdx].bHoldsResult = true;
00765 m_ppResults[iResultIdx][iCurrentIdx].fResult = fValue;
00766 m_ppResults[iResultIdx][iCurrentIdx].tTimeStamp = tTimeStamp;
00767
00768 return;
00769 }
00770
00771 void CLoudness::CalcFreqBounds ()
00772 {
00773 #ifdef FREQ_VALUES_FROM_TABLE
00774
00775 m_iNumOfDINThirdBands = 28;
00776 m_iNumOfDINCritBands = 20;
00777
00778 const float afMidFreqs[] =
00779 {
00780 25,
00781 31.5F,
00782 40,
00783 50,
00784 63,
00785 80,
00786 100,
00787 125,
00788 160,
00789 200,
00790 250,
00791 315,
00792 400,
00793 500,
00794 630,
00795 800,
00796 1000,
00797 1250,
00798 1600,
00799 2000,
00800 2500,
00801 3150,
00802 4000,
00803 5000,
00804 6300,
00805 8000,
00806 10000,
00807 12500
00808 };
00809
00810 float fDownFactor = powf (2.0F, -1/6.0F),
00811 fUpFactor = 1.0F/fDownFactor;
00812
00813 int i;
00814
00815 ZASSERT (m_pDINFreqBands != 0);
00816
00817
00818 m_pDINFreqBands = new FrequencyBands_t [m_iNumOfDINThirdBands];
00819 m_pfDINBandLevels = new float [m_iNumOfDINThirdBands];
00820
00821 for (i = 0; i < m_iNumOfDINThirdBands; i++)
00822 {
00823 m_pDINFreqBands[i].fMidFreq = afMidFreqs[i];
00824 m_pDINFreqBands[i].fLowFreqBound = afMidFreqs[i] * fDownFactor;
00825 m_pDINFreqBands[i].fUpFreqBound = afMidFreqs[i] * fUpFactor;
00826
00827 m_pDINFreqBands[i].fMidBark = loudFreq2Bark (m_pDINFreqBands[i].fMidFreq);
00828 m_pDINFreqBands[i].fLowBarkBound = loudFreq2Bark (m_pDINFreqBands[i].fLowFreqBound);
00829 m_pDINFreqBands[i].fUpBarkBound = loudFreq2Bark (m_pDINFreqBands[i].fUpFreqBound);
00830 }
00831
00832 #else
00833 #endif
00834
00835
00836 return;
00837 }
00838
00839 FEAPI_Error_t CLoudness::GetBandLevels (FrequencyBands_t *pFrequencyValues, float *pfBandLevels, int iNumOfBands, bool bDezibel)
00840 {
00841
00842 for (int i = 0; i < iNumOfBands; i++)
00843 {
00844 float fLowFrac = pFrequencyValues[i].fLowFreqBound/m_fSampleRate * m_pfParameters[kParamBlockSize],
00845 fHighFrac = pFrequencyValues[i].fUpFreqBound/m_fSampleRate * m_pfParameters[kParamBlockSize];
00846 int iLowBin = (int)ceil (fLowFrac),
00847 iHighBin = (int)floor(fHighFrac);
00848
00849 fLowFrac = iLowBin - fLowFrac;
00850 fHighFrac = fHighFrac - iHighBin;
00851 pfBandLevels[i] = fLowFrac * m_pfProcessBuffer[ZMAX(0,iLowBin-1)];
00852 pfBandLevels[i] += fHighFrac * m_pfProcessBuffer[ZMIN((int)(m_pfParameters[kParamBlockSize]*.5 - .5),iHighBin+1)];
00853 for (int j = iLowBin; j <= ZMIN((int)(m_pfParameters[kParamBlockSize]*.5 - .5),iHighBin+1); j++)
00854 pfBandLevels[i] += m_pfProcessBuffer[j];
00855 if (bDezibel)
00856 {
00857 pfBandLevels[i] = ZMAX (pfBandLevels[i], 1e-20F);
00858 pfBandLevels[i] = _10INVLN10 * logf ((pfBandLevels[i] ));
00859 }
00860
00861
00862 }
00863
00864 return FEAPI_kNoError;
00865 }
00866
00867 float CLoudness::GetDinLoudness ()
00868 {
00869 int i,
00870 j;
00871 float fLevelCorrection = 0,
00872 fLoudness = 0,
00873 fLoudnessLevel = 0;
00874 float afTempResults[11];
00875
00876 static const float afInputLevelRange [] = {45.0F, 55.0F, 65.0F, 71.0F, 80.0F, 90.0F, 100.0F, 120.0F};
00877
00878 static const float aafEqualLoudnessCorr[11][8] =
00879 {
00880 {-32.0F, -29.0F, -27.0F, -25.0F, -23.0F, -20.0F, -18.0F, -15.0F},
00881 {-24.0F, -22.0F, -19.0F, -17.0F, -16.0F, -14.0F, -12.0F, -10.0F},
00882 {-16.0F, -15.0F, -14.0F, -12.0F, -11.0F, -10.0F, -9.0F, -8.0F},
00883 {-10.0F, -10.0F, -9.0F, -9.0F, -7.0F, -6.0F, -6.0F, -4.0F},
00884 {-5.0F, -4.0F, -4.0F, -3.0F, -3.0F, -3.0F, -2.0F, -2.0F},
00885 { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F},
00886 {-7.0F, -7.0F, -6.0F, -5.0F, -4.0F, -4.0F, -3.0F, -3.0F},
00887 {-3.0F, -2.0F, -2.0F, -2.0F, -1.0F, -1.0F, -1.0F, -1.0F},
00888 { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F},
00889 {-2.0F, -2.0F, -2.0F, -2.0F, -1.0F, -1.0F, -1.0F, -1.0F},
00890 { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}
00891 };
00892
00893 static const float afOuterEarTransferFunction[] = {0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, - 0.5F, -1.6F, -3.2F, -5.4F, -5.6F, -4.0F, -1.5F, 2.0F, 5.0F, 12.0F};
00894
00895 static const float afDiffuseFieldCorrection[] = {0.0F, 0.0F, 0.5F, 0.9F, 1.2F, 1.6F, 2.3F, 2.8F, 3.0F, 2.0F, 0.0F, -1.4F, -2.0F, -1.9F, -1.0F, 0.5F, 3.0F, 4.0F, 4.3F, 4.0F};
00896
00897 static const float afAbsoluteThresholdOfHearing[] = {30, 18, 12, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};
00898
00899 static const float afThirdBandToCritBandLevels[] = {-0.25F, -0.6F, -0.8F, -0.8F, -0.5F, 0.0F, 0.5F, 1.1F, 1.5F, 1.7F, 1.8F, 1.8F, 1.7F, 1.6F, 1.4F, 1.2F, 0.8F, 0.5F, 0.0F, -0.5};
00900
00901 static const float afUpperBarkValue[] = {0.9F, 1.8F, 2.8F, 3.5F, 4.4F, 5.4F, 6.6F, 7.9F, 9.2F, 10.6F, 12.3F, 13.8F, 15.2F, 16.7F, 18.1F, 19.3F, 20.6F, 21.8F, 22.7F, 23.6F, 24.0};
00902
00903 static const float afSpecificLoudnessRange[] = {21.5F, 18.0F, 15.1F, 11.5F, 9.0F, 6.1F, 4.4F, 3.1F, 2.13F, 1.36F, 0.82F, 0.42F, 0.30F, 0.22F, 0.15F, 0.10F, 0.035F, 0.0};
00904
00905 static const float afUpperSlope[18][8] =
00906 {
00907 {13.00F, 8.20F, 6.30F, 5.50F, 5.50F, 5.50F, 5.50F, 5.50F},
00908 {9.00F, 7.50F, 6.00F, 5.10F, 4.50F, 4.50F, 4.50F, 4.50F},
00909 {7.80F, 6.70F, 5.60F, 4.90F, 4.40F, 3.90F, 3.90F, 3.90F},
00910 {6.20F, 5.40F, 4.60F, 4.00F, 3.50F, 3.20F, 3.20F, 3.20F},
00911 {4.50F, 3.80F, 3.60F, 3.20F, 2.90F, 2.70F, 2.70F, 2.70F},
00912 {3.70F, 3.00F, 2.80F, 2.35F, 2.20F, 2.20F, 2.20F, 2.20F},
00913 {2.90F, 2.30F, 2.10F, 1.90F, 1.80F, 1.70F, 1.70F, 1.70F},
00914 {2.40F, 1.70F, 1.50F, 1.35F, 1.30F, 1.30F, 1.30F, 1.30F},
00915 {1.95F, 1.45F, 1.30F, 1.15F, 1.10F, 1.10F, 1.10F, 1.10F},
00916 {1.50F, 1.20F, 0.94F, 0.86F, 0.82F, 0.82F, 0.82F, 0.82F},
00917 {0.72F, 0.67F, 0.64F, 0.63F, 0.62F, 0.62F, 0.62F, 0.62F},
00918 {0.59F, 0.53F, 0.51F, 0.50F, 0.42F, 0.42F, 0.42F, 0.42F},
00919 {0.40F, 0.33F, 0.26F, 0.24F, 0.22F, 0.22F, 0.22F, 0.22F},
00920 {0.27F, 0.21F, 0.20F, 0.18F, 0.17F, 0.17F, 0.17F, 0.17F},
00921 {0.16F, 0.15F, 0.14F, 0.12F, 0.11F, 0.11F, 0.11F, 0.11F},
00922 {0.12F, 0.11F, 0.10F, 0.08F, 0.08F, 0.08F, 0.08F, 0.08F},
00923 {0.09F, 0.08F, 0.07F, 0.06F, 0.06F, 0.06F, 0.06F, 0.05F},
00924 {0.06F, 0.05F, 0.03F, 0.02F, 0.02F, 0.02F, 0.02F, 0.02F}
00925 };
00926
00927
00928 this->GetBandLevels (m_pDINFreqBands, m_pfDINBandLevels, m_iNumOfDINThirdBands);
00929
00931
00932
00933
00934
00935 for (i = 0; i < 11; i++)
00936 {
00937 j = 0;
00938 while (j < 7)
00939 {
00940 if (m_pfDINBandLevels[i] <= afInputLevelRange[j] - aafEqualLoudnessCorr[i][j])
00941 {
00942 afTempResults[i] = m_pfDINBandLevels[i] + aafEqualLoudnessCorr[i][j];
00943 afTempResults[i] = ZPOW10 (afTempResults[i]*.1F);
00944 break;
00945 }
00946 else
00947 j++;
00948 }
00949 }
00950
00951
00952 m_pfDINBandLevels[0] = _10INVLN10*logf(ZMAX (1e-6F, afTempResults[0] + afTempResults[1] + afTempResults[2] + afTempResults[3] + afTempResults[4] + afTempResults[5]));
00953 m_pfDINBandLevels[1] = _10INVLN10*logf(ZMAX (1e-6F, afTempResults[6] + afTempResults[7] + afTempResults[8]));
00954 m_pfDINBandLevels[2] = _10INVLN10*logf(ZMAX (1e-6F, afTempResults[9] + afTempResults[10]));
00955 for (i = 11; i < m_iNumOfDINThirdBands; i++)
00956 m_pfDINBandLevels[i-8] = m_pfDINBandLevels[i];
00957
00958
00959 for (i = 0; i < m_iNumOfDINCritBands; i++)
00960 {
00961
00962 m_pfDINBandLevels[i] -= afOuterEarTransferFunction[i];
00963
00964
00965 if (m_bDiffuseFieldCorrected)
00966 m_pfDINBandLevels[i] += afDiffuseFieldCorrection[i];
00967
00968 if (m_pfDINBandLevels[i] > afAbsoluteThresholdOfHearing[i])
00969 {
00970 float fS = .25F;
00971
00972
00973 m_pfDINBandLevels[i] -= afThirdBandToCritBandLevels[i];
00974
00975
00976 m_pfDINBandLevels[i] = 0.0635F * ZPOW10 (.25F * .1F * afAbsoluteThresholdOfHearing[i]) *
00977 (sqrtf(sqrtf(1-fS+fS*ZPOW10(.1F*(m_pfDINBandLevels[i]-afAbsoluteThresholdOfHearing[i]))))-1);
00978 m_pfDINBandLevels[i] = ZMAX (0, m_pfDINBandLevels[i]);
00979 }
00980 else
00981 m_pfDINBandLevels[i] = 0;
00982 }
00983 for (i = m_iNumOfDINCritBands; i < m_iNumOfDINThirdBands; i++)
00984 m_pfDINBandLevels[i] = 0;
00985
00986
00987 fLevelCorrection = .4F + .32F*powf(m_pfDINBandLevels[0],.2F);
00988 if (fLevelCorrection < 1)
00989 m_pfDINBandLevels[0] *= fLevelCorrection;
00990
00991
00992 j = 0;
00993 float fLowBarkValue = 0;
00994 float fNPreviousBand = 0;
00995 for (i = 0; i <= m_iNumOfDINCritBands; i++)
00996 {
00997 float fNCurrent = 0;
00998 while (fLowBarkValue < afUpperBarkValue[i])
00999 {
01000 float fUpBarkValue = afUpperBarkValue[i];
01001 if (fNPreviousBand <= m_pfDINBandLevels[i])
01002 {
01003
01004 for (j = 0; j < 18; j++)
01005 if (afSpecificLoudnessRange[j] < m_pfDINBandLevels[i])
01006 break;
01007
01008
01009 fNCurrent = m_pfDINBandLevels[i];
01010 fLoudness += (fUpBarkValue - fLowBarkValue) * fNCurrent;
01011 }
01012 else
01013 {
01014 float fDeltaBark = 0;
01015 fNCurrent = ZMAX (m_pfDINBandLevels[i], afSpecificLoudnessRange[j]);
01016 fDeltaBark = (fNPreviousBand - fNCurrent) / afUpperSlope [j][ZMIN(i-1,7)];
01017 fUpBarkValue = fLowBarkValue + fDeltaBark;
01018 if (fUpBarkValue > afUpperBarkValue[i])
01019 {
01020 fUpBarkValue= afUpperBarkValue[i];
01021 fDeltaBark = fUpBarkValue - fLowBarkValue;
01022 fNCurrent = fNPreviousBand - fDeltaBark * afUpperSlope [j][ZMIN(i-1,7)];
01023 }
01024 fLoudness += fDeltaBark * .5F * (fNCurrent + fNPreviousBand);
01025 }
01026
01027
01028
01029 while (j < 17)
01030 {
01031 if (fNCurrent <= afSpecificLoudnessRange[j])
01032 j++;
01033 else
01034 break;
01035 }
01036 if (fNCurrent <= afSpecificLoudnessRange[j] && j >= 17)
01037 j = 17;
01038
01039
01040 fLowBarkValue = fUpBarkValue;
01041 fNPreviousBand = fNCurrent;
01042 }
01043 }
01044
01045 fLoudnessLevel = (fLoudness >= 1)? 40 + 10.0F*_INVLN2*logf (fLoudness) : 40*powf (fLoudness + 0.0005F, 0.35F);
01046
01047 return fLoudnessLevel;
01048 }
01049
01050 float CLoudness::GetHRLoudness ()
01051 {
01052
01053 zplfRealMul_I (m_pfProcessBuffer, m_stInternalTables.pfOuterEarTransferFunction, ((int)(m_pfParameters[kParamBlockSize]+.1F))>>1);
01054
01055
01056 this->GetBandLevels (m_stInternalTables.pstFrequencyBands, m_pfHRBandLevels, m_iNumOfCritBands, false);
01057
01058
01059
01060
01061 this->CalcSpreading (m_pfHRBandLevels, m_pfExcitationPatterns);
01062
01063
01064
01065
01066 return this->CalcSpecLoudness ();
01067
01068 }
01069
01070 float CLoudness::CalcSpecLoudness ()
01071 {
01072 float *pfATH = m_stInternalTables.pfATH,
01073 *pfThreshIdx = m_stInternalTables.pfThreshIdx,
01074 fLoudness = 0;
01075
01076 int i;
01077 for (i = 0; i < m_iNumOfCritBands; i++)
01078 {
01079
01080
01081 m_pfExcitationPatterns[i] = powf (pfATH[i]/pfThreshIdx[i], .23F) * (powf(1-pfThreshIdx[i]+pfThreshIdx[i]*m_pfExcitationPatterns[i]/pfATH[i], .23F)-1);
01082 fLoudness += ZMAX(0,0.068F*m_pfExcitationPatterns[i]);
01083 }
01084
01085 return fLoudness;
01086 }
01087
01088 FEAPI_Error_t CLoudness::CalcSpreading (float *pfBandLevels, float *pfResult)
01089 {
01090
01091
01092 int iBarkj,
01093 iBarkk,
01094 iNumOfBands = m_iNumOfCritBands;
01095
01096 float fTmp1,
01097 fTmp2,
01098 fSlope,
01099 fScale = sqrtf(8/3),
01100 fBRes = loudFreq2Bark (.5F*m_fSampleRate, 2)/m_iNumOfCritBands,
01101 *pfEnPowTmp = m_pfProcessBuffer,
01102 *pfSlopeUp = m_pfHelpBuffer;
01103 float *pfSlope = m_stInternalTables.pfSlopeSpread,
01104 *pfNorm = m_stInternalTables.pfNormSpread;
01105
01106
01107 memset (pfResult, 0, sizeof(float)*iNumOfBands);
01108
01109 fSlope = expf ( -fBRes * 2.7F * _LN10);
01110 fTmp2 = 1.0F / (1.0F - fSlope);
01111 for (iBarkj = 0; iBarkj < iNumOfBands; iBarkj++)
01112 {
01113 pfSlopeUp[iBarkj] = pfSlope[iBarkj] * powf (pfBandLevels[iBarkj]*fScale, .2F * fBRes);
01114 fTmp1 = (1.0F - loudIntPow(fSlope, iBarkj+1)) * fTmp2;
01115 fTmp2 = (1.0F - loudIntPow(pfSlopeUp[iBarkj], iNumOfBands - iBarkj)) / (1.0F - pfSlopeUp[iBarkj]);
01116 if (pfBandLevels[iBarkj] < 1e-20F)
01117 {
01118 pfSlopeUp[iBarkj] = 0;
01119 pfEnPowTmp[iBarkj] = 0;
01120 continue;
01121 }
01122 pfSlopeUp[iBarkj] = expf (0.4F * logf (pfSlopeUp[iBarkj]));
01123 pfEnPowTmp[iBarkj] = expf (0.4F * logf (pfBandLevels[iBarkj]/(fTmp1 + fTmp2 -1)));
01124 }
01125 fSlope = expf ( 0.4F * logf (fSlope));
01126
01127
01128 pfResult[iNumOfBands-1] = pfEnPowTmp[iNumOfBands-1];
01129 for (iBarkk = iNumOfBands-2; iBarkk >= 0; iBarkk--)
01130 pfResult[iBarkk] = pfEnPowTmp[iBarkk] + pfResult[iBarkk + 1] * fSlope;
01131
01132
01133 for (iBarkj = 0; iBarkj < iNumOfBands-1; iBarkj++)
01134 {
01135 fSlope = pfSlopeUp[iBarkj];
01136 fTmp1 = pfEnPowTmp[iBarkj];
01137 for (iBarkk = iBarkj+1; iBarkk < iNumOfBands; iBarkk++)
01138 {
01139 double dTmp1 = fTmp1 * fSlope;
01140 fTmp1 = (dTmp1 < 1e-30)? 0 : (float)dTmp1;
01141 pfResult[iBarkk] += fTmp1;
01142 }
01143 }
01144
01145
01146 for (iBarkk = 0; iBarkk < iNumOfBands; iBarkk++)
01147 {
01148 pfResult[iBarkk] = sqrtf (pfResult[iBarkk]);
01149 pfResult[iBarkk] *= ZSQR(ZSQR(pfResult[iBarkk]));
01150 pfResult[iBarkk] *= pfNorm[iBarkk];
01151 }
01152 return FEAPI_kNoError;
01153 }
01154
01155 FEAPI_Error_t CLoudness::AllocHRTables ()
01156 {
01157 int i,
01158 iBlockSize = ((int)(m_pfParameters[kParamBlockSize]+.1F))>>1;
01159
01160
01161
01162 {
01163 m_stInternalTables.pfOuterEarTransferFunction = zplfMalloc (iBlockSize);
01164 for (i = 0; i < iBlockSize; i++)
01165 {
01166 double dTmp;
01167 float fkFreq = i * .5e-3F * m_fSampleRate / iBlockSize;
01168 dTmp = 6.5 * exp (-.6 * ZSQR(fkFreq-3.3F));
01169 m_stInternalTables.pfOuterEarTransferFunction[i] = (dTmp > 1e-37)? (float)dTmp : 0;
01170 if (fkFreq < 1e-10)
01171 {
01172 m_stInternalTables.pfOuterEarTransferFunction[i] = 0;
01173 continue;
01174 }
01175 m_stInternalTables.pfOuterEarTransferFunction[i] -= 1e-3F * powf (fkFreq, -3.6F);
01176 if (m_stInternalTables.pfOuterEarTransferFunction[i] < -120)
01177 m_stInternalTables.pfOuterEarTransferFunction[i] = 0;
01178 else
01179 m_stInternalTables.pfOuterEarTransferFunction[i] = ZPOW10 (.05 *m_stInternalTables.pfOuterEarTransferFunction[i]);
01180 }
01181 }
01182
01183
01184 {
01185 float fBarkResolution = loudFreq2Bark (.5F*m_fSampleRate, 2)/m_iNumOfCritBands;
01186 m_stInternalTables.pstFrequencyBands = new FrequencyBands_t [m_iNumOfCritBands];
01187 for (i = 0; i < m_iNumOfCritBands; i++)
01188 {
01189 m_stInternalTables.pstFrequencyBands[i].fLowBarkBound = i*fBarkResolution;
01190 m_stInternalTables.pstFrequencyBands[i].fMidBark = (i+.5F)*fBarkResolution;
01191 m_stInternalTables.pstFrequencyBands[i].fUpBarkBound = (i+1)*fBarkResolution;
01192
01193 m_stInternalTables.pstFrequencyBands[i].fLowFreqBound = loudBark2Freq (m_stInternalTables.pstFrequencyBands[i].fLowBarkBound, 2);
01194 m_stInternalTables.pstFrequencyBands[i].fMidFreq = loudBark2Freq (m_stInternalTables.pstFrequencyBands[i].fMidBark, 2);
01195 m_stInternalTables.pstFrequencyBands[i].fUpFreqBound = loudBark2Freq (m_stInternalTables.pstFrequencyBands[i].fUpBarkBound, 2);
01196 }
01197 m_pfHRBandLevels = new float [m_iNumOfCritBands];
01198 m_pfExcitationPatterns = new float [m_iNumOfCritBands];
01199 m_stInternalTables.pfSlopeSpread = new float [m_iNumOfCritBands];
01200 m_stInternalTables.pfNormSpread = new float [m_iNumOfCritBands];
01201 m_stInternalTables.pfATH = new float [m_iNumOfCritBands];
01202 m_stInternalTables.pfThreshIdx = new float [m_iNumOfCritBands];
01203 memset (m_stInternalTables.pfNormSpread, 0, sizeof(float)*m_iNumOfCritBands);
01204
01205 for (i = 0; i < m_iNumOfCritBands; i++)
01206 {
01207 int cBarkk;
01208 float fAtt = 1.0F,
01209 fNorm = 1.0F,
01210 fSlope = ZPOW10 (-2.7F * fBarkResolution);
01211
01212 m_stInternalTables.pfSlopeSpread[i] = 24.0F + 230.0F/m_stInternalTables.pstFrequencyBands[i].fMidFreq;
01213 m_stInternalTables.pfSlopeSpread[i] = ZPOW10 (-0.1F * fBarkResolution * m_stInternalTables.pfSlopeSpread[i]);
01214 m_stInternalTables.pfThreshIdx[i] = -2-2.05F*atanf(m_stInternalTables.pstFrequencyBands[i].fMidFreq/4000)-.7F*atan(ZSQR(m_stInternalTables.pstFrequencyBands[i].fMidFreq/1600));
01215 m_stInternalTables.pfThreshIdx[i] = ZPOW10 (.1F * m_stInternalTables.pfThreshIdx[i]);
01216 m_stInternalTables.pfATH[i] = 3.64F * powf (1e-3F * m_stInternalTables.pstFrequencyBands[i].fMidFreq, -.8F);
01217 m_stInternalTables.pfATH[i] = ZPOW10 (.1F * m_stInternalTables.pfATH[i]);
01218
01219 m_pfProcessBuffer[i] = 1.0F;
01220
01221 for (cBarkk = i; cBarkk > 0; cBarkk--)
01222 {
01223 double dTmp = fAtt * fSlope;
01224 fAtt = (dTmp < 1e-30F) ? 0 : (float) dTmp;
01225
01226 m_pfProcessBuffer[cBarkk-1] = fAtt;
01227 fNorm += fAtt;
01228 }
01229
01230
01231
01232 fAtt = 1.0F;
01233
01234
01235 for (cBarkk = i; cBarkk < m_iNumOfCritBands-1; cBarkk++)
01236 {
01237 double dTmp = fAtt * m_stInternalTables.pfSlopeSpread[i];
01238 fAtt = (dTmp < 1e-30F) ? 0 : (float) dTmp;
01239
01240 m_pfProcessBuffer[cBarkk+1] = fAtt;
01241 fNorm += fAtt;
01242 }
01243
01244 fNorm = 1.0F/fNorm;
01245
01246
01247 for (cBarkk = 0; cBarkk < m_iNumOfCritBands; cBarkk++)
01248 {
01249 m_pfProcessBuffer[cBarkk] *= fNorm;
01250 m_stInternalTables.pfNormSpread[cBarkk] += powf (m_pfProcessBuffer[cBarkk], 0.4F);
01251 }
01252 }
01253 for (i = 0; i < m_iNumOfCritBands; i++)
01254 m_stInternalTables.pfNormSpread[i] = powf (m_stInternalTables.pfNormSpread[i], -2.5F);
01255 }
01256
01257
01258 return FEAPI_kNoError;
01259 }
01260
01262
01263 #ifdef __cplusplus
01264 extern "C" {
01265 #endif
01266
01267 FEAPI_ENTRY_POINTS(CLoudness)
01268
01269 #ifdef __cplusplus
01270 }
01271 #endif
01272