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 #include <stdlib.h>
00032 #include <stdio.h>
00033 #include <math.h>
00034
00035 #include "agc.h"
00036
00038 typedef struct s_agc
00039 {
00041 double maximum_gain;
00043 double minimum_gain;
00045 double max_amp;
00049 double noise_floor;
00051 double gain;
00052 te_agc_types agc_type;
00054 double gain_increase_correction_factor;
00056 double gain_decrease_correction_factor;
00057 } s_agc;
00058
00059 typedef double (* agc_algorithm)(agc gain_object, double current_amplitude);
00060
00061 static double agc_update_1(agc gain_object, double current_amplitude);
00062 static double agc_update_2(agc gain_object, double current_amplitude);
00063 static double agc_update_3(agc gain_object, double current_amplitude);
00064 static double agc_update_4(agc gain_object, double current_amplitude);
00065
00066 static const agc_algorithm AGC_ALGOR_TABLE[AGC_NUMBER_OF_ADJUSTMENT_TYPES] = {
00067 agc_update_1,
00068 agc_update_2,
00069 agc_update_3,
00070 agc_update_4
00071 };
00072
00073 agc agc_create(double max_gain,
00074 double min_gain,
00075 double noise_floor,
00076 double max_amp,
00077 te_agc_types agc_type,
00078 double gain_increase_correct,
00079 double gain_decrease_correct)
00080 {
00081 agc gain_object;
00082
00083 if((gain_object = malloc(sizeof(struct s_agc))) != NULL) {
00084 gain_object->maximum_gain = max_gain;
00085 gain_object->minimum_gain = min_gain;
00086 gain_object->noise_floor = noise_floor;
00087
00088 if(agc_type < AGC_NUMBER_OF_ADJUSTMENT_TYPES) {
00089 gain_object->agc_type = agc_type;
00090 }
00091 else {
00092 gain_object->agc_type = AGC_LINEAR_PEAK_LIMIT;
00093 }
00094
00095 gain_object->gain_increase_correction_factor = gain_increase_correct;
00096 gain_object->gain_decrease_correction_factor = gain_decrease_correct;
00097 gain_object->max_amp = max_amp;
00098 gain_object->gain = 1.0;
00099 }
00100 return gain_object;
00101 }
00102
00103 double agc_update(agc gain_object, double current_amplitude)
00104 {
00105 return AGC_ALGOR_TABLE[gain_object->agc_type](gain_object, current_amplitude);
00106 }
00107
00108 static double agc_update_1(agc gain_object, double current_amplitude)
00109 {
00110 if(current_amplitude > gain_object->max_amp) {
00111 gain_object->gain -= gain_object->gain_decrease_correction_factor;
00112 }
00113 else {
00114 if(gain_object->gain < gain_object->maximum_gain) {
00115 gain_object->gain += gain_object->gain_increase_correction_factor;
00116 }
00117 }
00118 return gain_object->gain;
00119 }
00120
00121 static double agc_update_2(agc gain_object, double current_amplitude)
00122 {
00123 double temp;
00124
00125 if(current_amplitude > gain_object->noise_floor)
00126 {
00127 if(current_amplitude < gain_object->max_amp) {
00128 if(gain_object->gain < gain_object->maximum_gain) {
00129 temp = (1.0 + gain_object->gain_increase_correction_factor);
00130 gain_object->gain *= temp;
00131 }
00132 }
00133 else if(current_amplitude >= gain_object->max_amp) {
00134 if(gain_object->gain > gain_object->minimum_gain) {
00135 temp = (1.0 - gain_object->gain_decrease_correction_factor);
00136 gain_object->gain *= temp;
00137 }
00138 }
00139 else { }
00140 }
00141 return gain_object->gain;
00142 }
00143
00144 static double agc_update_3(agc gain_object, double current_amplitude)
00145 {
00146 double temp;
00147
00148 if(current_amplitude > gain_object->max_amp) {
00149 temp = (1.0 - gain_object->gain_decrease_correction_factor);
00150 gain_object->gain *= temp;
00151 }
00152 else {
00153 if(gain_object->gain < gain_object->maximum_gain) {
00154 temp = (1.0 + gain_object->gain_increase_correction_factor);
00155 gain_object->gain *= temp;
00156 }
00157 }
00158 return gain_object->gain;
00159 }
00160
00161 static double agc_update_4(agc gain_object, double current_amplitude)
00162 {
00163 if(
00164 (current_amplitude > gain_object->max_amp)
00165 && \
00166 (gain_object->gain > 0.0)
00167 )
00168 {
00169 gain_object->gain = gain_object->max_amp / (current_amplitude / gain_object->gain);
00170 }
00171 else {
00172 if(gain_object->gain < gain_object->maximum_gain) {
00173 gain_object->gain += gain_object->gain_increase_correction_factor;
00174 }
00175 }
00176 return gain_object->gain;
00177 }
00178
00179 void agc_destroy(agc *gain_object)
00180 {
00181 free(*gain_object);
00182 *gain_object = NULL;
00183 }