aboutsummaryrefslogtreecommitdiffstats
path: root/Game/Code/Classes/UAudioPlayback_Bass.pas
diff options
context:
space:
mode:
Diffstat (limited to 'Game/Code/Classes/UAudioPlayback_Bass.pas')
-rw-r--r--Game/Code/Classes/UAudioPlayback_Bass.pas460
1 files changed, 460 insertions, 0 deletions
diff --git a/Game/Code/Classes/UAudioPlayback_Bass.pas b/Game/Code/Classes/UAudioPlayback_Bass.pas
new file mode 100644
index 00000000..ee6b1ef9
--- /dev/null
+++ b/Game/Code/Classes/UAudioPlayback_Bass.pas
@@ -0,0 +1,460 @@
+unit UAudioPlayback_Bass;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+
+uses Classes,
+ {$IFDEF win32}
+ windows,
+ {$ENDIF}
+ SysUtils,
+ bass,
+ ULog,
+ UMusic;
+
+implementation
+
+uses
+ {$IFDEF LAZARUS}
+ lclintf,
+ {$ENDIF}
+ URecord,
+ UIni,
+ UMain,
+ UCommon,
+ UThemes;
+
+type
+ TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking,
+ mpPaused, mpOpen);
+
+const
+ ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open');
+
+type
+ TBassOutputStream = class(TAudioOutputStream)
+ Handle: HSTREAM;
+
+ constructor Create(); overload;
+ constructor Create(stream: HSTREAM); overload;
+ end;
+
+type
+ TAudioPlayback_Bass = class( TInterfacedObject, IAudioPlayback)
+ private
+ MusicStream: HSTREAM;
+
+ StartSoundStream: HSTREAM;
+ BackSoundStream: HSTREAM;
+ SwooshSoundStream: HSTREAM;
+ ChangeSoundStream: HSTREAM;
+ OptionSoundStream: HSTREAM;
+ ClickSoundStream: HSTREAM;
+ DrumSoundStream: HSTREAM;
+ HihatSoundStream: HSTREAM;
+ ClapSoundStream: HSTREAM;
+ ShuffleSoundStream: HSTREAM;
+
+ //Custom Sounds
+ CustomSounds: array of TCustomSoundEntry;
+ Loaded: boolean;
+ Loop: boolean;
+
+ public
+ function GetName: String;
+
+ {IAudioOutput interface}
+
+ procedure InitializePlayback;
+ procedure SetVolume(Volume: integer);
+ procedure SetMusicVolume(Volume: integer);
+ procedure SetLoop(Enabled: boolean);
+
+ function Open(Name: string): boolean; // true if succeed
+
+ procedure Rewind;
+ procedure Play;
+ procedure Pause; //Pause Mod
+ procedure Stop;
+ procedure Close;
+ function Finished: boolean;
+ function Length: real;
+ function GetPosition: real;
+ procedure SetPosition(Time: real);
+
+ procedure PlayStart;
+ procedure PlayBack;
+ procedure PlaySwoosh;
+ procedure PlayChange;
+ procedure PlayOption;
+ procedure PlayClick;
+ procedure PlayDrum;
+ procedure PlayHihat;
+ procedure PlayClap;
+ procedure PlayShuffle;
+ procedure StopShuffle;
+
+ function LoadSoundFromFile(var stream: HSTREAM; Name: string): boolean;
+
+ //Equalizer
+ function GetFFTData: TFFTData;
+
+ // Interface for Visualizer
+ function GetPCMData(var data: TPCMData): Cardinal;
+
+ //Custom Sounds
+ function LoadCustomSound(const Filename: String): Cardinal;
+ procedure PlayCustomSound(const Index: Cardinal );
+ end;
+
+var
+ singleton_AudioPlaybackBass : IAudioPlayback;
+
+
+constructor TBassOutputStream.Create();
+begin
+ inherited;
+end;
+
+constructor TBassOutputStream.Create(stream: HSTREAM);
+begin
+ Create();
+ Handle := stream;
+end;
+
+
+function TAudioPlayback_Bass.GetName: String;
+begin
+ result := 'BASS_Playback';
+end;
+
+procedure TAudioPlayback_Bass.InitializePlayback;
+var
+ Pet: integer;
+ S: integer;
+begin
+// Log.BenchmarkStart(4);
+// Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize');
+
+ Loaded := false;
+ Loop := false;
+
+ if not BASS_Init(1, 44100, 0, 0, nil) then
+ begin
+ Log.LogError('Could not initialize BASS', 'Error');
+ Exit;
+ end;
+
+// Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4);
+
+ // config playing buffer
+// BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10);
+// BASS_SetConfig(BASS_CONFIG_BUFFER, 100);
+
+// Log.LogStatus('Loading Sounds', 'Music Initialize');
+
+// Log.BenchmarkStart(4);
+ LoadSoundFromFile(StartSoundStream, SoundPath + 'Common Start.mp3');
+ LoadSoundFromFile(BackSoundStream, SoundPath + 'Common Back.mp3');
+ LoadSoundFromFile(SwooshSoundStream, SoundPath + 'menu swoosh.mp3');
+ LoadSoundFromFile(ChangeSoundStream, SoundPath + 'select music change music 50.mp3');
+ LoadSoundFromFile(OptionSoundStream, SoundPath + 'option change col.mp3');
+ LoadSoundFromFile(ClickSoundStream, SoundPath + 'rimshot022b.mp3');
+
+// LoadSoundFromFile(DrumSoundStream, SoundPath + 'bassdrumhard076b.mp3');
+// LoadSoundFromFile(HihatSoundStream, SoundPath + 'hihatclosed068b.mp3');
+// LoadSoundFromFile(ClapSoundStream, SoundPath + 'claps050b.mp3');
+
+// LoadSoundFromFile(ShuffleSoundStream, SoundPath + 'Shuffle.mp3');
+
+// Log.BenchmarkEnd(4);
+// Log.LogBenchmark('--> Loading Sounds', 4);
+end;
+
+procedure TAudioPlayback_Bass.SetVolume(Volume: integer);
+begin
+ //Old Sets Wave Volume
+ //BASS_SetVolume(Volume);
+ //New: Sets Volume only for this Application
+
+ BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume);
+ BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume);
+ BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume);
+end;
+
+procedure TAudioPlayback_Bass.SetMusicVolume(Volume: Integer);
+begin
+ //Max Volume Prevention
+ if Volume > 100 then
+ Volume := 100;
+
+ if Volume < 0 then
+ Volume := 0;
+
+ //Set Volume
+ BASS_ChannelSetAttributes (MusicStream, -1, Volume, -101);
+end;
+
+procedure TAudioPlayback_Bass.SetLoop(Enabled: boolean);
+begin
+ Loop := Enabled;
+end;
+
+function TAudioPlayback_Bass.Open(Name: string): boolean;
+begin
+ Loaded := false;
+ if FileExists(Name) then
+ begin
+ MusicStream := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0);
+
+ Loaded := true;
+ //Set Max Volume
+ SetMusicVolume (100);
+ end;
+
+ Result := Loaded;
+end;
+
+procedure TAudioPlayback_Bass.Rewind;
+begin
+ if Loaded then begin
+ end;
+end;
+
+procedure TAudioPlayback_Bass.SetPosition(Time: real);
+var
+ bytes: integer;
+begin
+ bytes := BASS_ChannelSeconds2Bytes(MusicStream, Time);
+ BASS_ChannelSetPosition(MusicStream, bytes);
+end;
+
+procedure TAudioPlayback_Bass.Play;
+begin
+ if Loaded then
+ begin
+ if Loop then
+ BASS_ChannelPlay(MusicStream, True); // start from beginning... actually bass itself does not loop, nor does this TAudio_bass Class
+
+ BASS_ChannelPlay(MusicStream, False); // for setting position before playing
+ end;
+end;
+
+procedure TAudioPlayback_Bass.Pause; //Pause Mod
+begin
+ if Loaded then begin
+ BASS_ChannelPause(MusicStream); // Pauses Song
+ end;
+end;
+
+procedure TAudioPlayback_Bass.Stop;
+begin
+ Bass_ChannelStop(MusicStream);
+end;
+
+procedure TAudioPlayback_Bass.Close;
+begin
+ Bass_StreamFree(MusicStream);
+end;
+
+function TAudioPlayback_Bass.Length: real;
+var
+ bytes: integer;
+begin
+ Result := 60;
+
+ bytes := BASS_ChannelGetLength(MusicStream);
+ Result := BASS_ChannelBytes2Seconds(MusicStream, bytes);
+end;
+
+function TAudioPlayback_Bass.getPosition: real;
+var
+ bytes: integer;
+begin
+ Result := 0;
+
+ bytes := BASS_ChannelGetPosition(MusicStream);
+ Result := BASS_ChannelBytes2Seconds(MusicStream, bytes);
+end;
+
+function TAudioPlayback_Bass.Finished: boolean;
+begin
+ Result := false;
+
+ if BASS_ChannelIsActive(MusicStream) = BASS_ACTIVE_STOPPED then
+ begin
+ Result := true;
+ end;
+end;
+
+procedure TAudioPlayback_Bass.PlayStart;
+begin
+ BASS_ChannelPlay(StartSoundStream, True);
+end;
+
+procedure TAudioPlayback_Bass.PlayBack;
+begin
+ BASS_ChannelPlay(BackSoundStream, True);// then
+end;
+
+procedure TAudioPlayback_Bass.PlaySwoosh;
+begin
+ BASS_ChannelPlay(SwooshSoundStream, True);
+end;
+
+procedure TAudioPlayback_Bass.PlayChange;
+begin
+ BASS_ChannelPlay(ChangeSoundStream, True);
+end;
+
+procedure TAudioPlayback_Bass.PlayOption;
+begin
+ BASS_ChannelPlay(OptionSoundStream, True);
+end;
+
+procedure TAudioPlayback_Bass.PlayClick;
+begin
+ BASS_ChannelPlay(ClickSoundStream, True);
+end;
+
+procedure TAudioPlayback_Bass.PlayDrum;
+begin
+ BASS_ChannelPlay(DrumSoundStream, True);
+end;
+
+procedure TAudioPlayback_Bass.PlayHihat;
+begin
+ BASS_ChannelPlay(HihatSoundStream, True);
+end;
+
+procedure TAudioPlayback_Bass.PlayClap;
+begin
+ BASS_ChannelPlay(ClapSoundStream, True);
+end;
+
+procedure TAudioPlayback_Bass.PlayShuffle;
+begin
+ BASS_ChannelPlay(ShuffleSoundStream, True);
+end;
+
+procedure TAudioPlayback_Bass.StopShuffle;
+begin
+ BASS_ChannelStop(ShuffleSoundStream);
+end;
+
+function TAudioPlayback_Bass.LoadSoundFromFile(var stream: HSTREAM; Name: string): boolean;
+var
+ L: Integer;
+begin
+ if FileExists(Name) then
+ begin
+ Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile');
+ try
+ stream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0);
+
+ //Add CustomSound
+ L := High(CustomSounds) + 1;
+ SetLength (CustomSounds, L + 1);
+ CustomSounds[L].Filename := Name;
+ CustomSounds[L].Stream := TBassOutputStream.Create(stream);
+ except
+ Log.LogError('Failed to open using BASS', 'LoadSoundFromFile');
+ end;
+ end
+ else
+ begin
+ Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile');
+ exit;
+ end;
+end;
+
+//Equalizer
+function TAudioPlayback_Bass.GetFFTData: TFFTData;
+var
+ Data: TFFTData;
+begin
+ //Get Channel Data Mono and 256 Values
+ BASS_ChannelGetData(MusicStream, @Result, BASS_DATA_FFT512);
+end;
+
+{*
+ * Copies interleaved PCM 16bit uint (maybe fake) stereo samples into data.
+ * Returns the number of frames (= stereo/mono sample)
+ *}
+function TAudioPlayback_Bass.GetPCMData(var data: TPCMData): Cardinal;
+var
+ info: BASS_CHANNELINFO;
+ nBytes: DWORD;
+begin
+ //Get Channel Data Mono and 256 Values
+ BASS_ChannelGetInfo(MusicStream, info);
+ ZeroMemory(@data, sizeof(TPCMData));
+
+ if (info.chans = 1) then
+ begin
+ // mono file -> add stereo channel
+ {
+ nBytes := BASS_ChannelGetData(Bass, @data[0], samples*sizeof(Smallint));
+ // interleave data
+ //CopyMemory(@data[1], @data[0], samples*sizeof(Smallint));
+ }
+ result := 0;
+ end
+ else
+ begin
+ // stereo file
+ nBytes := BASS_ChannelGetData(MusicStream, @data, sizeof(TPCMData));
+ end;
+ if(nBytes <= 0) then
+ result := 0
+ else
+ result := nBytes div sizeof(TPCMStereoSample);
+end;
+
+function TAudioPlayback_Bass.LoadCustomSound(const Filename: String): Cardinal;
+var
+ S: hStream;
+ I: Integer;
+ F: String;
+begin
+ //Search for Sound in already loaded Sounds
+ F := UpperCase(SoundPath + FileName);
+ For I := 0 to High(CustomSounds) do
+ begin
+ if (UpperCase(CustomSounds[I].Filename) = F) then
+ begin
+ Result := I;
+ Exit;
+ end;
+ end;
+
+ if LoadSoundFromFile(S, SoundPath + Filename) then
+ Result := High(CustomSounds)
+ else
+ Result := 0;
+end;
+
+procedure TAudioPlayback_Bass.PlayCustomSound(const Index: Cardinal );
+begin
+ if Index <= High(CustomSounds) then
+ with CustomSounds[Index].Stream as TBassOutputStream do
+ begin
+ BASS_ChannelPlay(Handle, True);
+ end;
+end;
+
+
+initialization
+ singleton_AudioPlaybackBass := TAudioPlayback_Bass.create();
+ AudioManager.add( singleton_AudioPlaybackBass );
+
+finalization
+ AudioManager.Remove( singleton_AudioPlaybackBass );
+
+end.