<commit_before>unit KM_Music;
{$I KaM_Remake.inc}
interface

//We have two choices for music libraries:
//BASS: Free for non-commercial projects. Requires bass.dll. Website: http://www.un4seen.com/
//ZLibPlay: GNU GPL license. Requires libzplay.dll. Website: http://libzplay.sourceforge.net/

//Comparision:  - BASS's DLL is much smaller (102kb vs 2.13mb(!)) and BASS seems faster at loading tracks.
//              - ZLibPlay supports more formats, (FLAC, AC-3, AAC, PCM) but we don't care
//              - ZLibPlay is GPL but BASS is not, and BASS can only be used for free in non-commercial products

{.DEFINE USEBASS}
{$IFDEF MSWindows}
  {$DEFINE USELIBZPLAY}
{$ENDIF}

uses
  Classes, SysUtils, KromUtils, Math, Types,
  KM_Defaults
  {$IFDEF USEBASS}     , Bass {$ENDIF}
  {$IFDEF USELIBZPLAY} , libZPlay {$ENDIF}
  ;

type
  TFadeState = (fsNone, fsFadeOut, fsFadeIn, fsFaded);

  TKMMusicLib = class
  private
    fMusicCount: Integer;
    fMusicIndex: Integer; //Points to the index in TrackOrder of the current track
    fMusicTracks: TStringDynArray;
    fTrackOrder: TIntegerDynArray; //Each index points to an index of MusicTracks
    //MIDICount,MIDIIndex:integer;
    //MIDITracks:array[1..256]of string;
    IsMusicInitialized: Boolean;
    MusicGain: Single;
    {$IFDEF USEBASS} fBassStream, fBassOtherStream: Cardinal; {$ENDIF}
    {$IFDEF USELIBZPLAY} ZPlayer, ZPlayerOther: ZPlay; {$ENDIF} //I dislike that it's not TZPlay... Guess they don't know Delphi conventions.
    fFadeState: TFadeState;
    fFadeStarted: Cardinal;
    fToPlayAfterFade: UnicodeString;
    fFadedToPlayOther: Boolean;
    fOtherVolume: Single;
    function PlayMusicFile(FileName: UnicodeString): Boolean;
    function PlayOtherFile(FileName: UnicodeString): Boolean;
    procedure ScanMusicTracks(aPath: UnicodeString);
    procedure ShuffleSongs; //should not be seen outside of this class
    procedure UnshuffleSongs;
  public
    constructor Create(aVolume: Single);
    destructor Destroy; override;
    procedure UpdateMusicVolume(Value: Single);
    procedure PlayMenuTrack;
    procedure PlayNextTrack;
    procedure PlayPreviousTrack;
    function IsMusicEnded: Boolean;
    function IsOtherEnded: Boolean;
    procedure StopMusic;
    procedure ToggleMusic(aEnableMusic: Boolean);
    procedure ToggleShuffle(aEnableShuffle: Boolean);
    procedure FadeMusic;
    procedure UnfadeMusic(aHandleCrackling: Boolean);
    procedure PauseMusicToPlayFile(aFileName: UnicodeString; aVolume: Single);
    procedure StopPlayingOtherFile;
    function GetTrackTitle: UnicodeString;
    procedure UpdateStateIdle; //Used for fading
  end;


implementation
uses
  KM_Log, KM_CommonUtils;


const
  FADE_TIME = 2000; //Time that a fade takes to occur in ms


{ TKMMusicLib }
constructor TKMMusicLib.Create(aVolume: Single);
var
  I: Integer;
begin
  inherited Create;
  IsMusicInitialized := True;
  ScanMusicTracks(ExeDir + 'Music'+PathDelim);


  {$IFDEF USELIBZPLAY}
  ZPlayer := ZPlay.Create; //Note: They should have used TZPlay not ZPlay for a class
  ZPlayerOther := ZPlay.Create;
  {$ENDIF}

  {$IFDEF USEBASS}
  // Setup output - default device, 44100hz, stereo, 16 bits
  if not BASS_Init(-1, 44100, 0, 0, nil) then
  begin
    gLog.AddTime('Failed to initialize the music playback device');
    IsMusicInitialized := False;
  end;
  {$ENDIF}

  UpdateMusicVolume(aVolume);<commit_msg>Create music dir on game start, to prevent crash<commit_after>unit KM_Music;
{$I KaM_Remake.inc}
interface

