Hello everybody
.
I use the following code (audio spectrum wave), it works perfectly with Linux and Windows but with OSX, the graphic is not showed
(even after a Paintbox.refresh). Why ?
unit Ing_Spectrum;
{$mode objfpc}{$H+}
interface
uses Graphics, Classes,LCLType, LCLIntf;
type TSpectrum = Class(TObject)
private
BMPBuffer : TBitmap;
Img_Hand : THandle;
Img_W, Img_H : Integer;
No_Peaks : Integer;
Show_Peaks : Boolean;
BackC : TColor;
Bound1, Bound2 : Integer;
BCL, BCM, BCH : TColor;
PCL, PCM, PCH : TColor;
Spec_Data, Top_Peaks, Bar_Peaks : array of Single;
Peak_FR, Bar_FR : Single;
BarWidth, BarSpac, XOff : Integer;
Procedure Draw_It() ;
public
Constructor Create(Width, Height, Number_Peaks : Integer);
Procedure Draw_Spec(HWND : THandle; FFTData : array of single);
property Back_Colour : TColor read BackC write BackC;
property Bar_ColorL : TColor read BCL write BCL;
property Bar_ColorM : TColor read BCM write BCM;
property Bar_ColorH : TColor read BCH write BCH;
property Peak_ColorL : TColor read PCL write PCL;
property Peak_ColorM : TColor read PCM write PCM;
property Peak_ColorH : TColor read PCH write PCH;
Property Low_Bound : Integer read Bound1 write Bound1;
Property High_Bound : Integer read Bound2 write Bound2;
property Draw_Peaks : Boolean read Show_Peaks write Show_Peaks;
property Peak_Fall_Rate : Single read Peak_FR write Peak_FR;
property Bar_Fall_Rate : Single read Bar_FR write Bar_FR;
property Bar_Width : Integer read BarWidth write BarWidth;
property Bar_Spacing : Integer read BarSpac write BarSpac;
property X_Offset : Integer read XOff write XOff;
end;
implementation
Constructor TSpectrum.Create(Width, Height, Number_Peaks : Integer);
var
i : integer;
begin
// Default Settings
BCL := $0076B297; //green
BCM := $0017D6DD; //yellow
BCH := $001643EA; // red
PCL := $0076B297;
PCM := $0017D6DD;
PCH := $001643EA;
BackC := clBlack;
Bound1 := 20;
Bound2 := 40;
Show_Peaks := True;
Peak_FR := 0.5;
Bar_FR := 1.5;
BarWidth := 8;
BarSpac := 1;
XOff := 5;
No_Peaks := Number_Peaks;
SetLength(Top_Peaks, No_Peaks);
SetLength(Bar_Peaks, No_Peaks);
SetLength(Spec_Data, No_Peaks);
for i := 0 to No_Peaks - 1 do
begin
Bar_Peaks[i] := 0;
Top_Peaks[i] := 0;
Spec_Data[i] := 0;
end;
Img_W := Width;
Img_H := Height;
// BMPBuffer.clear ;
BMPBuffer := TBitmap.Create;
// BMPBuffer.Parent.DoubleBuffered := true;
BMPBuffer.Height := Img_H;
BMPBuffer.Width := Img_W;
end;
Procedure TSpectrum.Draw_Spec(HWND : THandle; FFTData : array of single);
var
i : Integer;
begin
Img_Hand := HWND;
for i := 0 to No_Peaks - 1 do Spec_Data[i] := FFTData[i];
Draw_It() ;
end;
Procedure TSpectrum.Draw_It() ;
var
i, j, k, r, wd, wdp, toppoint : Integer;
begin
BMPBuffer.Canvas.Brush.Color := clblack;
BMPBuffer.Canvas.FillRect(Rect(0, 0, Img_W, Img_H));
// BMPBuffer.Canvas.gradientfill(Rect(0,0,Img_W, Img_H),clblack,BackC,gdvertical) ;
// PaintBox2.Canvas.gradientfill(Rect(0,0,PaintBox2.width, PaintBox2.height),clblack,$00450000,gdvertical) ;
BitBlt(Img_Hand, 0, 0, Img_W, Img_H, BMPBuffer.Canvas.Handle, 0, 0, SRCCOPY);
j := XOff;
for i := 0 to No_Peaks-1 do
begin
//////////////////// Peaks
If Show_Peaks = True then
begin
If Top_Peaks[i] > 0 then Top_Peaks[i] := Top_Peaks[i] - Peak_FR;
If Top_Peaks[i] <= Bound1 *2 then BMPBuffer.Canvas.Pen.Color := BCL;
If (Top_Peaks[i] > Bound1 *2) and (Top_Peaks[i] < Bound2*2) then BMPBuffer.Canvas.Pen.Color := BCM;
If Top_Peaks[i] >= Bound2 * 2 then BMPBuffer.Canvas.Pen.Color := BCH;
If Spec_Data[i] > Top_Peaks[i] then Top_Peaks[i] := Spec_Data[i];
toppoint := ((Img_H - 5)-(Round(Top_Peaks[i]/2)));
BMPBuffer.Canvas.MoveTo(j, toppoint);
BMPBuffer.Canvas.LineTo(j+BarWidth, toppoint);
end;
j := j + BarSpac;
//////////////////// Bars
wd := Round(Spec_Data[i]) div 2 ;
If Bar_Peaks[i] > 0 then Bar_Peaks[i] := Bar_Peaks[i] - Bar_FR;
If wd > Bar_Peaks[i] then Bar_Peaks[i] := wd else wd := Round(Bar_Peaks[i]);
r := Trunc(Spec_Data[i])+1;
for k := 0 to wd do
begin
wdp := (Img_H+Trunc(Spec_Data[i])) - r;
r := r + 1;
If Img_H - wdp <= Bound1 then BMPBuffer.Canvas.Pen.Color := BCL;
If (Img_H - wdp > Bound1) and (Img_H - wdp < Bound2) then BMPBuffer.Canvas.Pen.Color := BCM;
If Img_H - wdp >= Bound2 then BMPBuffer.Canvas.Pen.Color := BCH;
BMPBuffer.Canvas.MoveTo((j-(BarSpac+1))+BarWidth, wdp);
BMPBuffer.Canvas.LineTo(j-(BarSpac+1), wdp);
end;
j := j + BarSpac;
end;
//////////////////// Drawing
BitBlt(Img_Hand, 0, 0, Img_W, Img_H, BMPBuffer.Canvas.Handle, 0, 0, SRCCOPY);
end;
end.
To use that code, in form1.formcreate :
My_Spectrum := TSpectrum.Create(PaintBox1.width, PaintBox1.height, 15); // Create a new Spectrum object with 16 bars
My_Spectrum.Back_Colour := $00003D00; // The background color
My_Spectrum.Bar_ColorL := $0076B297; // The bar color below the lowest bound
My_Spectrum.Bar_ColorM := $0017D6DD; // The bar color above the lowest bound
My_Spectrum.Bar_ColorH := $001643EA; // The bar color above the high bound
My_Spectrum.Peak_ColorL := $0076B297; // The peak color below the lowest bound
My_Spectrum.Peak_ColorM := $0017D6DD; // The peak color above the lowest bound
My_Spectrum.Peak_ColorH := $001643EA; // The peak color above the highest bound
My_Spectrum.Low_Bound := 10; // The top of the lowest bound at which colors will change
My_Spectrum.High_Bound := 20; // The bottom of the highest bound at which colors will change
My_Spectrum.Draw_Peaks := false; // Draw the peaks?
My_Spectrum.Peak_Fall_Rate := 0.5; // The rate at which the peaks fall
My_Spectrum.Bar_Fall_Rate := 1.5; // The rate at which the bars fall
My_Spectrum.Bar_Width := 7 ; // The width of the bars
My_Spectrum.Bar_Spacing := 4; // The space between the bars
My_Spectrum.X_Offset := 0; // The distance the first bar is from the side of canvas
And to show the spectrum, in a timer (paintbox1.Refresh do not help) :
GetData() ; // My proc to get and sort the data
My_Spectrum.Draw_Spec(paintbox1.Canvas.Handle, Scaled_FFT2); // Do the actual drawing to a paint box
{$IFDEF Darwin}
paintbox1.Refresh;
{$ENDIF}
And the procedure
getdata() (
Bass_ChannelGetData is a procedure from the Bass audio Library) :
procedure TMiXimumLP.GetData() ;
var
// Various variables
x, y : integer;
tot_sum : float;
begin
if (Breverselp1.tag = 0) then Bass_ChannelGetData(chan, @FFT, BASS_DATA_FFT2048)
else Bass_ChannelGetData(chanreverse, @FFT, BASS_DATA_FFT2048); // Get the data
for x := 0 to 14 do // 0 to 15 bars = 16 bars
begin
tot_sum := 0; // 0 so far
for y := Bin_Dist[x] to Bin_Dist[x+1] do tot_sum := tot_sum + (FFT[y]); // Add up all data in the fft bins
tot_sum := sqrt(tot_sum); // Square root it to make smaller values more visible
Scaled_FFT[x] := tot_sum * 50; // Just get the numbers a little larger to work with
end;
end;
PS: The problem is only graphic, Bass audio Library works perfectly in Lazarus OSX.
Thanks