00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00037
00038
00039
00040 #include <string>
00041 #include <iostream>
00042 #include <math.h>
00043
00044 #include "zplVecLib.h"
00045
00046 #include "FEAPI.h"
00047 #include "FEAPIExamplePluginZeroCrossings.h"
00048 #include "FEAPIEntryPoints.h"
00049
00050 #ifndef FLT_MAX
00051 #define FLT_MAX 3.402823466e+38F
00052 #endif
00053
00054 #define kDefaultNumOfResults 8
00055
00057 #define _MY_MAJOR_VERSION 0x00000000
00058 #define _MY_MINOR_VERSION 0x00000000
00059 #define _MY_SUB_VERSION 0x00000001
00060
00061
00062
00063 #define _MY_PLUGIN_NAME "ZeroCrossings"
00064 #define _MY_PLUGIN_VENDOR "zplane.development"
00065 #define _MY_PLUGIN_DESCRIPTION "This PlugIn calculates the relative number of zero crossings per channel. A zero crossing is a sign change of two neibourghed samples."
00066 #define _MY_PLUGIN_COPYRIGHT "(c) 2005 by zplane.development"
00067 #define _MY_PLUGIN_ID "zplZeroCrossings"
00068
00069
00070
00071 #define kFeatureIndex 0
00072 #define kFeatureName "Relative number of Zero-Crossings"
00073 #define kFeatureUnit "-"
00074 #define kFeatureDescription "The number of zero crossings in the analysis block divided by the analysis block length"
00075 #define kFeatureRangeMin 0.0F
00076 #define kFeatureRangeMax 1.0F
00077 #define kFeatureIsQuantized -1 // value is not quantized
00078
00079 #define kParam1Index 0
00080 #define kParam1Name "Analysis Block Length"
00081 #define kParam1Unit "Frames"
00082 #define kParam1Description "Length of analysis window for one result"
00083 #define kParam1RangeMin 4
00084 #define kParam1RangeMax (float)((1<<30)-1)
00085 #define kParam1DefaultValue 1024
00086 #define kParam1QuantizedTo 4
00087 #define kParam1IsChangeableInRealTime false
00088
00089 #define kParam2Index 1
00090 #define kParam2Name "Analysis Hop-Size"
00091 #define kParam2Unit "ms"
00092 #define kParam2Description "Distance between two analysis block beginnings"
00093 #define kParam2RangeMin 1
00094 #define kParam2RangeMax (float)((1<<30)-1)
00095 #define kParam2DefaultValue 10
00096 #define kParam2QuantizedTo -1
00097 #define kParam2IsChangeableInRealTime false
00098
00099 #define kParam3Index 2
00100 #define kParam3Name "Individual Channels or Sum Channel"
00101 #define kParam3Unit ""
00102 #define kParam3Description "Determines wether the calculation should be done on the sum of all input channels ('0') or on each individual channel ('1')"
00103 #define kParam3RangeMin 0
00104 #define kParam3RangeMax 1
00105 #define kParam3DefaultValue 0
00106 #define kParam3QuantizedTo 1
00107 #define kParam3IsChangeableInRealTime false
00108
00109 enum MyParameters_t
00110 {
00111 kBlockSize = 0,
00112 kHopSize = 1,
00113 kChannelMode = 2,
00114
00115 kNumParameters
00116 };
00117
00118 CZeroCrossings::CZeroCrossings () : CFeatureExtractBase()
00119 {
00120
00121 zplVecLibDispatcher ();
00122
00123 m_ppCRingBuffer = 0;
00124 m_ppResults = 0;
00125 m_pfProcessBuffer = 0;
00126 m_ptLocalTimeStamp = 0;
00127
00128 m_iSizeOfResultBuffer = kDefaultNumOfResults;
00129
00130
00131 m_cPluginName = _MY_PLUGIN_NAME;
00132 m_cPluginVendor = _MY_PLUGIN_VENDOR;
00133 m_cPluginDescription = _MY_PLUGIN_DESCRIPTION;
00134 m_cPluginId = _MY_PLUGIN_ID;
00135 m_cPluginCopyRight = _MY_PLUGIN_COPYRIGHT;
00136
00137
00138 m_iMajorVersion = _MY_MAJOR_VERSION;
00139 m_iMinorVersion = _MY_MINOR_VERSION;
00140 m_iSubVersion = _MY_SUB_VERSION;
00141
00142 m_afParameters[kBlockSize] = kParam1DefaultValue;
00143 m_afParameters[kHopSize] = kParam2DefaultValue;
00144 m_afParameters[kChannelMode]= kParam3DefaultValue;
00145 }
00146
00147
00148 CZeroCrossings::~CZeroCrossings ()
00149 {
00150 int iCh;
00151 if (m_ppCRingBuffer)
00152 {
00153 for (iCh = 0; iCh < this->GetPluginNumOfInputs (); iCh++)
00154 {
00155 if (m_ppCRingBuffer[iCh])
00156 delete m_ppCRingBuffer[iCh];
00157 m_ppCRingBuffer[iCh] = 0;
00158 }
00159 delete [] m_ppCRingBuffer;
00160 m_ppCRingBuffer = 0;
00161 }
00162 if (m_ppResults)
00163 {
00164 for (iCh = 0; iCh < this->GetPluginNumOfResults (); iCh++)
00165 {
00166 if (m_ppResults[iCh])
00167 delete [] m_ppResults[iCh];
00168 m_ppResults[iCh] = 0;
00169 }
00170 delete [] m_ppResults;
00171 m_ppResults = 0;
00172 }
00173 if (m_ptLocalTimeStamp)
00174 delete [] m_ptLocalTimeStamp;
00175 m_ptLocalTimeStamp = 0;
00176
00177 zplfFree (m_pfProcessBuffer);
00178 }
00179
00180
00181 FEAPI_Error_t CZeroCrossings::InitializePlugin ( float fInputSampleRate,
00182 int iNumberOfAudioChannels,
00183 int iHostApiMajorVersion,
00184 FEAPI_UserData_t *pstUserData)
00185 {
00186 FEAPI_Error_t rErr;
00187 int iCh;
00188
00189
00190 if (m_ppCRingBuffer)
00191 {
00192 for (iCh = 0; iCh < this->GetPluginNumOfInputs (); iCh++)
00193 {
00194 if (m_ppCRingBuffer[iCh])
00195 delete m_ppCRingBuffer[iCh];
00196 m_ppCRingBuffer[iCh] = 0;
00197 }
00198 delete [] m_ppCRingBuffer;
00199 m_ppCRingBuffer = 0;
00200 }
00201 if (m_ppResults)
00202 {
00203 for (iCh = 0; iCh < this->GetPluginNumOfResults (); iCh++)
00204 {
00205 if (m_ppResults[iCh])
00206 delete [] m_ppResults[iCh];
00207 m_ppResults[iCh] = 0;
00208 }
00209 delete [] m_ppResults;
00210 m_ppResults = 0;
00211 }
00212 if (m_ptLocalTimeStamp)
00213 delete [] m_ptLocalTimeStamp;
00214 m_ptLocalTimeStamp = 0;
00215 zplfFree (m_pfProcessBuffer);
00216
00217 rErr = CFeatureExtractBase::InitializePlugin ( fInputSampleRate,
00218 iNumberOfAudioChannels,
00219 iHostApiMajorVersion,
00220 pstUserData);
00221
00222
00223 if (rErr != FEAPI_kNoError)
00224 return rErr;
00225
00226
00227 char acChannelStr[FEAPI_kMaxDescriptionLength];
00228 for (iCh = 0; iCh < iNumberOfAudioChannels; ++iCh) {
00229 sprintf(acChannelStr, "Channel: %d", iCh);
00230 SetPluginInputPinInfo(CPin::SetIndex(iCh)
00231 .SetName(acChannelStr)
00232 .SetUnit("")
00233 .SetDescription(acChannelStr)
00234 .SetRangeMin(-1.0f)
00235 .SetRangeMax(1.0f)
00236 .SetSampleRate(fInputSampleRate)
00237 );
00238 }
00239
00240
00241
00242 if (m_afParameters[kChannelMode] == 0)
00243 {
00244 SetPluginResultPinInfo(CPin::SetIndex(kFeatureIndex)
00245 .SetName(kFeatureName)
00246 .SetUnit(kFeatureUnit)
00247 .SetDescription(kFeatureDescription)
00248 .SetRangeMin(kFeatureRangeMin)
00249 .SetRangeMax(kFeatureRangeMax)
00250 .SetQuantizedTo(kFeatureIsQuantized)
00251 .SetSampleRate(1000.0F / m_afParameters[kHopSize])
00252 );
00253 }
00254 else
00255 {
00256 for (iCh = 0; iCh < iNumberOfAudioChannels; ++iCh)
00257 {
00258 sprintf(acChannelStr, "%s Channel: %d", kFeatureName, iCh);
00259 SetPluginInputPinInfo(CPin::SetIndex(iCh)
00260 .SetName(acChannelStr)
00261 .SetUnit(kFeatureUnit)
00262 .SetDescription(kFeatureDescription)
00263 .SetRangeMin(kFeatureRangeMin)
00264 .SetRangeMax(kFeatureRangeMax)
00265 .SetSampleRate(1000.0F / m_afParameters[kHopSize])
00266 );
00267 }
00268 }
00269
00270
00271 SetPluginParameterPinInfo(CPin::SetIndex(kParam1Index)
00272 .SetName(kParam1Name)
00273 .SetUnit(kParam1Unit)
00274 .SetDescription(kParam1Description)
00275 .SetRangeMin(kParam1RangeMin)
00276 .SetRangeMax(kParam1RangeMax)
00277 .SetDefaultValue(kParam1DefaultValue)
00278 .SetQuantizedTo(kParam1QuantizedTo)
00279 .SetIsChangeableInRealTime(kParam1IsChangeableInRealTime)
00280 );
00281
00282 SetPluginParameterPinInfo(CPin::SetIndex(kParam2Index)
00283 .SetName(kParam2Name)
00284 .SetUnit(kParam2Unit)
00285 .SetDescription(kParam2Description)
00286 .SetRangeMin(kParam2RangeMin)
00287 .SetRangeMax(kParam2RangeMax)
00288 .SetDefaultValue(kParam2DefaultValue)
00289 .SetQuantizedTo(kParam2QuantizedTo)
00290 .SetIsChangeableInRealTime(kParam2IsChangeableInRealTime)
00291 );
00292
00293 SetPluginParameterPinInfo(CPin::SetIndex(kParam3Index)
00294 .SetName(kParam3Name)
00295 .SetUnit(kParam3Unit)
00296 .SetDescription(kParam3Description)
00297 .SetRangeMin(kParam3RangeMin)
00298 .SetRangeMax(kParam3RangeMax)
00299 .SetDefaultValue(kParam3DefaultValue)
00300 .SetQuantizedTo(kParam3QuantizedTo)
00301 .SetIsChangeableInRealTime(kParam3IsChangeableInRealTime)
00302 );
00303
00304
00305 m_pfProcessBuffer = zplfMalloc ((int)(m_afParameters[kBlockSize]));
00306 m_ptLocalTimeStamp = new FEAPI_TimeStamp_t [iNumberOfAudioChannels];
00307 m_ppCRingBuffer = new CRingBuffer<float>*[iNumberOfAudioChannels];
00308 m_ppResults = new InternalResults_t*[iNumberOfAudioChannels];
00309 for (iCh = 0; iCh < iNumberOfAudioChannels; iCh++)
00310 {
00311 m_ppCRingBuffer[iCh] = new CRingBuffer<float>((unsigned int)(m_afParameters[kBlockSize])<<1);
00312 m_ppResults[iCh] = new InternalResults_t[m_iSizeOfResultBuffer];
00313 memset (m_ppResults[iCh], 0, sizeof (InternalResults_t) * m_iSizeOfResultBuffer);
00314 }
00315 memset (m_ptLocalTimeStamp, 0, sizeof(FEAPI_TimeStamp_t)*iNumberOfAudioChannels);
00316
00317 return FEAPI_kNoError;
00318 }
00319
00320 FEAPI_Error_t CZeroCrossings::SetPluginParameter (int iParameterIndex, float fValue)
00321 {
00322 float fMinValue,
00323 fMaxValue;
00324
00325 if ((iParameterIndex >= this->GetPluginNumOfParameters ()) || (iParameterIndex < 0))
00326 return FEAPI_kUnspecifiedError;
00327
00328
00329 switch (iParameterIndex)
00330 {
00331 case kBlockSize:
00332 fMinValue = kParam1RangeMin;
00333 fMaxValue = kParam1RangeMax;
00334 break;
00335 case kHopSize:
00336 fMinValue = kParam2RangeMin;
00337 fMaxValue = kParam2RangeMax;
00338 break;
00339 case kChannelMode:
00340 fMinValue = kParam3RangeMin;
00341 fMaxValue = kParam3RangeMax;
00342 break;
00343 default:
00344 return FEAPI_kUnspecifiedError;
00345 }
00346
00347 if ((fValue < fMinValue) || (fValue > fMaxValue))
00348 return FEAPI_kUnspecifiedError;
00349
00350 m_afParameters[iParameterIndex] = fValue;
00351
00352
00353 this->InitializePlugin (m_fSampleRate, this->GetPluginNumOfInputs (), 1, 0);
00354
00355 return FEAPI_kUnknownError;
00356 }
00357
00358
00359 float CZeroCrossings::GetPluginParameter (int iParameterIndex)
00360 {
00361 if ((iParameterIndex >= this->GetPluginNumOfParameters ()) || (iParameterIndex < 0))
00362 return FEAPI_kUnspecifiedError;
00363
00364 return m_afParameters[iParameterIndex];
00365 }
00366
00367
00368 int CZeroCrossings::GetPluginResultLatency (int iResultIndex)
00369 {
00370 return (int)m_afParameters[kBlockSize];
00371 }
00372
00373
00374 FEAPI_Error_t CZeroCrossings::ProcessPluginDone ()
00375 {
00376 int iNumProcessChannels = this->GetPluginNumOfResults (),
00377 iProcessBlockSize = (int)(m_afParameters[kBlockSize]),
00378 iSamplesInBuffer = m_ppCRingBuffer[0]->GetSamplesInBuffer ();
00379
00380 for (int iCh = 0; iCh < iNumProcessChannels; iCh++)
00381 {
00382 int iTempResult = 0;
00383
00384 m_ppCRingBuffer[iCh]->GetPostInc (m_pfProcessBuffer, iSamplesInBuffer);
00385 memset (&m_pfProcessBuffer[iSamplesInBuffer], 0, sizeof(float)*(iProcessBlockSize - iSamplesInBuffer));
00386
00387 iTempResult = zplfZeroCrossings (m_pfProcessBuffer, iProcessBlockSize);
00388
00389 m_ptLocalTimeStamp[iCh] = m_ptLocalTimeStamp[iCh] + m_afParameters[kHopSize]*0.001F;
00390 this->WriteResult (iCh, iTempResult * 1.0F / iSamplesInBuffer, m_ptLocalTimeStamp[iCh]);
00391 }
00392
00393 return FEAPI_kNoError;
00394 }
00395
00396 FEAPI_Error_t CZeroCrossings::ProcessPlugin (const float **ppfInputBuffer, const FEAPI_TimeStamp_t *ptTimeStamps, int iNumberOfFrames)
00397 {
00398 bool bDownmixToMono = (m_afParameters[kChannelMode] == 0)? true : false;
00399 int iCh,
00400 iIdx,
00401 iProcessBlockSize = (int)(m_afParameters[kBlockSize]),
00402 iHopSize = (int)(m_afParameters[kHopSize]*0.001F * m_fSampleRate + .5F),
00403 iNumFramesLeft = iNumberOfFrames,
00404 iNumInputChannels = this->GetPluginNumOfInputs (),
00405 iNumProcessChannels = this->GetPluginNumOfResults (),
00406 iSamplesInBuffer = 0;
00407
00408 if (!m_bIsInitialized)
00409 return FEAPI_kUnspecifiedError;
00410
00411
00412 if (ptTimeStamps)
00413 {
00414 for (iCh = 0; iCh < iNumInputChannels; iCh++)
00415 m_ptLocalTimeStamp[iCh] = ptTimeStamps[iCh] + iNumberOfFrames/m_fSampleRate;
00416 }
00417 else
00418 {
00419 for (iCh = 0; iCh < iNumInputChannels; iCh++)
00420 m_ptLocalTimeStamp[iCh] += iNumberOfFrames/m_fSampleRate;
00421 }
00422
00423
00424 while (m_ppCRingBuffer[0]->GetSamplesInBuffer () + iNumFramesLeft >= iProcessBlockSize)
00425 {
00426
00427 if (bDownmixToMono)
00428 {
00429 int iLength = (iHopSize < iNumFramesLeft) ? iHopSize : iNumFramesLeft;
00430 iNumProcessChannels = 1;
00431
00432 memcpy (m_pfProcessBuffer, &ppfInputBuffer[0][iNumberOfFrames - iNumFramesLeft], sizeof(float) * iLength);
00433 for (iCh = 1; iCh < iNumInputChannels; iCh++)
00434 {
00435 const float *pfBuffer = &ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft];
00436
00437 for (iIdx = 0; iIdx < iLength; iIdx++)
00438 m_pfProcessBuffer[iIdx] += pfBuffer[iIdx];
00439 }
00440
00441
00442 for (iIdx = 0; iIdx < iLength; iIdx++)
00443 m_pfProcessBuffer[iIdx] *= 1.0F/iNumInputChannels;
00444
00445 m_ppCRingBuffer[0]->PutPostInc (m_pfProcessBuffer, iLength);
00446 }
00447 else
00448 {
00449 for (iCh = 0; iCh < iNumInputChannels; iCh++)
00450 m_ppCRingBuffer[iCh]->PutPostInc (&ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft], (iHopSize < iNumFramesLeft) ? iHopSize : iNumFramesLeft);
00451 }
00452
00453
00454 iNumFramesLeft -= (iHopSize < iNumFramesLeft) ? iHopSize : iNumFramesLeft;
00455
00456
00457 iSamplesInBuffer = m_ppCRingBuffer[0]->GetSamplesInBuffer ();
00458
00459
00460 if (iSamplesInBuffer < iProcessBlockSize)
00461 continue;
00462
00463
00464 for (iCh = 0; iCh < iNumProcessChannels; iCh++)
00465 {
00466 int iTempResult = 0;
00467
00468 m_ptLocalTimeStamp[iCh] = ptTimeStamps[iCh] + iNumberOfFrames/m_fSampleRate - (iSamplesInBuffer+iNumFramesLeft)/m_fSampleRate;
00469
00470
00471 m_ppCRingBuffer[iCh]->GetOff (m_pfProcessBuffer, iProcessBlockSize, 0);
00472 m_ppCRingBuffer[iCh]->SetReadPos (m_ppCRingBuffer[iCh]->GetReadPos () + iHopSize);
00473
00474
00475 iTempResult = zplfZeroCrossings (m_pfProcessBuffer, iProcessBlockSize);
00476
00477
00478 this->WriteResult (iCh, iTempResult * 1.0F / iProcessBlockSize, m_ptLocalTimeStamp[iCh]);
00479 }
00480 }
00481
00482
00483 if (iNumFramesLeft > 0)
00484 {
00485
00486 if (bDownmixToMono)
00487 {
00488
00489 memcpy (m_pfProcessBuffer, &ppfInputBuffer[0][iNumberOfFrames - iNumFramesLeft], sizeof(float) * iNumFramesLeft);
00490 for (iCh = 1; iCh < iNumInputChannels; iCh++)
00491 {
00492 const float *pfBuffer = &ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft];
00493
00494 for (iIdx = 0; iIdx < iNumFramesLeft; iIdx++)
00495 m_pfProcessBuffer[iIdx] += pfBuffer[iIdx];
00496 }
00497 m_ppCRingBuffer[0]->PutPostInc (m_pfProcessBuffer, iNumFramesLeft);
00498 }
00499 else
00500 {
00501 for (iCh = 0; iCh < iNumInputChannels; iCh++)
00502 m_ppCRingBuffer[iCh]->PutPostInc (&ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft], iNumFramesLeft);
00503 }
00504 }
00505
00506 return FEAPI_kNoError;
00507 }
00508
00509 int CZeroCrossings::GetPluginSizeOfResult (int iResultIndex)
00510 {
00511 if ((iResultIndex >= this->GetPluginNumOfResults ()) || (iResultIndex < 0))
00512 return -1;
00513
00514 if (m_ppResults[iResultIndex][0].bHoldsResult == true)
00515 return 1;
00516 else
00517 return 0;
00518 }
00519
00520
00521 FEAPI_Error_t CZeroCrossings::GetPluginResult (int iResultIndex, float *pfResult, FEAPI_TimeStamp_t *ptTimeStamp)
00522 {
00523 if ((iResultIndex >= this->GetPluginNumOfResults ()) || (iResultIndex < 0))
00524 return FEAPI_kUnspecifiedError;
00525
00526 if (m_ppResults[iResultIndex][0].bHoldsResult == false)
00527 return FEAPI_kUnspecifiedError;
00528
00529 pfResult[0] = m_ppResults[iResultIndex][0].fResult;
00530 ptTimeStamp[0] = m_ppResults[iResultIndex][0].tTimeStamp;
00531
00532 memmove (&m_ppResults[iResultIndex][0], &m_ppResults[iResultIndex][1], (m_iSizeOfResultBuffer - 1)*sizeof(InternalResults_t));
00533 m_ppResults[iResultIndex][m_iSizeOfResultBuffer-1].bHoldsResult = false;
00534
00535 return FEAPI_kNoError;
00536 }
00537
00538
00539 FEAPI_Error_t CZeroCrossings::ResetPlugin ()
00540 {
00541 for (int iCh = 0; iCh < this->GetPluginNumOfInputs (); iCh++)
00542 {
00543 m_ppCRingBuffer[iCh]->Reset ();
00544 m_ptLocalTimeStamp[iCh] = 0;
00545 }
00546 return FEAPI_kNoError;
00547 }
00548
00549
00550 float CZeroCrossings::GetPluginProperty ( FEAPI_PluginProperty_t ePluginProperty)
00551 {
00552 switch (ePluginProperty)
00553 {
00554 case FEAPI_kMinSampleRate:
00555 {
00556 return 1;
00557 }
00558 case FEAPI_kMaxSampleRate:
00559 {
00560 return 1e38F;
00561 }
00562 case FEAPI_kMinChannels:
00563 {
00564 return 1;
00565 }
00566 case FEAPI_kMaxChannels:
00567 {
00568 return (float)((1<<30)-1);
00569 }
00570 case FEAPI_kMinFrameSize:
00571 {
00572 return 1;
00573 }
00574 case FEAPI_kMaxFrameSize:
00575 {
00576 return (float)((1<<30)-1);
00577 }
00578 case FEAPI_kOptFrameSize:
00579 {
00580 return floorf(m_afParameters[kHopSize] * 0.001F * m_fSampleRate + .5F);
00581 }
00582 default:
00583 {
00584
00585 return -1;
00586 }
00587 }
00588 return -1;
00589 }
00590
00591 void CZeroCrossings::WriteResult (int iResultIdx, float fValue, FEAPI_TimeStamp_t tTimeStamp)
00592 {
00593 int iCurrentIdx = 0;
00594
00595 for (iCurrentIdx = 0; iCurrentIdx < m_iSizeOfResultBuffer; iCurrentIdx++)
00596 {
00597 ZASSERT (!m_ppResults[iCurrentIdx]);
00598 if (m_ppResults[iResultIdx][iCurrentIdx].bHoldsResult == false)
00599 break;
00600 }
00601 if (iCurrentIdx == m_iSizeOfResultBuffer)
00602 {
00603
00604 m_iSizeOfResultBuffer <<= 1;
00605 for (int i = 0; i < this->GetPluginNumOfResults (); i++)
00606 {
00607 InternalResults_t *pTmp = new InternalResults_t[m_iSizeOfResultBuffer];
00608 memcpy (pTmp, m_ppResults[i], (m_iSizeOfResultBuffer>>1) * sizeof(InternalResults_t));
00609 memset (&pTmp[(m_iSizeOfResultBuffer>>1)], 0, (m_iSizeOfResultBuffer>>1) * sizeof(InternalResults_t));
00610 delete [] m_ppResults[i];
00611 m_ppResults[i] = 0;
00612 m_ppResults[i] = pTmp;
00613 }
00614 }
00615
00616 m_ppResults[iResultIdx][iCurrentIdx].bHoldsResult = true;
00617 m_ppResults[iResultIdx][iCurrentIdx].fResult = fValue;
00618 m_ppResults[iResultIdx][iCurrentIdx].tTimeStamp = tTimeStamp;
00619
00620 return;
00621 }
00622
00624
00625 #ifdef __cplusplus
00626 extern "C" {
00627 #endif
00628
00629 FEAPI_ENTRY_POINTS(CZeroCrossings)
00630
00631 #ifdef __cplusplus
00632 }
00633 #endif
00634