Lines Matching refs:aec
12 * The core AEC algorithm, which is presented with time-aligned signals.
108 static void ProcessBlock(aec_t* aec);
110 static void NonLinearProcessing(aec_t *aec, short *output, short *outputH);
115 static void ComfortNoise(aec_t *aec, float efw[2][PART_LEN1],
122 static void UpdateMetrics(aec_t *aec);
149 aec_t *aec = malloc(sizeof(aec_t));
150 *aecInst = aec;
151 if (aec == NULL) {
155 if (WebRtc_CreateBuffer(&aec->nearFrBuf,
158 WebRtcAec_FreeAec(aec);
159 aec = NULL;
163 if (WebRtc_CreateBuffer(&aec->outFrBuf,
166 WebRtcAec_FreeAec(aec);
167 aec = NULL;
171 if (WebRtc_CreateBuffer(&aec->nearFrBufH,
174 WebRtcAec_FreeAec(aec);
175 aec = NULL;
179 if (WebRtc_CreateBuffer(&aec->outFrBufH,
182 WebRtcAec_FreeAec(aec);
183 aec = NULL;
188 if (WebRtc_CreateBuffer(&aec->far_buf, kBufSizePartitions,
190 WebRtcAec_FreeAec(aec);
191 aec = NULL;
194 if (WebRtc_CreateBuffer(&aec->far_buf_windowed, kBufSizePartitions,
196 WebRtcAec_FreeAec(aec);
197 aec = NULL;
201 if (WebRtc_CreateBuffer(&aec->far_time_buf, kBufSizePartitions,
203 WebRtcAec_FreeAec(aec);
204 aec = NULL;
208 if (WebRtc_CreateDelayEstimator(&aec->delay_estimator,
212 WebRtcAec_FreeAec(aec);
213 aec = NULL;
220 int WebRtcAec_FreeAec(aec_t *aec)
222 if (aec == NULL) {
226 WebRtc_FreeBuffer(aec->nearFrBuf);
227 WebRtc_FreeBuffer(aec->outFrBuf);
229 WebRtc_FreeBuffer(aec->nearFrBufH);
230 WebRtc_FreeBuffer(aec->outFrBufH);
232 WebRtc_FreeBuffer(aec->far_buf);
233 WebRtc_FreeBuffer(aec->far_buf_windowed);
235 WebRtc_FreeBuffer(aec->far_time_buf);
237 WebRtc_FreeDelayEstimator(aec->delay_estimator);
239 free(aec);
243 static void FilterFar(aec_t *aec, float yf[2][PART_LEN1])
248 int xPos = (i + aec->xfBufBlockPos) * PART_LEN1;
251 if (i + aec->xfBufBlockPos >= NR_PART) {
256 yf[0][j] += MulRe(aec->xfBuf[0][xPos + j], aec->xfBuf[1][xPos + j],
257 aec->wfBuf[0][ pos + j], aec->wfBuf[1][ pos + j]);
258 yf[1][j] += MulIm(aec->xfBuf[0][xPos + j], aec->xfBuf[1][xPos + j],
259 aec->wfBuf[0][ pos + j], aec->wfBuf[1][ pos + j]);
264 static void ScaleErrorSignal(aec_t *aec, float ef[2][PART_LEN1])
269 ef[0][i] /= (aec->xPow[i] + 1e-10f);
270 ef[1][i] /= (aec->xPow[i] + 1e-10f);
273 if (absEf > aec->errThresh) {
274 absEf = aec->errThresh / (absEf + 1e-10f);
280 ef[0][i] *= aec->mu;
281 ef[1][i] *= aec->mu;
287 //static void FilterAdaptationUnconstrained(aec_t *aec, float *fft,
291 // int xPos = (i + aec->xfBufBlockPos)*(PART_LEN1);
294 // if (i + aec->xfBufBlockPos >= NR_PART) {
301 // aec->wfBuf[pos + j][0] += MulRe(aec->xfBuf[xPos + j][0],
302 // -aec->xfBuf[xPos + j][1],
304 // aec->wfBuf[pos + j][1] += MulIm(aec->xfBuf[xPos + j][0],
305 // -aec->xfBuf[xPos + j][1],
311 static void FilterAdaptation(aec_t *aec, float *fft, float ef[2][PART_LEN1]) {
314 int xPos = (i + aec->xfBufBlockPos)*(PART_LEN1);
317 if (i + aec->xfBufBlockPos >= NR_PART) {
325 fft[2 * j] = MulRe(aec->xfBuf[0][xPos + j],
326 -aec->xfBuf[1][xPos + j],
328 fft[2 * j + 1] = MulIm(aec->xfBuf[0][xPos + j],
329 -aec->xfBuf[1][xPos + j],
332 fft[1] = MulRe(aec->xfBuf[0][xPos + PART_LEN],
333 -aec->xfBuf[1][xPos + PART_LEN],
348 aec->wfBuf[0][pos] += fft[0];
349 aec->wfBuf[0][pos + PART_LEN] += fft[1];
352 aec->wfBuf[0][pos + j] += fft[2 * j];
353 aec->wfBuf[1][pos + j] += fft[2 * j + 1];
358 static void OverdriveAndSuppress(aec_t *aec, float hNl[PART_LEN1],
368 hNl[i] = powf(hNl[i], aec->overDriveSm * WebRtcAec_overDriveCurve[i]);
385 int WebRtcAec_InitAec(aec_t *aec, int sampFreq)
389 aec->sampFreq = sampFreq;
392 aec->mu = 0.6f;
393 aec->errThresh = 2e-6f;
396 aec->mu = 0.5f;
397 aec->errThresh = 1.5e-6f;
400 if (WebRtc_InitBuffer(aec->nearFrBuf) == -1) {
404 if (WebRtc_InitBuffer(aec->outFrBuf) == -1) {
408 if (WebRtc_InitBuffer(aec->nearFrBufH) == -1) {
412 if (WebRtc_InitBuffer(aec->outFrBufH) == -1) {
417 if (WebRtc_InitBuffer(aec->far_buf) == -1) {
420 if (WebRtc_InitBuffer(aec->far_buf_windowed) == -1) {
424 if (WebRtc_InitBuffer(aec->far_time_buf) == -1) {
428 aec->system_delay = 0;
430 if (WebRtc_InitDelayEstimator(aec->delay_estimator) != 0) {
433 aec->delay_logging_enabled = 0;
434 memset(aec->delay_histogram, 0, sizeof(aec->delay_histogram));
437 aec->targetSupp = -11.5;
438 aec->minOverDrive = 2.0;
442 if (aec->sampFreq == 32000) {
443 aec->mult = (short)aec->sampFreq / 16000;
446 aec->mult = (short)aec->sampFreq / 8000;
449 aec->farBufWritePos = 0;
450 aec->farBufReadPos = 0;
452 aec->inSamples = 0;
453 aec->outSamples = 0;
454 aec->knownDelay = 0;
457 memset(aec->dBuf, 0, sizeof(aec->dBuf));
458 memset(aec->eBuf, 0, sizeof(aec->eBuf));
460 memset(aec->dBufH, 0, sizeof(aec->dBufH));
462 memset(aec->xPow, 0, sizeof(aec->xPow));
463 memset(aec->dPow, 0, sizeof(aec->dPow));
464 memset(aec->dInitMinPow, 0, sizeof(aec->dInitMinPow));
465 aec->noisePow = aec->dInitMinPow;
466 aec->noiseEstCtr = 0;
470 aec->dMinPow[i] = 1.0e6f;
474 aec->xfBufBlockPos = 0;
477 memset(aec->xfBuf, 0, sizeof(complex_t) * NR_PART * PART_LEN1);
478 memset(aec->wfBuf, 0, sizeof(complex_t) * NR_PART * PART_LEN1);
479 memset(aec->sde, 0, sizeof(complex_t) * PART_LEN1);
480 memset(aec->sxd, 0, sizeof(complex_t) * PART_LEN1);
481 memset(aec->xfwBuf, 0, sizeof(complex_t) * NR_PART * PART_LEN1);
482 memset(aec->se, 0, sizeof(float) * PART_LEN1);
486 aec->sd[i] = 1;
489 aec->sx[i] = 1;
492 memset(aec->hNs, 0, sizeof(aec->hNs));
493 memset(aec->outBuf, 0, sizeof(float) * PART_LEN);
495 aec->hNlFbMin = 1;
496 aec->hNlFbLocalMin = 1;
497 aec->hNlXdAvgMin = 1;
498 aec->hNlNewMin = 0;
499 aec->hNlMinCtr = 0;
500 aec->overDrive = 2;
501 aec->overDriveSm = 2;
502 aec->delayIdx = 0;
503 aec->stNearState = 0;
504 aec->echoState = 0;
505 aec->divergeState = 0;
507 aec->seed = 777;
508 aec->delayEstCtr = 0;
511 aec->metricsMode = 0;
512 WebRtcAec_InitMetrics(aec);
529 void WebRtcAec_InitMetrics(aec_t *aec)
531 aec->stateCounter = 0;
532 WebRtcAec_InitLevel(&aec->farlevel);
533 WebRtcAec_InitLevel(&aec->nearlevel);
534 WebRtcAec_InitLevel(&aec->linoutlevel);
535 WebRtcAec_InitLevel(&aec->nlpoutlevel);
537 WebRtcAec_InitStats(&aec->erl);
538 WebRtcAec_InitStats(&aec->erle);
539 WebRtcAec_InitStats(&aec->aNlp);
540 WebRtcAec_InitStats(&aec->rerl);
544 void WebRtcAec_BufferFarendPartition(aec_t *aec, const float* farend) {
549 if (WebRtc_available_write(aec->far_buf) < 1) {
550 WebRtc_MoveReadPtr(aec->far_buf, 1);
551 WebRtc_MoveReadPtr(aec->far_buf_windowed, 1);
552 aec->system_delay -= PART_LEN;
554 WebRtc_MoveReadPtr(aec->far_time_buf, 1);
560 WebRtc_WriteBuffer(aec->far_buf, &xf[0][0], 1);
565 WebRtc_WriteBuffer(aec->far_buf_windowed, &xf[0][0], 1);
568 void WebRtcAec_ProcessFrame(aec_t *aec,
587 // than |aec->knownDelay|. We therefore, round (-32) in that direction. In
591 int move_elements = (aec->knownDelay - knownDelay - 32) / PART_LEN;
597 WebRtc_WriteBuffer(aec->nearFrBuf, nearend, FRAME_LEN);
599 if (aec->sampFreq == 32000) {
600 WebRtc_WriteBuffer(aec->nearFrBufH, nearendH, FRAME_LEN);
603 // 1) At most we process |aec->mult|+1 partitions in 10 ms. Make sure we
606 if (aec->system_delay < FRAME_LEN) {
608 WebRtc_MoveReadPtr(aec->far_buf_windowed, -(aec->mult + 1));
609 aec->system_delay -= WebRtc_MoveReadPtr(aec->far_buf, -(aec->mult + 1)) *
612 WebRtc_MoveReadPtr(aec->far_time_buf, -(aec->mult + 1));
618 WebRtc_MoveReadPtr(aec->far_buf_windowed, move_elements);
619 moved_elements = WebRtc_MoveReadPtr(aec->far_buf, move_elements);
620 aec->knownDelay -= moved_elements * PART_LEN;
622 WebRtc_MoveReadPtr(aec->far_time_buf, move_elements);
626 while (WebRtc_available_read(aec->nearFrBuf) >= PART_LEN) {
627 ProcessBlock(aec);
631 aec->system_delay -= FRAME_LEN;
634 static void ProcessBlock(aec_t* aec) {
650 const int noiseInitBlocks = 500 * aec->mult;
663 if (aec->sampFreq == 32000) {
665 WebRtc_ReadBuffer(aec->nearFrBufH,
672 memcpy(aec->dBufH + PART_LEN, dH, sizeof(float) * PART_LEN);
674 WebRtc_ReadBuffer(aec->nearFrBuf, (void**) &nearend_ptr, nearend, PART_LEN);
681 memcpy(aec->dBuf + PART_LEN, d, sizeof(float) * PART_LEN);
687 WebRtc_ReadBuffer(aec->far_time_buf, (void**) &farend_ptr, farend, 1);
688 fwrite(farend_ptr, sizeof(int16_t), PART_LEN, aec->farFile);
689 fwrite(nearend_ptr, sizeof(int16_t), PART_LEN, aec->nearFile);
694 assert(WebRtc_available_read(aec->far_buf) > 0);
695 WebRtc_ReadBuffer(aec->far_buf, (void**) &xf_ptr, &xf[0][0], 1);
698 memcpy(fft, aec->dBuf, sizeof(float) * PART_LEN2);
705 aec->xPow[i] = gPow[0] * aec->xPow[i] + gPow[1] * NR_PART * far_spectrum;
710 aec->dPow[i] = gPow[0] * aec->dPow[i] + gPow[1] * near_spectrum;
716 if (aec->noiseEstCtr > 50) {
718 if (aec->dPow[i] < aec->dMinPow[i]) {
719 aec->dMinPow[i] = (aec->dPow[i] + step * (aec->dMinPow[i] -
720 aec->dPow[i])) * ramp;
723 aec->dMinPow[i] *= ramp;
730 if (aec->noiseEstCtr < noiseInitBlocks) {
731 aec->noiseEstCtr++;
733 if (aec->dMinPow[i] > aec->dInitMinPow[i]) {
734 aec->dInitMinPow[i] = gInitNoise[0] * aec->dInitMinPow[i] +
735 gInitNoise[1] * aec->dMinPow[i];
738 aec->dInitMinPow[i] = aec->dMinPow[i];
741 aec->noisePow = aec->dInitMinPow;
744 aec->noisePow = aec->dMinPow;
748 if (aec->delay_logging_enabled) {
751 delay_estimate = WebRtc_DelayEstimatorProcessFloat(aec->delay_estimator,
757 aec->delay_histogram[delay_estimate]++;
762 aec->xfBufBlockPos--;
763 if (aec->xfBufBlockPos == -1) {
764 aec->xfBufBlockPos = NR_PART - 1;
768 memcpy(aec->xfBuf[0] + aec->xfBufBlockPos * PART_LEN1, xf_ptr,
770 memcpy(aec->xfBuf[1] + aec->xfBufBlockPos * PART_LEN1, &xf_ptr[PART_LEN1],
776 WebRtcAec_FilterFar(aec, yf);
797 memcpy(aec->eBuf + PART_LEN, e, sizeof(float) * PART_LEN);
812 if (aec->metricsMode == 1) {
816 UpdateLevel(&aec->linoutlevel, ef);
820 WebRtcAec_ScaleErrorSignal(aec, ef);
821 WebRtcAec_FilterAdaptation(aec, fft, ef);
822 NonLinearProcessing(aec, output, outputH);
824 if (aec->metricsMode == 1) {
826 UpdateLevel(&aec->farlevel, (float (*)[PART_LEN1]) xf_ptr);
827 UpdateLevel(&aec->nearlevel, df);
828 UpdateMetrics(aec);
832 WebRtc_WriteBuffer(aec->outFrBuf, output, PART_LEN);
834 if (aec->sampFreq == 32000) {
835 WebRtc_WriteBuffer(aec->outFrBufH, outputH, PART_LEN);
846 fwrite(eInt16, sizeof(int16_t), PART_LEN, aec->outLinearFile);
847 fwrite(output, sizeof(int16_t), PART_LEN, aec->outFile);
852 static void NonLinearProcessing(aec_t *aec, short *output, short *outputH)
868 const int prefBandSize = PREF_BAND_SIZE / aec->mult;
869 const int minPrefBand = 4 / aec->mult;
876 const float *ptrGCoh = gCoh[aec->mult - 1];
880 const int delayEstInterval = 10 * aec->mult;
884 aec->delayEstCtr++;
885 if (aec->delayEstCtr == delayEstInterval) {
886 aec->delayEstCtr = 0;
896 if (aec->delayEstCtr == 0) {
898 aec->delayIdx = 0;
903 wfEn += aec->wfBuf[0][pos + j] * aec->wfBuf[0][pos + j] +
904 aec->wfBuf[1][pos + j] * aec->wfBuf[1][pos + j];
909 aec->delayIdx = i;
915 assert(WebRtc_available_read(aec->far_buf_windowed) > 0);
917 WebRtc_ReadBuffer(aec->far_buf_windowed, (void**) &xfw_ptr, &xfw[0][0], 1);
922 memcpy(aec->xfwBuf, xfw_ptr, sizeof(float) * 2 * PART_LEN1);
925 memcpy(xfw, aec->xfwBuf + aec->delayIdx * PART_LEN1, sizeof(xfw));
929 fft[i] = aec->dBuf[i] * sqrtHanning[i];
930 fft[PART_LEN + i] = aec->dBuf[PART_LEN + i] * sqrtHanning[PART_LEN - i];
945 fft[i] = aec->eBuf[i] * sqrtHanning[i];
946 fft[PART_LEN + i] = aec->eBuf[PART_LEN + i] * sqrtHanning[PART_LEN - i];
960 aec->sd[i] = ptrGCoh[0] * aec->sd[i] + ptrGCoh[1] *
962 aec->se[i] = ptrGCoh[0] * aec->se[i] + ptrGCoh[1] *
968 aec->sx[i] = ptrGCoh[0] * aec->sx[i] + ptrGCoh[1] *
971 aec->sde[i][0] = ptrGCoh[0] * aec->sde[i][0] + ptrGCoh[1] *
973 aec->sde[i][1] = ptrGCoh[0] * aec->sde[i][1] + ptrGCoh[1] *
976 aec->sxd[i][0] = ptrGCoh[0] * aec->sxd[i][0] + ptrGCoh[1] *
978 aec->sxd[i][1] = ptrGCoh[0] * aec->sxd[i][1] + ptrGCoh[1] *
981 sdSum += aec->sd[i];
982 seSum += aec->se[i];
986 if (aec->divergeState == 0) {
988 aec->divergeState = 1;
993 aec->divergeState = 0;
997 if (aec
1003 memset(aec->wfBuf, 0, sizeof(aec->wfBuf));
1008 cohde[i] = (aec->sde[i][0] * aec->sde[i][0] + aec->sde[i][1] * aec->sde[i][1]) /
1009 (aec->sd[i] * aec->se[i] + 1e-10f);
1010 cohxd[i] = (aec->sxd[i][0] * aec->sxd[i][0] + aec->sxd[i][1] * aec->sxd[i][1]) /
1011 (aec->sx[i] * aec->sd[i] + 1e-10f);
1027 if (hNlXdAvg < 0.75f && hNlXdAvg < aec->hNlXdAvgMin) {
1028 aec->hNlXdAvgMin = hNlXdAvg;
1032 aec->stNearState = 1;
1035 aec->stNearState = 0;
1038 if (aec->hNlXdAvgMin == 1) {
1039 aec->echoState = 0;
1040 aec->overDrive = aec->minOverDrive;
1042 if (aec->stNearState == 1) {
1057 if (aec->stNearState == 1) {
1058 aec->echoState = 0;
1064 aec->echoState = 1;
1079 if (hNlFbLow < 0.6f && hNlFbLow < aec->hNlFbLocalMin) {
1080 aec->hNlFbLocalMin = hNlFbLow;
1081 aec->hNlFbMin = hNlFbLow;
1082 aec->hNlNewMin = 1;
1083 aec->hNlMinCtr = 0;
1085 aec->hNlFbLocalMin = WEBRTC_SPL_MIN(aec->hNlFbLocalMin + 0.0008f / aec->mult, 1);
1086 aec->hNlXdAvgMin = WEBRTC_SPL_MIN(aec->hNlXdAvgMin + 0.0006f / aec->mult, 1);
1088 if (aec->hNlNewMin == 1) {
1089 aec->hNlMinCtr++;
1091 if (aec->hNlMinCtr == 2) {
1092 aec->hNlNewMin = 0;
1093 aec->hNlMinCtr = 0;
1094 aec->overDrive = WEBRTC_SPL_MAX(aec->targetSupp /
1095 ((float)log(aec->hNlFbMin + 1e-10f) + 1e-10f), aec->minOverDrive);
1099 if (aec->overDrive < aec->overDriveSm) {
1100 aec->overDriveSm = 0.99f * aec->overDriveSm + 0.01f * aec->overDrive;
1103 aec->overDriveSm = 0.9f * aec->overDriveSm + 0.1f * aec->overDrive;
1106 WebRtcAec_OverdriveAndSuppress(aec, hNl, hNlFb, efw);
1109 ComfortNoise(aec, efw, comfortNoiseHband, aec->noisePow, hNl);
1113 if (aec->metricsMode == 1) {
1118 UpdateLevel(&aec->nlpoutlevel, efw);
1134 fft[i] = fft[i]*sqrtHanning[i] + aec->outBuf[i];
1141 aec->outBuf[i] = fft[PART_LEN + i] * sqrtHanning[PART_LEN - i];
1145 if (aec->sampFreq == 32000) {
1166 dtmp = (float)aec->dBufH[i];
1182 memcpy(aec->dBuf, aec->dBuf + PART_LEN, sizeof(float) * PART_LEN);
1183 memcpy(aec->eBuf, aec->eBuf + PART_LEN, sizeof(float) * PART_LEN);
1186 if (aec->sampFreq == 32000) {
1187 memcpy(aec->dBufH, aec->dBufH + PART_LEN, sizeof(float) * PART_LEN);
1190 memmove(aec->xfwBuf + PART_LEN1, aec->xfwBuf, sizeof(aec->xfwBuf) -
1205 static void ComfortNoise(aec_t *aec, float efw[2][PART_LEN1],
1217 WebRtcSpl_RandUArray(randW16, PART_LEN, &aec->seed);
1247 if (aec->sampFreq == 32000 && flagHbandCn == 1) {
1375 static void UpdateMetrics(aec_t *aec)
1387 if (aec->echoState) { // Check if echo is likely present
1388 aec->stateCounter++;
1391 if (aec->farlevel.frcounter == 0) {
1393 if (aec->farlevel.minlevel < noisyPower) {
1400 if ((aec->stateCounter > (0.5f * countLen * subCountLen))
1401 && (aec->farlevel.sfrcounter == 0)
1404 && (aec->farlevel.averagelevel > (actThreshold * aec->farlevel.minlevel))
1408 echo = aec->nearlevel.averagelevel - safety * aec->nearlevel.minlevel;
1411 dtmp = 10 * (float)log10(aec->farlevel.averagelevel /
1412 aec->nearlevel.averagelevel + 1e-10f);
1413 dtmp2 = 10 * (float)log10(aec->farlevel.averagelevel / echo + 1e-10f);
1415 aec->erl.instant = dtmp;
1416 if (dtmp > aec->erl.max) {
1417 aec->erl.max = dtmp;
1420 if (dtmp < aec->erl.min) {
1421 aec->erl.min = dtmp;
1424 aec->erl.counter++;
1425 aec->erl.sum += dtmp;
1426 aec->erl.average = aec->erl.sum / aec->erl.counter;
1429 if (dtmp > aec->erl.average) {
1430 aec->erl.hicounter++;
1431 aec->erl.hisum += dtmp;
1432 aec->erl.himean = aec->erl.hisum / aec->erl.hicounter;
1436 dtmp = 10 * (float)log10(aec->nearlevel.averagelevel /
1437 (2 * aec->linoutlevel.averagelevel) + 1e-10f);
1440 suppressedEcho = 2 * (aec->linoutlevel.averagelevel -
1441 safety * aec->linoutlevel.minlevel);
1445 aec->aNlp.instant = dtmp2;
1446 if (dtmp > aec->aNlp.max) {
1447 aec->aNlp.max = dtmp;
1450 if (dtmp < aec->aNlp.min) {
1451 aec->aNlp.min = dtmp;
1454 aec->aNlp.counter++;
1455 aec->aNlp.sum += dtmp;
1456 aec->aNlp.average = aec->aNlp.sum / aec->aNlp.counter;
1459 if (dtmp > aec->aNlp.average) {
1460 aec->aNlp.hicounter++;
1461 aec->aNlp.hisum += dtmp;
1462 aec->aNlp.himean = aec->aNlp.hisum / aec->aNlp.hicounter;
1468 suppressedEcho = 2 * (aec->nlpoutlevel.averagelevel -
1469 safety * aec->nlpoutlevel.minlevel);
1471 dtmp = 10 * (float)log10(aec->nearlevel.averagelevel /
1472 (2 * aec->nlpoutlevel.averagelevel) + 1e-10f);
1476 aec->erle.instant = dtmp;
1477 if (dtmp > aec->erle.max) {
1478 aec->erle.max = dtmp;
1481 if (dtmp < aec->erle.min) {
1482 aec->erle.min = dtmp;
1485 aec->erle.counter++;
1486 aec->erle.sum += dtmp;
1487 aec->erle.average = aec->erle.sum / aec->erle.counter;
1490 if (dtmp > aec->erle.average) {
1491 aec->erle.hicounter++;
1492 aec->erle.hisum += dtmp;
1493 aec->erle.himean = aec->erle.hisum / aec->erle.hicounter;
1497 aec->stateCounter = 0;