Ибо получается что или ничего не слышно, или дунет ветерок, а динамик аж трищит - на лицо необходимость регулировки.
Собственно, после недолгих раздумий, действовал так:
Определил верхний порог: AGC_MINTHRESHOLD
нижний порог: AGC_MAXTHRESHOLD
На асме зарулил функцию, быстро считающую сумму квадратов переданного ей буфера из 320 отсчётов сигнала
И сам AGC
Код
unsigned long do_agc(int *input, int len){
//считаем энергию сигнала
agc_currEnergy=my_sqrsum(input,len);
if(agc_currEnergy==0)
return agc_currEnergy; //AGC не требуется - на выход
if(agc_currEnergy>=AGC_MINTHRESHOLD && agc_currEnergy<=AGC_MAXTHRESHOLD)
return agc_currEnergy; //AGC не требуется
else
if(agc_currEnergy<AGC_MINTHRESHOLD){ //надо бы усилить
agc_multiplier=sqrt((double)AGC_MINTHRESHOLD/(double)agc_currEnergy);
}
else
if(agc_currEnergy>AGC_MAXTHRESHOLD){//придётся сделать немного потише :)
agc_multiplier=sqrt((double)AGC_MAXTHRESHOLD/(double)agc_currEnergy);
}
//а теперь подправим сигнал
while(len--)
*input++=(int)((double)*input * agc_multiplier);
return agc_currEnergy;
}
//считаем энергию сигнала
agc_currEnergy=my_sqrsum(input,len);
if(agc_currEnergy==0)
return agc_currEnergy; //AGC не требуется - на выход
if(agc_currEnergy>=AGC_MINTHRESHOLD && agc_currEnergy<=AGC_MAXTHRESHOLD)
return agc_currEnergy; //AGC не требуется
else
if(agc_currEnergy<AGC_MINTHRESHOLD){ //надо бы усилить
agc_multiplier=sqrt((double)AGC_MINTHRESHOLD/(double)agc_currEnergy);
}
else
if(agc_currEnergy>AGC_MAXTHRESHOLD){//придётся сделать немного потише :)
agc_multiplier=sqrt((double)AGC_MAXTHRESHOLD/(double)agc_currEnergy);
}
//а теперь подправим сигнал
while(len--)
*input++=(int)((double)*input * agc_multiplier);
return agc_currEnergy;
}
От нижнего порога в итоге пришлось отказаться, т.к. регулировка чувствительности микрофона "железными" средствами аудиокодека вроде позволяет добиться неплохой чувствительности.
Верхний тоже вроде режет лишку и с диким теском, от того, что ты подул в микрофон вроде покончено.
Но в целом мне не нравится работа АРУ. Оно то и понятно, ведь то, что я сделал - достаточно тривиально.
Погуглить пробовал, но не так усердно, как мог бы.
Вот прошу пару подсказок.
Также, подозреваю, что и вокодер работал бы эффективнее и качественнее, при наличии грамотно спроектированного и настроенного AGC.
Традиционно, с громоздким и прожорливым Speex препроцессором связываться не хотелось-бы.
Беглого взгляда на функцию, реализующую AGC в speex хватило, чтобы понять, что там наворочено много всего и половина из этого мне не нужна.
Да и заодно практика будет.
В общем покритикуйте мою реализацию плиз. И дайте совет как бы завернуть так, чтобы и голос был loud and clear и в момент громких всплесков было всё хорошо. Ну а я пока параллельно буду гуглить и напрягать CPU:)