Вот ару которая у меня в сдр трудилась. Алгоритм сдерт со статей
Gerald Youngblood, K5SDR в QEX.
procedure TDSPAGCYB.DataEvent;
var px: PFloat32;
pf: PFloatArray absolute px;
j: Integer;
bf: TBuffer;
Vpk, Gain, GainStep, val: TFloat32;
AGCHang,ms1: integer;
begin
bf:=InputPin.Get;
if bf <> nil then begin
if Enabled and (HangTime > 0) then begin
AGCHang:=Round((1000*bf.Size)/(1.0*HangTime*bf.SampleRate));
ms1:=(bf.SampleRate+500) div 1000; // samples per 1 msec
if ms1 > bf.Size then ms1:=bf.Size;
if ms1 = 0 then ms1:=1;
px:=bf_Data(bf);
if AGCHang < 1 then AGCHang:=1
else if AGCHang >= MAX_Hang then AGCHang:=MAX_Hang;
Inc(AGCLoop);
if AGCLoop >= AGCHang then AGCLoop:=0;
// Get peak magnitude
Vpk:=0;
for j:=bf.Size-1 downto 0 do begin
val:=Abs(px^);
if val > Vpk then Vpk:=val;
Inc(px);
end;
if Vpk > 0 then begin
bf_Write(bf);
// AGC gain factor with 6 dB headroom
Gb[AGCLoop]:=NormalLevel/Vpk;
// Find peak gain reduction (Min)
Gain:=1e+6;
for j:=AGCHang-1 downto 0 do begin
if Gb[j] < Gain then Gain:=Gb[j];
end;
// Limit Gain to MaxGain
if Gain > MaxGain then Gain:=MaxGain;
// agc
pf:=bf_Data(bf);
if Gain < PrevGain then begin
// AGC Gain is decreasing
GainStep := (PrevGain - Gain) / ms1; // 44 Sample ramp = 1 ms attack time
for j:=0 to ms1-1 do // Ramp Gain down over 1 ms period
pf[j]:=pf[j]*(PrevGain - ((j + 1) * GainStep));
//for j:=ms1 to bf.Size-1 do // Multiply remaining Envelope by Gain
// pf[j]:=pf[j] * Gain;
MulConst_Buff(@pf[ms1],bf.Size-ms1,Gain);
end else if Gain > PrevGain then begin
// AGC Gain is increasing
GainStep := (Gain - PrevGain) / ms1; // 44 Sample ramp = 1 ms attack time
for j:=0 to ms1-1 do // Ramp Gain down over 1 ms period
pf[j]:=pf[j]*(PrevGain + ((j + 1) * GainStep));
//for j:=ms1 to bf.Size-1 do // Multiply remaining Envelope by Gain
// pf[j]:=pf[j] * Gain;
MulConst_Buff(@pf[ms1],bf.Size-ms1,Gain);
end else
MulConst_Buff(px,bf.Size,Gain); // Multiply Envelope by AGC gain
PrevGain:=Gain; // Save Gain for next loop
PropertyChanged(idCurrentGain);
end;
end else if MaxGain > 0 then begin
bf_Write(bf);
MulConst_Buff(bf_Data(bf),bf.Size,MaxGain);
end;
OutputPin.Put(bf);
end;
end;