home *** CD-ROM | disk | FTP | other *** search
/ PC Format (South-Africa) 2001 May / PCFMay2001.iso / Xenon / ModBass / Delphi / 3dTest / DTMain.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2000-02-24  |  15.2 KB  |  637 lines

  1. unit DTMain;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  7.   StdCtrls, ExtCtrls, BASS, Math;
  8.  
  9. const
  10.   MV_LEFT            = 1;
  11.   MV_RIGHT           = 2;
  12.   MV_UP              = 4;
  13.   MV_DOWN            = 8;
  14.  
  15.   XDIST              = 70;
  16.   YDIST              = 65;
  17.   XCENTER            = 268;
  18.   YCENTER            = 92;
  19.  
  20.   DIAM               = 10;
  21.  
  22.   MAXDIST            = 500;             // maximum distance of the channels (m)
  23.   SPEED              = 5.0;             // speed of the channels' movement (m/s)
  24.   PAR                = 50;
  25.  
  26. type
  27.   PSource = ^TSource;
  28.   TSource = record
  29.     x, y: Float;
  30.     next: PSource;
  31.     movement: Integer;
  32.     sample, channel: Integer;
  33.     playing: Boolean;
  34.   end;
  35.  
  36.   TForm1 = class(TForm)
  37.     GroupBox1: TGroupBox;
  38.     ListBox1: TListBox;
  39.     Button1: TButton;
  40.     Button2: TButton;
  41.     Button3: TButton;
  42.     Button4: TButton;
  43.     Bevel1: TBevel;
  44.     StaticText1: TStaticText;
  45.     RadioButton1: TRadioButton;
  46.     RadioButton2: TRadioButton;
  47.     RadioButton3: TRadioButton;
  48.     RadioButton4: TRadioButton;
  49.     RadioButton5: TRadioButton;
  50.     GroupBox2: TGroupBox;
  51.     ComboBox1: TComboBox;
  52.     GroupBox3: TGroupBox;
  53.     GroupBox4: TGroupBox;
  54.     ScrollBar1: TScrollBar;
  55.     ScrollBar2: TScrollBar;
  56.     GroupBox5: TGroupBox;
  57.     Label1: TLabel;
  58.     CheckBox1: TCheckBox;
  59.     ScrollBar3: TScrollBar;
  60.     Bevel2: TBevel;
  61.     Timer1: TTimer;
  62.     Bevel3: TBevel;
  63.     OpenDialog1: TOpenDialog;
  64.     procedure FormCreate(Sender: TObject);
  65.     procedure FormPaint(Sender: TObject);
  66.     procedure Timer1Timer(Sender: TObject);
  67.     procedure Button1Click(Sender: TObject);
  68.     procedure FormDestroy(Sender: TObject);
  69.     procedure ListBox1Click(Sender: TObject);
  70.     procedure Button2Click(Sender: TObject);
  71.     procedure ListBox1KeyDown(Sender: TObject; var Key: Word;
  72.       Shift: TShiftState);
  73.     procedure Button3Click(Sender: TObject);
  74.     procedure Button4Click(Sender: TObject);
  75.     procedure RadioButton1Click(Sender: TObject);
  76.     procedure RadioButton2Click(Sender: TObject);
  77.     procedure RadioButton3Click(Sender: TObject);
  78.     procedure RadioButton4Click(Sender: TObject);
  79.     procedure RadioButton5Click(Sender: TObject);
  80.     procedure ComboBox1Change(Sender: TObject);
  81.     procedure CheckBox1Click(Sender: TObject);
  82.     procedure ScrollBar3Change(Sender: TObject);
  83.     procedure ScrollBar1Change(Sender: TObject);
  84.     procedure ScrollBar2Change(Sender: TObject);
  85.   private
  86.     { Private-Deklarationen }
  87.     sources: PSource;
  88.     procedure Error(msg: string);
  89.     procedure AddSource(name: string);
  90.     procedure RemSource(num: Integer);
  91.     function GetSource(num: Integer): PSource;
  92.     procedure DrawSources;
  93.     procedure FreeSources;
  94.     procedure ActualizeSources(forceupdate: Boolean);
  95.     procedure ActualizeButtons;
  96.     function GetVel(p: PSource): BASS_3DVECTOR;
  97.   public
  98.     { Public-Deklarationen }
  99.   end;
  100.  
  101. var
  102.   Form1: TForm1;
  103.  
  104. implementation
  105.  
  106. uses DTSelect;
  107.  
  108. {$R *.DFM}
  109.  
  110. procedure TForm1.Error(msg: string);
  111. var
  112.   s: string;
  113. begin
  114.   s := msg + #13#10 + '(error code: ' + IntToStr(BASS_ErrorGetCode) + ')';
  115.   MessageBox(handle, PChar(s), 'Error', MB_ICONERROR or MB_OK);
  116. end;
  117.  
  118. procedure TForm1.FormCreate(Sender: TObject);
  119. begin
  120.   sources := nil;
  121. end;
  122.  
  123. procedure TForm1.AddSource(name: string);
  124. var
  125.   p, last: PSource;
  126.   newchan, newsamp: Integer;
  127.   sam: BASS_SAMPLE;
  128. begin
  129.   newsamp := 0;
  130.   // Load a music from "file" with 3D enabled, and make it loop & use ramping
  131.   newchan := BASS_MusicLoad(FALSE, PChar(name), 0, 0, BASS_MUSIC_RAMP or BASS_MUSIC_LOOP or BASS_MUSIC_3D);
  132.   if (newchan <> 0) then
  133.   begin
  134.     // Set the min/max distance to 15/1000 meters
  135.     BASS_ChannelSet3DAttributes(newchan, -1, 35.0, 1000.0, -1, -1, -1);
  136.   end
  137.   else
  138.   begin
  139.     // Load a sample from "file" with 3D enabled, and make it loop
  140.     newsamp := BASS_SampleLoad(FALSE, PChar(name), 0, 0, 1, BASS_SAMPLE_LOOP or BASS_SAMPLE_3D or BASS_SAMPLE_VAM);
  141.     if (newsamp <> 0) then
  142.       begin
  143.       // Set the min/max distance to 15/1000 meters
  144.       BASS_SampleGetInfo(newsamp, sam);
  145.       sam.mindist := 35.0;
  146.       sam.maxdist := 1000.0;
  147.       BASS_SampleSetInfo(newsamp, sam);
  148.     end;
  149.   end;
  150.   if (newchan = 0) and (newsamp = 0) then
  151.   begin
  152.     Error('Can''t load file');
  153.     Exit;
  154.   end;
  155.  
  156.   New(p);
  157.   p.x := 0;
  158.   p.y := 0;
  159.   p.movement := 0;
  160.   p.sample := newsamp;
  161.   p.channel := newchan;
  162.   p.playing := FALSE;
  163.   p.next := nil;
  164.   last := sources;
  165.   if last <> nil then
  166.     while (last.next <> nil) do last := last.next;
  167.   if last = nil then
  168.     sources := p
  169.   else
  170.     last.next := p;
  171.   ListBox1.Items.Add(name);
  172.   ActualizeButtons;
  173. end;
  174.  
  175. procedure TForm1.RemSource(num: Integer);
  176. var
  177.   p, prev: PSource;
  178.   i: Integer;
  179. begin
  180.   prev := nil;
  181.   p := sources;
  182.   i := 0;
  183.   while (p <> nil) and (i < num) do
  184.   begin
  185.     Inc(i);
  186.     prev := p;
  187.     p := p.next;
  188.   end;
  189.   if (p <> nil) then
  190.   begin
  191.     if (prev <> nil) then
  192.       prev.next := p.next
  193.     else
  194.       sources := p.next;
  195.     if (p.sample <> 0) then
  196.       BASS_SampleFree(p.sample)
  197.     else
  198.       BASS_MusicFree(p.channel);
  199.     Dispose(p);
  200.   end;
  201.   ListBox1.Items.Delete(num);
  202.   ActualizeButtons;
  203. end;
  204.  
  205. function TForm1.GetSource(num: Integer): PSource;
  206. var
  207.   p: PSource;
  208.   i: Integer;
  209. begin
  210.   if num < 0 then
  211.   begin
  212.     Result := nil;
  213.     Exit;
  214.   end;
  215.   p := sources;
  216.   i := 0;
  217.   while (p <> nil) and (i < num) do
  218.   begin
  219.     Inc(i);
  220.     p := p.next;
  221.   end;
  222.   Result := p;
  223. end;
  224.  
  225. procedure TForm1.DrawSources;
  226. var
  227.   p: PSource;
  228.   i, j: Integer;
  229. begin
  230.   p := sources;
  231.   with Canvas do
  232.   begin
  233.     Brush.Color := Form1.Color;
  234.     Pen.Color := Form1.Color;
  235.     Rectangle(XCENTER - XDIST - DIAM,
  236.               YCENTER - YDIST - DIAM,
  237.               XCENTER + XDIST + DIAM,
  238.               YCENTER + YDIST + DIAM);
  239.     Brush.Color := clGray;
  240.     Pen.Color := clBlack;
  241.     Ellipse(XCENTER - DIAM div 2,
  242.             YCENTER - DIAM div 2,
  243.             XCENTER + DIAM div 2,
  244.             YCENTER + DIAM div 2);
  245.     Pen.Color := Form1.Color;
  246.     i := 0; j := ListBox1.ItemIndex;
  247.     while (p <> nil) do
  248.     begin
  249.       if (i = j) then
  250.         Brush.Color := clRed
  251.       else
  252.         Brush.Color := clBlack;
  253.         Ellipse(XCENTER + Trunc(p.x * XDIST / MAXDIST) - DIAM div 2,
  254.                 YCENTER + Trunc(p.y * YDIST / MAXDIST) - DIAM div 2,
  255.                 XCENTER + Trunc(p.x * XDIST / MAXDIST) + DIAM div 2,
  256.                 YCENTER + Trunc(p.y * YDIST / MAXDIST) + DIAM div 2);
  257.       p := p.next;
  258.       Inc(i);
  259.     end;
  260.   end;
  261. end;
  262.  
  263. procedure TForm1.ActualizeSources(forceupdate: Boolean);
  264. var
  265.   p: PSource;
  266.   chng, fchng: Boolean;
  267.   pos, rot, vel: BASS_3DVECTOR;
  268. begin
  269.   pos.y := 0;
  270.   rot.x := 0;
  271.   rot.y := 0;
  272.   rot.z := 0;
  273.   fchng := forceupdate;
  274.   p := sources;
  275.   while (p <> nil) do
  276.   begin
  277.     chng := forceupdate;
  278.     if (p.playing) then
  279.     begin
  280.       if ((p.movement and MV_LEFT) = MV_LEFT) then
  281.       begin
  282.         p.x := p.x - SPEED;
  283.         chng := TRUE;
  284.       end;
  285.       if ((p.movement and MV_RIGHT) = MV_RIGHT) then
  286.       begin
  287.         p.x := p.x + SPEED;
  288.         chng := TRUE;
  289.       end;
  290.       if ((p.movement and MV_UP) = MV_UP) then
  291.       begin
  292.         p.y := p.y - SPEED;
  293.         chng := TRUE;
  294.       end;
  295.       if ((p.movement and MV_DOWN) = MV_DOWN) then
  296.       begin
  297.         p.y := p.y + SPEED;
  298.         chng := TRUE;
  299.       end;
  300.       if (p.x < -MAXDIST) then
  301.       begin
  302.         p.x := -MAXDIST;
  303.         p.movement := MV_RIGHT;
  304.       end;
  305.       if (p.x > MAXDIST) then
  306.       begin
  307.         p.x := MAXDIST;
  308.         p.movement := MV_LEFT;
  309.       end;
  310.       if (p.y < -MAXDIST) then
  311.       begin
  312.         p.y := -MAXDIST;
  313.         p.movement := MV_DOWN;
  314.       end;
  315.       if (p.y > MAXDIST) then
  316.       begin
  317.         p.y := MAXDIST;
  318.         p.movement := MV_UP;
  319.       end;
  320.       if chng then
  321.       begin
  322.         pos.x := p.x;
  323.         pos.z := -p.y;
  324.         vel := getVel(p);
  325.     BASS_ChannelSet3DPosition(p.channel, pos, rot, vel);
  326.       end;
  327.     end;
  328.     p := p.next;
  329.     if chng then fchng := TRUE;
  330.   end;
  331.   if fchng then
  332.   begin
  333.     DrawSources;
  334.     BASS_Apply3D;
  335.   end;
  336. end;
  337.  
  338. procedure TForm1.FreeSources;
  339. var
  340.   p, v: PSource;
  341. begin
  342.   p := sources;
  343.   while (p <> nil) do
  344.   begin
  345.     v := p.next;
  346.     Dispose(v);
  347.     p := v;
  348.   end;
  349.   sources := nil;
  350. end;
  351.  
  352. procedure TForm1.FormPaint(Sender: TObject);
  353. begin
  354.   DrawSources;
  355. end;
  356.  
  357. procedure TForm1.Timer1Timer(Sender: TObject);
  358. begin
  359.   ActualizeSources(FALSE);
  360. end;
  361.  
  362. procedure TForm1.Button1Click(Sender: TObject);
  363. begin
  364.   If OpenDialog1.Execute then
  365.   begin
  366.     AddSource(OpenDialog1.FileName);
  367.   end;
  368. end;
  369.  
  370. procedure TForm1.FormDestroy(Sender: TObject);
  371. begin
  372.   FreeSources;
  373.   BASS_Stop;
  374.   BASS_Free;
  375. end;
  376.  
  377. procedure TForm1.ActualizeButtons;
  378. var
  379.   en: Boolean;
  380.   p: PSource;
  381. begin
  382.   en := (ListBox1.ItemIndex >= 0);
  383.   Button2.Enabled := en;
  384.   Button3.Enabled := en;
  385.   Button4.Enabled := en;
  386.   RadioButton1.Enabled := en;
  387.   RadioButton2.Enabled := en;
  388.   RadioButton3.Enabled := en;
  389.   RadioButton4.Enabled := en;
  390.   RadioButton5.Enabled := en;
  391.   DrawSources;
  392.   p := GetSource(ListBox1.ItemIndex);
  393.   if p = nil then Exit;
  394.   if (p.x = -PAR) and ((p.movement = MV_UP) or (p.movement = MV_DOWN)) then
  395.     RadioButton1.Checked := TRUE
  396.   else if (p.x = PAR) and ((p.movement = MV_UP) or (p.movement = MV_DOWN)) then
  397.     RadioButton2.Checked := TRUE
  398.   else if (p.y = -PAR) and ((p.movement = MV_LEFT) or (p.movement = MV_RIGHT)) then
  399.     RadioButton3.Checked := TRUE
  400.   else if (p.y = PAR) and ((p.movement = MV_LEFT) or (p.movement = MV_RIGHT)) then
  401.     RadioButton4.Checked := TRUE
  402.   else
  403.     RadioButton5.Checked := TRUE;
  404. end;
  405.  
  406. procedure TForm1.ListBox1Click(Sender: TObject);
  407. begin
  408.   ActualizeButtons;
  409. end;
  410.  
  411. procedure TForm1.Button2Click(Sender: TObject);
  412. begin
  413.   if ListBox1.ItemIndex >= 0 then
  414.     RemSource(ListBox1.ItemIndex);
  415. end;
  416.  
  417. procedure TForm1.ListBox1KeyDown(Sender: TObject; var Key: Word;
  418.   Shift: TShiftState);
  419. begin
  420.   ActualizeButtons;
  421. end;
  422.  
  423. procedure TForm1.Button3Click(Sender: TObject);
  424. var
  425.   p: PSource;
  426.   pos, rot, vel: BASS_3DVECTOR;
  427. begin
  428.   if ListBox1.ItemIndex < 0 then Exit;
  429.   p := GetSource(ListBox1.itemIndex);
  430.   if not p.playing then
  431.   begin
  432.     p.playing := TRUE;
  433.     pos.x := p.x;
  434.     pos.y := 0;
  435.     pos.z := -p.y;
  436.     vel := GetVel(p);
  437.     rot.x := 0;
  438.     rot.y := 0;
  439.     rot.z := 0;
  440.     if (p.sample <> 0) then
  441.     begin
  442.       if (p.channel = 0) then
  443.         p.channel := BASS_SamplePlay3D(p.sample, pos, rot, vel);
  444.     end
  445.     else
  446.       BASS_MusicPlay(p.channel);
  447.   end;
  448. end;
  449.  
  450. procedure TForm1.Button4Click(Sender: TObject);
  451. var
  452.   p: PSource;
  453. begin
  454.   if ListBox1.ItemIndex < 0 then Exit;
  455.   p := GetSource(ListBox1.ItemIndex);
  456.   if p = nil then Exit;
  457.   BASS_ChannelStop(p.channel);
  458.   if (p.sample <> 0) then p.channel := 0;
  459.   p.playing := FALSE;
  460. end;
  461.  
  462. procedure TForm1.RadioButton1Click(Sender: TObject);
  463. var
  464.   p: PSource;
  465. begin
  466.   if ListBox1.ItemIndex < 0 then Exit;
  467.   p := GetSource(ListBox1.ItemIndex);
  468.   if p = nil then Exit;
  469.   if (p.movement and MV_UP = 0) and
  470.      (p.movement and MV_DOWN = 0) then
  471.   begin
  472.     p.movement := MV_UP;
  473.     p.x := -PAR;
  474.     p.y := 0;
  475.   end
  476.   else
  477.     p.x := -PAR;
  478.   DrawSources;
  479. end;
  480.  
  481. procedure TForm1.RadioButton2Click(Sender: TObject);
  482. var
  483.   p: PSource;
  484. begin
  485.   if ListBox1.ItemIndex < 0 then Exit;
  486.   p := GetSource(ListBox1.ItemIndex);
  487.   if p = nil then Exit;
  488.   if (p.movement and MV_UP = 0) and
  489.      (p.movement and MV_DOWN = 0) then
  490.   begin
  491.     p.movement := MV_UP;
  492.     p.x := PAR;
  493.     p.y := 0;
  494.   end
  495.   else
  496.     p.x := PAR;
  497.   DrawSources;
  498. end;
  499.  
  500. procedure TForm1.RadioButton3Click(Sender: TObject);
  501. var
  502.   p: PSource;
  503. begin
  504.   if ListBox1.ItemIndex < 0 then Exit;
  505.   p := GetSource(ListBox1.ItemIndex);
  506.   if p = nil then Exit;
  507.   if (p.movement and MV_LEFT = 0) and
  508.      (p.movement and MV_RIGHT = 0) then
  509.   begin
  510.     p.movement := MV_RIGHT;
  511.     p.x := 0;
  512.     p.y := -PAR;
  513.   end
  514.   else
  515.     p.y := -PAR;
  516.   DrawSources;
  517. end;
  518.  
  519. procedure TForm1.RadioButton4Click(Sender: TObject);
  520. var
  521.   p: PSource;
  522. begin
  523.   if ListBox1.ItemIndex < 0 then Exit;
  524.   p := GetSource(ListBox1.ItemIndex);
  525.   if p = nil then Exit;
  526.   if (p.movement and MV_LEFT = 0) and
  527.      (p.movement and MV_RIGHT = 0) then
  528.   begin
  529.     p.movement := MV_RIGHT;
  530.     p.x := 0;
  531.     p.y := PAR;
  532.   end
  533.   else
  534.     p.y := PAR;
  535.   DrawSources;
  536. end;
  537.  
  538. procedure TForm1.RadioButton5Click(Sender: TObject);
  539. var
  540.   p: PSource;
  541. begin
  542.   if ListBox1.ItemIndex < 0 then Exit;
  543.   p := GetSource(ListBox1.ItemIndex);
  544.   if p = nil then Exit;
  545.   p.movement := 0;
  546.   ActualizeSources(TRUE);
  547. end;
  548.  
  549. function TForm1.GetVel(p: PSource): BASS_3DVECTOR;
  550. var
  551.   x, z: Float;
  552.   sp: Float;
  553. begin
  554.   x := 0;
  555.   z := 0;
  556.   if p.playing then
  557.   begin
  558.     sp := SPEED * 1000 / Timer1.Interval;
  559.     if (p.movement = MV_LEFT) then x := -sp
  560.     else if (p.movement = MV_RIGHT) then x := sp
  561.     else if (p.movement = MV_UP) then z := sp
  562.     else if (p.movement = MV_DOWN) then z := -sp;
  563.   end;
  564.   Result.x := x;
  565.   Result.y := 0;
  566.   Result.z := z;
  567. end;
  568.  
  569. procedure TForm1.ComboBox1Change(Sender: TObject);
  570. begin
  571.   case (ComboBox1.ItemIndex) of
  572.     0: BASS_EAXPreset(EAX_ENVIRONMENT_OFF);
  573.     1: BASS_EAXPreset(EAX_ENVIRONMENT_GENERIC);
  574.     2: BASS_EAXPreset(EAX_ENVIRONMENT_PADDEDCELL);
  575.     3: BASS_EAXPreset(EAX_ENVIRONMENT_ROOM);
  576.     4: BASS_EAXPreset(EAX_ENVIRONMENT_BATHROOM);
  577.     5: BASS_EAXPreset(EAX_ENVIRONMENT_LIVINGROOM);
  578.     6: BASS_EAXPreset(EAX_ENVIRONMENT_STONEROOM);
  579.     7: BASS_EAXPreset(EAX_ENVIRONMENT_AUDITORIUM);
  580.     8: BASS_EAXPreset(EAX_ENVIRONMENT_CONCERTHALL);
  581.     9: BASS_EAXPreset(EAX_ENVIRONMENT_CAVE);
  582.     10: BASS_EAXPreset(EAX_ENVIRONMENT_ARENA);
  583.     11: BASS_EAXPreset(EAX_ENVIRONMENT_HANGAR);
  584.     12: BASS_EAXPreset(EAX_ENVIRONMENT_CARPETEDHALLWAY);
  585.     13: BASS_EAXPreset(EAX_ENVIRONMENT_HALLWAY);
  586.     14: BASS_EAXPreset(EAX_ENVIRONMENT_STONECORRIDOR);
  587.     15: BASS_EAXPreset(EAX_ENVIRONMENT_ALLEY);
  588.     16: BASS_EAXPreset(EAX_ENVIRONMENT_FOREST);
  589.     17: BASS_EAXPreset(EAX_ENVIRONMENT_CITY);
  590.     18: BASS_EAXPreset(EAX_ENVIRONMENT_MOUNTAINS);
  591.     19: BASS_EAXPreset(EAX_ENVIRONMENT_QUARRY);
  592.     20: BASS_EAXPreset(EAX_ENVIRONMENT_PLAIN);
  593.     21: BASS_EAXPreset(EAX_ENVIRONMENT_PARKINGLOT);
  594.     22: BASS_EAXPreset(EAX_ENVIRONMENT_SEWERPIPE);
  595.     23: BASS_EAXPreset(EAX_ENVIRONMENT_UNDERWATER);
  596.     24: BASS_EAXPreset(EAX_ENVIRONMENT_DRUGGED);
  597.     25: BASS_EAXPreset(EAX_ENVIRONMENT_DIZZY);
  598.     26: BASS_EAXPreset(EAX_ENVIRONMENT_PSYCHOTIC);
  599.   end;
  600. end;
  601.  
  602. procedure TForm1.CheckBox1Click(Sender: TObject);
  603. begin
  604.   if CheckBox1.Checked then
  605.     BASS_SetA3DHFAbsorbtion(Power(2, ScrollBar3.Position / 2.0))
  606.   else
  607.     BASS_SetA3DHFAbsorbtion(0);
  608. end;
  609.  
  610. procedure TForm1.ScrollBar3Change(Sender: TObject);
  611. var
  612.   a: Float;
  613. begin
  614.   a := ScrollBar3.Position;
  615.   if CheckBox1.Checked then
  616.     BASS_SetA3DHFAbsorbtion(Power(2.0, a / 2.0));
  617. end;
  618.  
  619. procedure TForm1.ScrollBar1Change(Sender: TObject);
  620. var
  621.   a: Float;
  622. begin
  623.   a := ScrollBar1.Position;
  624.   BASS_Set3DFactors(-1, Power(2.0, a / 4.0), -1);
  625. end;
  626.  
  627. procedure TForm1.ScrollBar2Change(Sender: TObject);
  628. var
  629.   a: Float;
  630. begin
  631.   a := ScrollBar2.Position;
  632.   BASS_Set3DFactors(-1, -1, Power(2.0, a / 4.0));
  633. end;
  634.  
  635. end.
  636.  
  637.