УФ
Новое АРУ по скату.
Код:
[Выделить]float32_t adcMin = 1;
float32_t nextAdc;
float32_t ampMax = 0;
uint8_t isMin = 0;
float32_t max = 0.8f;
void agcDo(float32_t *buffer) {
float32_t agcMetrTemp = 0;
uint16_t countBack = 10;
uint16_t idx = 0;
uint16_t idxMin = 0;
if (tim > 0)tim--; //уменьшение задержки
for (uint16_t i = 0; i < FRAME_SIZE; i++) {
float32_t a;
//a = (buffer[i] < 0.0f) ? -1.0f * buffer[i] : buffer[i];// adc V
a = fabsf(buffer[i]);
if (a > 0)nowAgc = max / a; //coeff --> 1, nowAgc=чем меньше - тем сильнее загибаем pOutLms, 1 макс усиление.
else nowAgc = max / 0.0001f;
if (nowAgc < agcLevel) { // всплеск V
tim = 10;//задежка отпускания
uint16_t downIdx = i;
uint16_t upIdx = i;
uint16_t exit = 1;
int direction = 0;//напрвление вниз (отрицательная синусоида)
if (buffer[i] > 0) direction = 1;//напрвление вверх (положительная синусоида)
while (exit) {
exit = 0;//выходим
if (direction) {//++
//going up
if (buffer[upIdx] <= buffer[upIdx + 1] && upIdx + 1 < FRAME_SIZE) {
upIdx++;
exit = 1;//не выходим
}
//go down
if (buffer[downIdx] >= buffer[downIdx - 1] && downIdx - 1 >= 0) {//&& buffer[downIdx - 1] >= 0
downIdx--;
exit = 1;//не выходим
}
} else { //--
//going up
if (buffer[upIdx] >= buffer[upIdx + 1] && upIdx + 1 < FRAME_SIZE) {
upIdx++;
exit = 1;//не выходим
}
//go down
if (buffer[downIdx] <= buffer[downIdx - 1] && downIdx - 1 >= 0) {// && buffer[downIdx - 1] <= 0
downIdx--;
exit = 1;//не выходим
}
}
}//while
if ((upIdx > downIdx) && i > 0 && i < FRAME_SIZE - 1) {
if (buffer[upIdx] != 0)
nowAgc = max / fabsf(buffer[upIdx]);//максимальное значение
else nowAgc = max / 0.0002f;
for (uint16_t z = downIdx; z <= upIdx; z++) {
double_t f = fabsf(buffer[z]) * nowAgc;
if (f > max) {//out
if (buffer[z] > 0) buffer[z] = max;
else buffer[z] = -max;
} else if (f > 0)//norm
buffer[z] *= nowAgc;
else {//out
if (buffer[z] >= 0) buffer[z] = 0.0002f;
else buffer[z] = -0.0002f;
}
}
i = upIdx;
} else {
double_t f = a * nowAgc;
if (f > max) {//out
if (buffer[i] > 0) buffer[i] = max;
else buffer[i] = -max;
} else if (f > 0)//norm
buffer[i] *= nowAgc;
else {//out
if (buffer[i] >= 0) buffer[i] = 0.0002f;
else buffer[i] = -0.0002f;
}
// //защита от прегруза
// if (buffer[i] < -max)buffer[i] = -(max-0.5f);
// if (buffer[i] > max) buffer[i] = max-0.5f;
//
}
agcLevel = nowAgc;
} else {//если спад V
double_t f;
float32_t cc = agcLevel + 0.005f;
if (tim == 0)f = a * cc;
else f = a * agcLevel;
if (f > max) {//out
if (buffer[i] > 0) buffer[i] = max;
else buffer[i] = -max;
} else if (f > 0) {//norm
if (tim == 0) {
agcLevel = cc;
buffer[i] *= cc;
} else buffer[i] *= agcLevel;
} else {//out
if (buffer[i] >= 0) buffer[i] = 0.0002f;
else buffer[i] = -0.0002f;
}
// //guard
// if (buffer[i] < -max)buffer[i] = -(max-0.5f);
// if (buffer[i] > max) buffer[i] = max-0.5f;
}
if (a > agcMetrTemp) agcMetrTemp = a; //s-meter макс V
}
// защита от перегруза
// for (uint16_t i = 0; i < FRAME_SIZE; i++) {
// if (buffer[i] < -max) buffer[i] = -max+0.2f;
// if (buffer[i] > max) buffer[i] = max-0.2f;
//
// }
agcMetr = agcMetrTemp; //s-meter
}