unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, ComCtrls, ThdTimer; type TForm1 = class(TForm) PaintBox1: TPaintBox; Bevel1: TBevel; ComboBox1: TComboBox; Edit1: TEdit; Edit2: TEdit; UpDown1: TUpDown; UpDown2: TUpDown; Label1: TLabel; Label2: TLabel; Label3: TLabel; Edit3: TEdit; UpDown3: TUpDown; Label4: TLabel; FXTimer: TThreadedTimer; Label5: TLabel; PaintBox2: TPaintBox; Bevel2: TBevel; Edit4: TEdit; UpDown4: TUpDown; procedure paintOutput; procedure createGraph; procedure FormCreate(Sender: TObject); procedure ComboBox1Change(Sender: TObject); procedure UpDown1Click(Sender: TObject; Button: TUDBtnType); procedure UpDown2Click(Sender: TObject; Button: TUDBtnType); procedure Edit3Change(Sender: TObject); procedure FXTimerTimer(Sender: TObject); procedure UpDown4Click(Sender: TObject; Button: TUDBtnType); private { Private declarations } public { Public declarations } end; var Form1: TForm1; channels: byte; // no. of output channels output: array[0..200] of byte; // output data ringbuffer: array[0..200] of byte; // function is stored in offset: byte; // offset of function to 0 amplitude: byte; // amplitude of function phase: byte; // space between output cells in ringbuffer readPos: byte; // position of read pointer GraphBuf: TBitmap; // Back-Buffer implementation {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject); var i: integer; begin GraphBuf := TBitmap.create; GraphBuf.Width := 200; GraphBuf.height := 100; bitblt(GraphBuf.canvas.handle,0,0,205,145,0,0,0,blackness); // kill back-buffer for i:=0 to 200 do begin ringbuffer[i]:=0; output[i]:=0; end; amplitude:=127; offset:=127; phase:=1; readPos:=0; channels:=10; end; // select function procedure TForm1.ComboBox1Change(Sender: TObject); var i, buffer: integer; begin case ComboBox1.ItemIndex of 0: // sine begin for i:=0 to 200 do begin buffer:= offset + round(amplitude *sin(i *PI/100)); if buffer < 0 then buffer:=0; if buffer > 255 then buffer:= 255; ringbuffer[i]:= buffer; end; end; end; createGraph; end; // offset procedure TForm1.UpDown1Click(Sender: TObject; Button: TUDBtnType); begin offset:= UpDown1.Position; ComboBox1Change(Form1); end; // amplitude procedure TForm1.UpDown2Click(Sender: TObject; Button: TUDBtnType); begin amplitude:= UpDown2.Position; ComboBox1Change(Form1); end; // phase procedure TForm1.Edit3Change(Sender: TObject); begin phase:= UpDown3.Position; if phase * channels > 200 then begin phase:= 200 div channels; UpDown3.Position:= phase; end; end; // set channels procedure TForm1.UpDown4Click(Sender: TObject; Button: TUDBtnType); begin channels:= UpDown4.Position; end; // generate output procedure TForm1.FXTimerTimer(Sender: TObject); var i, buffer: integer; begin readPos:=readPos +1; if readPos > 200 then readPos:=0; label5.caption:= inttostr(readPos); for i:=0 to channels do begin buffer:= readPos +phase *i; if buffer > 200 then buffer:= buffer -200; output[i]:= ringbuffer[buffer]; end; paintOutput; end; // paint Outut Bar procedure TForm1.paintOutput; var i, lang, inkrement: integer; begin // bar with PaintBox1.Canvas do begin lang:=0; inkrement:= 300 div channels; for i:=0 to channels do begin Brush.Color:= RGB(0, Output[i], 0); FillRect(Rect(1,lang, 24, lang +inkrement)); lang:= lang +inkrement; end; end; // graph bitblt(PaintBox2.Canvas.Handle,0,0,200,100,GraphBuf.canvas.handle,0,0,srccopy); with PaintBox2.canvas do begin Pen.Color:= clRed; for i:=0 to channels do begin inkrement:= readPos +phase *i; if inkrement > 200 then inkrement:= inkrement -200; MoveTo(inkrement, 200); LineTo(inkrement,0); end; end; end; procedure TForm1.createGraph; var i: integer; begin with GraphBuf.Canvas do begin Brush.Color:= clBlack; Pen.Color:= clGreen; Rectangle(0,0,200,100); MoveTo(0,200); for i:=0 to 200 do begin LineTo(i, 92-(ringbuffer[i]div 3)); end; end; bitblt(PaintBox2.Canvas.Handle,0,0,200,100,GraphBuf.canvas.handle,0,0,srccopy); end; end.