mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
Add audio buffer setting and optimize overlays
This commit is contained in:
+153
-11
@@ -21,6 +21,7 @@ type
|
||||
FOnSelect: TModeFilterEvent;
|
||||
FOnDSPChange: TDSPChangeEvent;
|
||||
FOnAGCChange: TAGCChangeEvent;
|
||||
FOnInvalidate: TNotifyEvent;
|
||||
FModeFilter: array[0..7] of Integer;
|
||||
|
||||
FNRMode: Integer; // 0=off, 1..4=NR/NR2/NR3/NR4
|
||||
@@ -34,6 +35,8 @@ type
|
||||
FHitActions: array[0..24] of Integer;
|
||||
FHitCount: Integer;
|
||||
FHotIdx: Integer;
|
||||
FCacheBitmap: TBitmap;
|
||||
FCacheDirty: Boolean;
|
||||
|
||||
procedure DrawSelf(C: TCanvas; W, H: Integer);
|
||||
procedure DrawSMeterBar(C: TCanvas; X, Y, BW, BH: Integer);
|
||||
@@ -47,6 +50,7 @@ type
|
||||
function GetFilterBWForMode(ModeIdx, FilterIdx: Integer): Integer;
|
||||
function GetFilterLblForMode(ModeIdx, FilterIdx: Integer): string;
|
||||
function GetFilterCountForMode(ModeIdx: Integer): Integer;
|
||||
procedure RequestInvalidate;
|
||||
|
||||
protected
|
||||
procedure Paint; override;
|
||||
@@ -57,19 +61,28 @@ type
|
||||
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
procedure DrawOverlay(Target: TBitmap; W, H: Integer);
|
||||
function HandleMouseDown(Button: TMouseButton; X, Y: Integer): Boolean;
|
||||
function HandleMouseMove(X, Y: Integer): Boolean;
|
||||
function HandleMouseLeave: Boolean;
|
||||
procedure SetState(AMode, ABW: Integer; AVfoHz, ASMeterDB: Double);
|
||||
procedure SetDSPState(ANRMode, ANBMode: Integer; ASNBOn, AANFOn: Boolean;
|
||||
AAGCMode: Integer);
|
||||
procedure UpdateSMeter(DB: Double);
|
||||
procedure UpdateVfo(AVfoHz: Double);
|
||||
property HotIdx: Integer read FHotIdx;
|
||||
property OnSelect: TModeFilterEvent read FOnSelect write FOnSelect;
|
||||
property OnDSPChange: TDSPChangeEvent read FOnDSPChange write FOnDSPChange;
|
||||
property OnAGCChange: TAGCChangeEvent read FOnAGCChange write FOnAGCChange;
|
||||
property OnInvalidate: TNotifyEvent read FOnInvalidate write FOnInvalidate;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
KEY_COLOR = TColor($00FF00FF);
|
||||
|
||||
HIT_NR = -9;
|
||||
HIT_NB = -10;
|
||||
HIT_SNB = -11;
|
||||
@@ -126,6 +139,53 @@ const
|
||||
// S-шкала: S1..S9
|
||||
DB_S: array[1..9] of Double = (-121,-115,-109,-103,-97,-91,-85,-79,-73);
|
||||
|
||||
procedure BlendBitmapKey(Target, Source: TBitmap; DstX, DstY: Integer; Alpha: Byte);
|
||||
var
|
||||
Y, X, SX0, SY0, SX1, SY1, TY, InvA: Integer;
|
||||
SrcRow, DstRow: PByte;
|
||||
begin
|
||||
if (Target = nil) or (Source = nil) or (Alpha = 0) then Exit;
|
||||
SX0 := 0;
|
||||
SY0 := 0;
|
||||
SX1 := Source.Width;
|
||||
SY1 := Source.Height;
|
||||
if DstX < 0 then begin SX0 := -DstX; DstX := 0; end;
|
||||
if DstY < 0 then begin SY0 := -DstY; DstY := 0; end;
|
||||
if DstX + (SX1 - SX0) > Target.Width then SX1 := SX0 + Target.Width - DstX;
|
||||
if DstY + (SY1 - SY0) > Target.Height then SY1 := SY0 + Target.Height - DstY;
|
||||
if (SX1 <= SX0) or (SY1 <= SY0) then Exit;
|
||||
|
||||
InvA := 255 - Alpha;
|
||||
Target.BeginUpdate(False);
|
||||
Source.BeginUpdate(False);
|
||||
try
|
||||
for Y := SY0 to SY1 - 1 do
|
||||
begin
|
||||
TY := DstY + (Y - SY0);
|
||||
SrcRow := PByte(Source.ScanLine[Y]);
|
||||
DstRow := PByte(Target.ScanLine[TY]);
|
||||
if (SrcRow = nil) or (DstRow = nil) then Continue;
|
||||
Inc(SrcRow, SX0 * 4);
|
||||
Inc(DstRow, DstX * 4);
|
||||
for X := SX0 to SX1 - 1 do
|
||||
begin
|
||||
// KEY_COLOR is clFuchsia in pf32bit B,G,R order.
|
||||
if not ((SrcRow[0] = $FF) and (SrcRow[1] = $00) and (SrcRow[2] = $FF)) then
|
||||
begin
|
||||
DstRow[0] := Byte((Alpha * SrcRow[0] + InvA * DstRow[0]) div 255);
|
||||
DstRow[1] := Byte((Alpha * SrcRow[1] + InvA * DstRow[1]) div 255);
|
||||
DstRow[2] := Byte((Alpha * SrcRow[2] + InvA * DstRow[2]) div 255);
|
||||
end;
|
||||
Inc(SrcRow, 4);
|
||||
Inc(DstRow, 4);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
Source.EndUpdate(False);
|
||||
Target.EndUpdate(False);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TVfoOverlay.GetFilterBWForMode(ModeIdx, FilterIdx: Integer): Integer;
|
||||
begin
|
||||
case ModeIdx of
|
||||
@@ -206,11 +266,20 @@ begin
|
||||
FANFOn := False;
|
||||
FAGCMode := 0;
|
||||
FAGCPickerOpen := False;
|
||||
FCacheBitmap := TBitmap.Create;
|
||||
FCacheBitmap.PixelFormat := pf32bit;
|
||||
FCacheDirty := True;
|
||||
Width := 260;
|
||||
Height := OVL_H_NORM;
|
||||
Cursor := crHandPoint;
|
||||
end;
|
||||
|
||||
destructor TVfoOverlay.Destroy;
|
||||
begin
|
||||
FCacheBitmap.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TVfoOverlay.RegisterHit(HR: TRect; HV: Integer);
|
||||
begin
|
||||
if FHitCount > High(FHitRects) then Exit;
|
||||
@@ -219,6 +288,13 @@ begin
|
||||
Inc(FHitCount);
|
||||
end;
|
||||
|
||||
procedure TVfoOverlay.RequestInvalidate;
|
||||
begin
|
||||
FCacheDirty := True;
|
||||
inherited Invalidate;
|
||||
if Assigned(FOnInvalidate) then FOnInvalidate(Self);
|
||||
end;
|
||||
|
||||
function TVfoOverlay.FormatFreq(Hz: Double): string;
|
||||
var
|
||||
iM, iK, iH: Integer;
|
||||
@@ -534,6 +610,72 @@ begin
|
||||
DrawSelf(Canvas, Width, Height);
|
||||
end;
|
||||
|
||||
procedure TVfoOverlay.DrawOverlay(Target: TBitmap; W, H: Integer);
|
||||
begin
|
||||
if (not Visible) or (Target = nil) or (Width <= 0) or (Height <= 0) then Exit;
|
||||
if (Left >= W) or (Top >= H) then Exit;
|
||||
|
||||
if (FCacheBitmap.Width <> Width) or (FCacheBitmap.Height <> Height) then
|
||||
begin
|
||||
FCacheBitmap.SetSize(Width, Height);
|
||||
FCacheDirty := True;
|
||||
end;
|
||||
if FCacheDirty then
|
||||
begin
|
||||
FCacheBitmap.Canvas.Brush.Color := KEY_COLOR;
|
||||
FCacheBitmap.Canvas.Brush.Style := bsSolid;
|
||||
FCacheBitmap.Canvas.Pen.Style := psClear;
|
||||
FCacheBitmap.Canvas.FillRect(Rect(0, 0, Width, Height));
|
||||
DrawSelf(FCacheBitmap.Canvas, Width, Height);
|
||||
FCacheDirty := False;
|
||||
end;
|
||||
BlendBitmapKey(Target, FCacheBitmap, Left, Top, 218);
|
||||
end;
|
||||
|
||||
function TVfoOverlay.HandleMouseDown(Button: TMouseButton; X, Y: Integer): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
if not Visible then Exit;
|
||||
if (X < Left) or (Y < Top) or (X >= Left + Width) or (Y >= Top + Height) then Exit;
|
||||
MouseDown(Button, [], X - Left, Y - Top);
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function TVfoOverlay.HandleMouseMove(X, Y: Integer): Boolean;
|
||||
var
|
||||
I, OldHot, LX, LY: Integer;
|
||||
begin
|
||||
Result := False;
|
||||
if not Visible then Exit;
|
||||
LX := X - Left;
|
||||
LY := Y - Top;
|
||||
OldHot := FHotIdx;
|
||||
FHotIdx := -1;
|
||||
if (LX >= 0) and (LY >= 0) and (LX < Width) and (LY < Height) then
|
||||
for I := 0 to FHitCount - 1 do
|
||||
if PtInRect(FHitRects[I], Point(LX, LY)) then
|
||||
begin
|
||||
FHotIdx := I;
|
||||
Break;
|
||||
end;
|
||||
if FHotIdx <> OldHot then
|
||||
begin
|
||||
RequestInvalidate;
|
||||
Result := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TVfoOverlay.HandleMouseLeave: Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
if FHotIdx >= 0 then
|
||||
begin
|
||||
FHotIdx := -1;
|
||||
RequestInvalidate;
|
||||
Result := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TVfoOverlay.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
||||
X, Y: Integer);
|
||||
var
|
||||
@@ -556,7 +698,7 @@ begin
|
||||
FModeFilter[FMode] := FFilterBW;
|
||||
FMode := NewMode;
|
||||
FFilterBW := FModeFilter[FMode];
|
||||
Invalidate;
|
||||
RequestInvalidate;
|
||||
if Assigned(FOnSelect) then FOnSelect(FMode, FFilterBW);
|
||||
end;
|
||||
end
|
||||
@@ -568,7 +710,7 @@ begin
|
||||
FAGCPickerOpen := not FAGCPickerOpen;
|
||||
if FAGCPickerOpen then Height := OVL_H_AGC
|
||||
else Height := OVL_H_NORM;
|
||||
Invalidate;
|
||||
RequestInvalidate;
|
||||
end
|
||||
else
|
||||
begin
|
||||
@@ -578,7 +720,7 @@ begin
|
||||
HIT_SNB: FSNBOn := not FSNBOn;
|
||||
HIT_ANF: FANFOn := not FANFOn;
|
||||
end;
|
||||
Invalidate;
|
||||
RequestInvalidate;
|
||||
if Assigned(FOnDSPChange) then
|
||||
FOnDSPChange(FNRMode, FNBMode, FSNBOn, FANFOn);
|
||||
end;
|
||||
@@ -590,7 +732,7 @@ begin
|
||||
FAGCMode := HV - HIT_AGC_PICK_BASE;
|
||||
FAGCPickerOpen := False;
|
||||
Height := OVL_H_NORM;
|
||||
Invalidate;
|
||||
RequestInvalidate;
|
||||
if Assigned(FOnAGCChange) then FOnAGCChange(FAGCMode);
|
||||
end
|
||||
else if HV > 0 then
|
||||
@@ -600,7 +742,7 @@ begin
|
||||
begin
|
||||
FFilterBW := NewBW;
|
||||
FModeFilter[FMode] := FFilterBW;
|
||||
Invalidate;
|
||||
RequestInvalidate;
|
||||
if Assigned(FOnSelect) then FOnSelect(FMode, FFilterBW);
|
||||
end;
|
||||
end;
|
||||
@@ -617,13 +759,13 @@ begin
|
||||
for I := 0 to FHitCount - 1 do
|
||||
if PtInRect(FHitRects[I], Point(X, Y)) then
|
||||
begin FHotIdx := I; Break; end;
|
||||
if FHotIdx <> OldHot then Invalidate;
|
||||
if FHotIdx <> OldHot then RequestInvalidate;
|
||||
end;
|
||||
|
||||
procedure TVfoOverlay.MouseLeave;
|
||||
begin
|
||||
inherited;
|
||||
if FHotIdx >= 0 then begin FHotIdx := -1; Invalidate; end;
|
||||
if FHotIdx >= 0 then begin FHotIdx := -1; RequestInvalidate; end;
|
||||
end;
|
||||
|
||||
procedure TVfoOverlay.SetState(AMode, ABW: Integer; AVfoHz, ASMeterDB: Double);
|
||||
@@ -634,7 +776,7 @@ begin
|
||||
FModeFilter[FMode] := ABW;
|
||||
FVfoHz := AVfoHz;
|
||||
FSMeterDB := ASMeterDB;
|
||||
Invalidate;
|
||||
RequestInvalidate;
|
||||
end;
|
||||
|
||||
procedure TVfoOverlay.SetDSPState(ANRMode, ANBMode: Integer; ASNBOn, AANFOn: Boolean;
|
||||
@@ -645,7 +787,7 @@ begin
|
||||
FSNBOn := ASNBOn;
|
||||
FANFOn := AANFOn;
|
||||
FAGCMode := AAGCMode;
|
||||
Invalidate;
|
||||
RequestInvalidate;
|
||||
end;
|
||||
|
||||
procedure TVfoOverlay.UpdateSMeter(DB: Double);
|
||||
@@ -654,7 +796,7 @@ begin
|
||||
if Abs(DB - FSMeterDB) > 0.4 then
|
||||
begin
|
||||
FSMeterDB := DB;
|
||||
Invalidate;
|
||||
RequestInvalidate;
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -663,7 +805,7 @@ begin
|
||||
if FVfoHz <> AVfoHz then
|
||||
begin
|
||||
FVfoHz := AVfoHz;
|
||||
Invalidate;
|
||||
RequestInvalidate;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user