//We have two choices for music libraries:
//BASS: Free for non-commercial projects. Requires bass.dll. Website: http://www.un4seen.com/
//ZLibPlay: GNU GPL license. Requires libzplay.dll. Website: http://libzplay.sourceforge.net/

//Comparision:  - BASS's DLL is much smaller (102kb vs 2.13mb(!)) and BASS seems faster at loading tracks.
//              - ZLibPlay supports more formats, (FLAC, AC-3, AAC, PCM) but we don't care
//              - ZLibPlay is GPL but BASS is not, and BASS can only be used for free in non-commercial products

{.DEFINE USEBASS}
{$IFDEF MSWindows}
  {$DEFINE USELIBZPLAY}
{$ENDIF}

uses
  Classes, SysUtils, KromUtils, Math, Types,
  KM_Defaults
  {$IFDEF USEBASS}     , Bass {$ENDIF}
  {$IFDEF USELIBZPLAY} , libZPlay {$ENDIF}
  ;

type
  TFadeState = (fsNone, fsFadeOut, fsFadeIn, fsFaded);

  TKMMusicLib = class
  private
    fMusicCount: Integer;
    fMusicIndex: Integer; //Points to the index in TrackOrder of the current track
    fMusicTracks: TStringDynArray;
    fTrackOrder: TIntegerDynArray; //Each index points to an index of MusicTracks
    //MIDICount,MIDIIndex:integer;
    //MIDITracks:array[1..256]of string;
    IsMusicInitialized: Boolean;
    MusicGain: Single;
    {$IFDEF USEBASS} fBassStream, fBassOtherStream: Cardinal; {$ENDIF}
    {$IFDEF USELIBZPLAY} ZPlayer, ZPlayerOther: ZPlay; {$ENDIF} //I dislike that it's not TZPlay... Guess they don't know Delphi conventions.
    fFadeState: TFadeState;
    fFadeStarted: Cardinal;
    fToPlayAfterFade: UnicodeString;
    fFadedToPlayOther: Boolean;
    fOtherVolume: Single;
    function PlayMusicFile(FileName: UnicodeString): Boolean;
    function PlayOtherFile(FileName: UnicodeString): Boolean;
    procedure ScanMusicTracks(aPath: UnicodeString);
    procedure ShuffleSongs; //should not be seen outside of this class
    procedure UnshuffleSongs;
  public
    constructor Create(aVolume: Single);
    destructor Destroy; override;
    procedure UpdateMusicVolume(Value: Single);
    procedure PlayMenuTrack;
    procedure PlayNextTrack;
    procedure PlayPreviousTrack;
    function IsMusicEnded: Boolean;
    function IsOtherEnded: Boolean;
    procedure StopMusic;
    procedure ToggleMusic(aEnableMusic: Boolean);
    procedure ToggleShuffle(aEnableShuffle: Boolean);
    procedure FadeMusic;
    procedure UnfadeMusic(aHandleCrackling: Boolean);
    procedure PauseMusicToPlayFile(aFileName: UnicodeString; aVolume: Single);
    procedure StopPlayingOtherFile;
    function GetTrackTitle: UnicodeString;
    procedure UpdateStateIdle; //Used for fading
  end;


implementation
uses
  KM_Log, KM_CommonUtils;


const
  FADE_TIME = 2000; //Time that a fade takes to occur in ms


{ TKMMusicLib }
constructor TKMMusicLib.Create(aVolume: Single);
var
  I: Integer;
begin
  inherited Create;
  IsMusicInitialized := True;

  if not DirectoryExists(ExeDir + 'Music') then
    ForceDirectories(ExeDir + 'Music');

  ScanMusicTracks(ExeDir + 'Music' + PathDelim);


  {$IFDEF USELIBZPLAY}
  ZPlayer := ZPlay.Create; //Note: They should have used TZPlay not ZPlay for a class
  ZPlayerOther := ZPlay.Create;
  {$ENDIF}

  {$IFDEF USEBASS}
  // Setup output - default device, 44100hz, stereo, 16 bits
  if not BASS_Init(-1, 44100, 0, 0, nil) then
  begin
    gLog.AddTime('Failed to initialize the music playback device');
    IsMusicInitialized := False;
  end;
  {$ENDIF}

  UpdateMusicVolume(aVolume);
{'fraction_non_alphanumeric': 0.09089593284122159, 'fraction_numerical': 0.008973802286872196, 'mean_word_length': 4.021802325581396, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '758675', 'n_tokens_mistral': 2318, 'n_tokens_neox': 2170, 'n_words': 667}