(* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
                         -****************+.
               .-=++*+::*###############*-
           :=+##*+=-::*##**############=
        .=*#*=:    .+#*=+############+.
       =##+.      +#+-=############*-:
     :*#+.      =+-.=#############- =#*.
    -##-      -=..+#############*:.  ---.
   -##:     .: .+################= :+#*-:.
  .##-        :==========*#####= :*#*- -#*
  =##                   -####*:-*#*-   .##:
  +#+                  -###*--*#*-      *#=
  *#+                 +###==*#*:        *#=
  +#*                *##+=*#*-          ##-
  :##.             .*##*##*:           -##.
   +#*            -#####*:             *#=
    *#+          =####+:             .*#+
     +#*.       +###+.              :##=
      -##+.    *##+:              :+#*:
        =*#+..*#+:             .-*#*-
          :-:#+::.        .:-=*##+:
           -+..+*###****####*+-.
          :.      ..:::::..
        ____                   _
       / ___| _ __   __ _ _ __| | __
       \___ \| '_ \ / _` | '__| |/ /
        ___) | |_) | (_| | |  |   <
       |____/| .__/ \__,_|_|  |_|\_\
             |_|   Game Toolkit™

Copyright © 2024-present tinyBigGAMES™ LLC
         All Rights Reserved.

Website: https://tinybiggames.com
Email  : support@tinybiggames.com

See LICENSE for license information
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *)

unit UAudio01;

interface

uses
  System.SysUtils,
  System.Math,
  System.IOUtils,
  SGT.Deps,
  SGT.Deps.Ext,
  SGT.OGL,
  SGT.Core,
  SGT.Lua,
  SGT.LuaDebugger,
  UCommon;

procedure Demo();

implementation

// The 'Demo' procedure demonstrates playing sound effects and music from a zip file using keyboard inputs.
// It sets up a window, loads the audio resources, and manages playback of sounds and music.

procedure Demo();
var
  LZipFile: TZipFile;             // Represents the zip file from which audio resources will be loaded.
  LWindow: TWindow;               // Represents the window where the content will be displayed.
  LFont: TFont;                   // Represents the font used to render text.
  LPos: TPoint;                   // Represents the position on the window where the text will be drawn.
  LSound: array[0..7] of Integer; // Array to store sound effect handles.
  LChan: integer;                 // Channel handle for playing sounds.
  LSongNum: Integer;              // Current song number being played.
  LSongFilename: string;          // Filename of the current song being played.

  // Procedure to load and play the current song based on 'LSongNum'.
  procedure PlaySong;
  begin
    // Unload any currently playing music.
    Audio.UnloadMusic();

    // Format the filename for the song based on the current song number.
    LSongFilename := Format('res/music/song%.2d.ogg', [LSongNum]);

    // Play the music from the zip file at full volume (1.0) and set it to loop.
    Audio.PlayMusicFromZipFile(LZipFile, LSongFilename, 1.0, True);
  end;

