Recent

Author Topic: [solved] Graphic not refresh with OS X ?  (Read 8189 times)

Fred vS

  • Hero Member
  • *****
  • Posts: 3168
    • StrumPract is the musicians best friend
[solved] Graphic not refresh with OS X ?
« on: July 08, 2011, 01:05:59 pm »
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 ?

Code: [Select]
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 :

Code: [Select]
      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) :

Code: [Select]
    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) :

Code: [Select]
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
« Last Edit: July 12, 2011, 01:34:37 am by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Fred vS

  • Hero Member
  • *****
  • Posts: 3168
    • StrumPract is the musicians best friend
Re: Graphic not refresh with OSX ?
« Reply #1 on: July 11, 2011, 11:40:46 pm »
Toc, toc, toc, is there anybody here ?  %)
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Blaazen

  • Hero Member
  • *****
  • Posts: 3241
  • POKE 54296,15
    • Eye-Candy Controls
Re: Graphic not refresh with OS X ?
« Reply #2 on: July 12, 2011, 12:04:12 am »
I overlooked this because I usualy don't read OS X threads.
This is known behaviour. Not all widgetsets are the same. Qt4 and Carbon do not allow to paint outside of the Paint method. When you say that it works on Linux, you mean GTK2, yes?
Solution: Move code to OnPaint method and only call Repaint. Repaint will fire OnPaint event and method will run. This should work (I hope).
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

Fred vS

  • Hero Member
  • *****
  • Posts: 3168
    • StrumPract is the musicians best friend
Re: Graphic not refresh with OS X ?
« Reply #3 on: July 12, 2011, 12:31:49 am »
@ Blaazen.

 :P

I gonna directly try that, thaaaanks.
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Fred vS

  • Hero Member
  • *****
  • Posts: 3168
    • StrumPract is the musicians best friend
Re: Graphic not refresh with OS X ?
« Reply #4 on: July 12, 2011, 01:33:46 am »
@ Mr Blaazen :

YOU ARE THE BEST

That does the trick :

Code: [Select]
procedure TMiXimumLP.paintbox1Paint(Sender: TObject);
                      begin                       My_Spectrum.Draw_Spec(paintbox1.Canvas.Handle, Scaled_FFT); // Do the actual drawing to a paint box
                       end; 

and in timer :

Code: [Select]
My_Spectrum.Draw_Spec(paintbox1.Canvas.Handle, Scaled_FFT); //// Must be recall in OS X otherwise not show

paintbox1.repaint;



Mr Blaazen you are very lucid, i was thinking nobody could understand me. Congratulations.

PS : What is the difference between paintbox.refresh and paintbox.repaint ?

Many, many, many thanks.

PS2 : The new version of miXimum for OS X, the DJ's best friend, with full spectrum and VU (like for GTK2 and Windows) is available there :
https://sites.google.com/site/fiensprototyping/home

 ::)
« Last Edit: July 12, 2011, 02:13:44 am by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Blaazen

  • Hero Member
  • *****
  • Posts: 3241
  • POKE 54296,15
    • Eye-Candy Controls
Re: [solved] Graphic not refresh with OS X ?
« Reply #5 on: July 12, 2011, 01:52:04 am »
A few weeks ago I found this short article:
http://stackoverflow.com/questions/1251009/whats-the-difference-between-refresh-update-repaint
But I really don't know if it is exactly the same in Lazarus because Laz. is not the same as Delphi.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

Fred vS

  • Hero Member
  • *****
  • Posts: 3168
    • StrumPract is the musicians best friend
Re: [solved] Graphic not refresh with OS X ?
« Reply #6 on: July 12, 2011, 02:03:11 am »
@ Mr Blaazen

Quote
A few weeks ago I found this short article:
http://stackoverflow.com/questions/1251009/whats-the-difference-between-refresh-update-repaint
But I really don't know if it is exactly the same in Lazarus because Laz. is not the same as Delphi.

Humm, i do not exactly feel the difference between refresh vs repaint...

What is your opinion, should i use repaint in place of all other refresh ?
Witch one use less memory ?

I have try changing all refresh into repaint but i do not see-feel any difference....
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Fred vS

  • Hero Member
  • *****
  • Posts: 3168
    • StrumPract is the musicians best friend
Re: [solved] Graphic not refresh with OS X ?
« Reply #7 on: July 12, 2011, 02:18:26 am »
@ Mr Blaazen

I gonna start a new topic about refresh vs repaint in general programming.

Many thanks for your help.
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

 

TinyPortal © 2005-2018