Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

FEAPIExamplePluginLoudness.cpp

Go to the documentation of this file.
00001 
00002 //          /*!  \file  FEAPIExamplePluginLoudness.cpp:  \brief  implementation  of  the  CLoudnessFeatures  class.  */
00003 //
00004 //        Copyright (c) 2004-2006  
00005 //        zplane.development
00006 //        Flohrer Lerch Schwerdtfeger GbR
00007 //        All rights reserved.
00008 //
00009 //    This program is free software; you can redistribute it and/or modify
00010 //    it under the terms of the GNU General Public License as published by
00011 //    the Free Software Foundation; either version 2 of the License, or
00012 //    (at your option) any later version.
00013 //
00014 //    This program is distributed in the hope that it will be useful,
00015 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 //    GNU General Public License for more details.
00018 //
00019 //    You should have received a copy of the GNU General Public License
00020 //    along with this program; if not, write to the Free Software
00021 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 //  defines  for  plug  in  name  etc.
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     //Name,                                                                          Unit,              Description,                                                                                                                                                                                                                                        RangeMin,                      RangeMax,                              Default,        Quantized,            Realtime
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     //Name,                                                                          Unit,              Description,                                                                                                                                                                                                                                                                RangeMin,                      RangeMax,                              Quantized                              SampleRate
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:  //  zwicker
00205         fBark      =  13.0F  *  atanf  (0.00076F*fFrequency)  +  3.5F  *  atanf  (ZSQR(fFrequency/7500.0F));
00206         break;
00207     case  1:  //  terhardt
00208         fBark      =  13.3F  *  atanf  (0.00075F*fFrequency);
00209         break;
00210     case  2:  //  schroeder
00211         fFrequency  /=  650;
00212         fBark              =  7.0F  *  logf  (fFrequency  +  sqrtf  (ZSQR(fFrequency)  +  1));  //  7*asinh  (fFrequency/650);
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:  //  terhardt
00226         fFrequency    =  4*1000.0F/3  *  tan  (fBark/13.3F);
00227         break;
00228     case  2:  //  schroeder
00229         fFrequency    =  650.0F  *  sinhf  (fBark/7);  //  asinh  (fFrequency/650);
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     //m_iNumberOfParameters       =  kNumParameters;
00267     m_iSizeOfResultBuffer       =  kDefaultNumOfResults;
00268     
00269     //  set  strings  that  will  be  returned  by  the  default  methods
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     //  set  plug  in  version  info
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     //  free  already  allocated  memory
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     // Setting information about the plugin inputs
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     // Setting information about the plugin parameters
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     //  calculate  frequency  boundaries
00409     this->CalcFreqBounds  ();
00410     
00411     //  allocate  ringbuffers  and  memory  for  results  and  temp  memory  for  processing
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     // Setting information about the plugin results
00422     char acDescription[FEAPI_kMaxDescriptionLength];
00423     //int  iNumOfChannels =  (m_pfParameters[kParamChannelMode]  ==  0)  ?  1  :  iNumberOfAudioChannels;
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     //  get  normalization  factor  for  psd
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     //  since  all  other  parameters  are  non-realtime  parameters,  we  can  call  initialize  here  for  simplicity
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 (), // either 1 or num of channels...,
00534             iSamplesInBuffer        =  0;
00535     
00536     if  (!m_bIsInitialized)
00537         return  FEAPI_kUnspecifiedError;
00538     
00539     //  do  time  stamp  handling,  in  both  cases:  no/defined  time  stamp
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     //  if  there  are  sufficient  frames  to  process,  do  it!
00552     while  (m_ppCRingBuffer[0]->GetSamplesInBuffer  ()  +  iNumFramesLeft  >=  iProcessBlockSize)
00553     {
00554         //  check  if  we  have  to  downmix  to  mono  or  not
00555         if (bDownmixToMono)
00556         {
00557             int iLength = (iHopSize < iNumFramesLeft) ? iHopSize : iNumFramesLeft;
00558             iNumProcessChannels = 1;
00559             // downmix and write to buffer, decr numframesleft
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             // scale downmixed signal
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         //  decrement  number  of  frames  left  in  ppfInputBuffer
00582         iNumFramesLeft     -= (iHopSize < iNumFramesLeft) ? iHopSize : iNumFramesLeft;
00583         
00584         //  get  the  current  number  of  sample  in  ring  buffer
00585         iSamplesInBuffer        =  m_ppCRingBuffer[0]->GetSamplesInBuffer  ();
00586         
00587         //  if  there  are  not  enough  sample  in  ring  buffer,  go  on
00588         if  (iSamplesInBuffer  <  iProcessBlockSize)
00589             continue;
00590         
00591         //  now  do  the  processing
00592         for  (iCh  =  0;  iCh  <  iNumProcessChannels;  iCh++)
00593         {
00594             float      fSum    =  0;
00595             
00596             //  get  data  from  ring  buffer  and  increment  read  pointer
00597             m_ppCRingBuffer[iCh]->GetOff  (m_pfProcessBuffer,  iProcessBlockSize,  0);
00598             m_ppCRingBuffer[iCh]->SetReadPos  (m_ppCRingBuffer[iCh]->GetReadPos  ()  +  iHopSize);
00599             
00600             //  adjust  time  stamp
00601             m_ptLocalTimeStamp[iCh]  = ptTimeStamps[iCh] + iNumberOfFrames/m_fSampleRate - (iSamplesInBuffer+iNumFramesLeft)/m_fSampleRate;
00602             
00603             //  calc  fft
00604             m_pFFTInstance->zplfFFT  (m_pfProcessBuffer,  m_pfProcessBuffer);
00605     
00606             //  calc  abs
00607             zplfCompAbs  (m_pfProcessBuffer,  m_pfProcessBuffer,  iProcessBlockSize>>1);
00608 
00609             // set remaining values to zero (just for security)
00610             zplfSetZero (&m_pfProcessBuffer[iProcessBlockSize>>1], iProcessBlockSize>>1);
00611     
00612             //  normalize  spectral  values
00613             zplfRealMulC_I  (m_pfProcessBuffer,  m_fNormFactor * m_fRMSFullScaleLevel/kReferenceLevel,  iProcessBlockSize>>1);
00614     
00615             //  calc  power
00616             zplfRealMul_I  (m_pfProcessBuffer,  m_pfProcessBuffer,  iProcessBlockSize>>1);
00617             
00618             // store results
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     //  if  there  are  frames  left  in  ppfInputBuffer,  handle  them  here
00625     if (iNumFramesLeft > 0)
00626     {
00627         // write remaining frames to ringbuffer (distinguish downmix or not..., decr numframesleft)
00628         if (bDownmixToMono)
00629         {
00630             // downmix and write to buffer
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             // scale downmixed signal
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             //  this  shall  never  happen  ...
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         //  alloc  new  memory
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     //  number  of  frequency  bands
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     //  alloc  freq  table  and  filters
00818     m_pDINFreqBands            =  new  FrequencyBands_t  [m_iNumOfDINThirdBands];
00819     m_pfDINBandLevels          =  new  float  [m_iNumOfDINThirdBands];
00820     //  fill  freq  table
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     //  filter  bank  or  fft  based?
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 //        else
00861 //            pfBandLevels[i]    /= 20e-6F*20e-6F;
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     // DIN: RAP
00876     static const float afInputLevelRange []     = {45.0F,  55.0F,  65.0F,  71.0F,  80.0F,  90.0F,  100.0F,  120.0F}; 
00877     // DIN: DLL
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     // DIN: AO
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     // DIN: DDF
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     // DIN: LTQ
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     // DIN: DCB
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     // DIN: ZUP
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     // DIN: RNS
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     // DIN: USL
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     //  get  band  levels
00928     this->GetBandLevels  (m_pDINFreqBands, m_pfDINBandLevels, m_iNumOfDINThirdBands);
00929 
00931     // now the DIN part
00932 
00933     //  adjust  all  third  bands  below  315Hz  acc.  to  equal  loudness  contours
00934     //  naturally,  make  this  dependent  of  the  input  level  range
00935     for  (i  =  0;  i  <  11;  i++)        //  i  is  band  index
00936     {
00937         j  =  0;
00938         while  (j  <  7)                      //  j  is  level  range  index
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     //  sum  to  get  first  three  critical  bands  and  move  other  third  bands
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     //  now  calculate  the  main  loudness
00959     for  (i  =  0;  i  <  m_iNumOfDINCritBands;  i++)
00960     {
00961         //  apply  outer  ear  transfer  function
00962         m_pfDINBandLevels[i]    -=  afOuterEarTransferFunction[i];
00963         
00964         //  apply  diffuse  field  correction
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             // do another level correction...
00973             m_pfDINBandLevels[i]  -= afThirdBandToCritBandLevels[i];
00974             
00975             // calculate the loudness 
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     // and another level correction for the lowest critical band...
00987     fLevelCorrection    = .4F + .32F*powf(m_pfDINBandLevels[0],.2F);
00988     if (fLevelCorrection < 1)
00989         m_pfDINBandLevels[0]  *= fLevelCorrection;
00990     
00991     // now to the complicated part... 
00992     j = 0;
00993     float   fLowBarkValue   = 0; // DIN: Z1
00994     float   fNPreviousBand  = 0; // DIN: N1
00995     for (i = 0; i <= m_iNumOfDINCritBands; i++) // there is one band more now....
00996     {
00997         float   fNCurrent   = 0;    // DIN: N2
00998         while (fLowBarkValue < afUpperBarkValue[i])        
00999         {
01000             float fUpBarkValue  = afUpperBarkValue[i]; // DIN: Z2
01001             if (fNPreviousBand <= m_pfDINBandLevels[i]) // no masking
01002             {
01003                 // adjust j for next iteration 
01004                 for (j = 0; j < 18; j++)
01005                     if (afSpecificLoudnessRange[j] < m_pfDINBandLevels[i])
01006                         break;
01007                     
01008                     // adjust current loundess estimate
01009                     fNCurrent   = m_pfDINBandLevels[i];
01010                     fLoudness  += (fUpBarkValue - fLowBarkValue) * fNCurrent;
01011             }
01012             else // now this is the hard to understand part
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             // adjust j for next iteration (probably redundant????)
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             // update variables
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     // weight with outer ear transfer function
01053     zplfRealMul_I (m_pfProcessBuffer, m_stInternalTables.pfOuterEarTransferFunction, ((int)(m_pfParameters[kParamBlockSize]+.1F))>>1);
01054     
01055     // group bands into bark scale
01056     this->GetBandLevels  (m_stInternalTables.pstFrequencyBands, m_pfHRBandLevels, m_iNumOfCritBands, false);
01057 
01058     // add internal noise here?
01059 
01060     // calculate spreading
01061     this->CalcSpreading (m_pfHRBandLevels, m_pfExcitationPatterns);
01062 
01063     // add simple time domain smearing
01064 
01065     // calculate specific loudness patterns
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 //        if (m_stInternalTables.pstFrequencyBands[i].fUpBarkBound>24)
01080 //            continue;
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]);// * (m_stInternalTables.pstFrequencyBands[i].fUpBarkBound-m_stInternalTables.pstFrequencyBands[i].fLowBarkBound); 
01083     }
01084 
01085     return fLoudness;
01086 }
01087 
01088 FEAPI_Error_t CLoudness::CalcSpreading (float *pfBandLevels, float *pfResult)
01089 {
01090     // this is level dependend adapted from ITU-R BS.1387
01091     
01092     int    iBarkj,                 // Masker
01093             iBarkk,                 // Maskee
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     // initialize pfResult
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     // lower slope
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     // upper slope
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     // normalization 
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     // outer ear transfer function
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     // frequency bands and spreading
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             // lower slope
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;                                             // nonnormalized masking threshold
01227                 fNorm                      += fAtt;                                             // normalization factor
01228             }
01229 
01230 
01231             // initialize new
01232             fAtt                            = 1.0F;
01233         
01234             // upper slope
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;                                             // normalization factor
01242             }
01243 
01244             fNorm                           = 1.0F/fNorm;
01245 
01246             // nonlinear superposition
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);            // resulting normalization pattern (eq. 19)
01255     }
01256     
01257     
01258     return  FEAPI_kNoError;
01259 }
01260 
01262 // entry points
01263 #ifdef __cplusplus                                                      
01264 extern "C" {                                                            
01265 #endif                                                              
01266 
01267 FEAPI_ENTRY_POINTS(CLoudness)
01268 
01269 #ifdef __cplusplus                                                  
01270 }                                                               
01271 #endif
01272 

Generated on Fri Mar 23 10:28:54 2007 for FEAPI Plugin Documentation by  doxygen 1.3.9.1