begin
  // Initialize the zip file with the specified filename.
  LZipFile := TZipFile.Init(CZipFilename);

  // Initialize the window with the title 'SGT: Audio #01'.
  LWindow := TWindow.Init('SGT: Audio #01');

  // Load the default font with a size of 10, associated with the window.
  LFont := TFont.LoadDefault(LWindow, 10);

  // Initialize the audio system.
  Audio.Open();

  // Set the initial song number and channel handle.
  LSongNum := 1;
  LChan := -1;

  // Load sound effects from the zip file into the LSound array.
  LSound[0] := Audio.LoadSoundFromZipFile(LZipFile, 'res/sfx/digthis.ogg');
  LSound[1] := Audio.LoadSoundFromZipFile(LZipFile, 'res/sfx/samp0.ogg');
  LSound[2] := Audio.LoadSoundFromZipFile(LZipFile, 'res/sfx/samp1.ogg');
  LSound[3] := Audio.LoadSoundFromZipFile(LZipFile, 'res/sfx/samp2.ogg');
  LSound[4] := Audio.LoadSoundFromZipFile(LZipFile, 'res/sfx/samp3.ogg');
  LSound[5] := Audio.LoadSoundFromZipFile(LZipFile, 'res/sfx/samp4.ogg');
  LSound[6] := Audio.LoadSoundFromZipFile(LZipFile, 'res/sfx/samp5.ogg');
  LSound[7] := Audio.LoadSoundFromZipFile(LZipFile, 'res/sfx/explo_rock.ogg');

  // Reserve channels 0 and 1 for exclusive use, to prevent other sounds from being played on them.
  Audio.ReserveChannel(0, True);
  Audio.ReserveChannel(1, True);

  // Play the first song.
  PlaySong();

  // Main loop to keep the window running until the user closes it.
  while not LWindow.ShouldClose() do
  begin
    // Start processing a new frame.
    LWindow.StartFrame();

    // Check if the ESC key was pressed. If so, set the window to close.
    if LWindow.GetKey(KEY_ESCAPE, isWasPressed) then
      LWindow.SetShouldClose(True);

    // Check if number keys 1-8 are pressed and play corresponding sounds.
    if LWindow.GetKey(KEY_1, isWasPressed) then
      Audio.PlaySound(LSound[0], 0, 1.0, False); // Play sound on channel 0 without looping.

    if LWindow.GetKey(KEY_2, isWasPressed) then
      LChan := Audio.PlaySound(LSound[1], 1, 1.0, True); // Play sound on channel 1 with looping.

    if LWindow.GetKey(KEY_3, isWasPressed) then
      Audio.PlaySound(LSound[2], Audio.CHANNEL_DYNAMIC, 1.0, False); // Play sound on a dynamic channel without looping.

    if LWindow.GetKey(KEY_4, isWasPressed) then
      Audio.PlaySound(LSound[3], Audio.CHANNEL_DYNAMIC, 1.0, False); // Play sound on a dynamic channel without looping.

    if LWindow.GetKey(KEY_5, isWasPressed) then
      Audio.PlaySound(LSound[4], Audio.CHANNEL_DYNAMIC, 1.0, False); // Play sound on a dynamic channel without looping.

    if LWindow.GetKey(KEY_6, isWasPressed) then
      Audio.PlaySound(LSound[5], Audio.CHANNEL_DYNAMIC, 1.0, False); // Play sound on a dynamic channel without looping.

    if LWindow.GetKey(KEY_7, isWasPressed) then
      Audio.PlaySound(LSound[6], Audio.CHANNEL_DYNAMIC, 1.0, False); // Play sound on a dynamic channel without looping.

    if LWindow.GetKey(KEY_8, isWasPressed) then
      Audio.PlaySound(LSound[7], Audio.CHANNEL_DYNAMIC, 1.0, False); // Play sound on a dynamic channel without looping.

    // Stop the sound playing on the reserved channel 1 if the '9' key is pressed.
    if LWindow.GetKey(KEY_9, isWasPressed) then
      Audio.StopChannel(LChan);

    // Check if the UP or DOWN arrow keys are pressed to change the current song.
    if LWindow.GetKey(KEY_UP, isWasPressed) then
    begin
      Inc(LSongNum); // Increment the song number.
      LSongNum := EnsureRange(LSongNum, 1, 14); // Ensure the song number stays within the valid range.
      PlaySong(); // Play the new song.
    end
    else if LWindow.GetKey(KEY_DOWN, isWasPressed) then
    begin
      Dec(LSongNum); // Decrement the song number.
      LSongNum := EnsureRange(LSongNum, 1, 14); // Ensure the song number stays within the valid range.
      PlaySong(); // Play the new song.
    end;

    // Start drawing on the window.
    LWindow.StartDrawing();

    // Clear the window with a dark slate brown background color.
    LWindow.Clear(DARKSLATEBROWN);

    // Set the initial position for text rendering.
    LPos := Math.Point(3, 3);

    // Draw the current frame rate in the top-left corner of the window in white color.
    LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, WHITE, haLeft, 'fps %d', [FrameLimitTimer.FrameRate()]);

    // Draw instructions for quitting, playing sounds, stopping sound, and changing songs.
    LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, GREEN, haLeft, Utils.HudTextItem('Quit', 'ESC'), [FrameLimitTimer.FrameRate()]);
    LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, GREEN, haLeft, Utils.HudTextItem('1-8', 'Play sound'), [FrameLimitTimer.FrameRate()]);
    LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, GREEN, haLeft, Utils.HudTextItem('9', 'Stop sound on channel #1'), [FrameLimitTimer.FrameRate()]);
    LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, GREEN, haLeft, Utils.HudTextItem('UP/DOWN', 'Next/Prev song'), [FrameLimitTimer.FrameRate()]);
    LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, YELLOW, haLeft, Utils.HudTextItem('Song', '%s'), [TPath.GetFileName(LSongFilename)]);

    // Finish drawing on the window.
    LWindow.EndDrawing();

    // End processing the frame.
    LWindow.EndFrame();
  end;

  // Close the audio system after the loop ends.
  Audio.Close();

  // Free the font resources after the loop ends.
  LFont.Free();

  // Free the window resources after the loop ends.
  LWindow.Free();

  // Free the zip file resources after the loop ends.
  LZipFile.Free();
end;


end.
