diff options
Diffstat (limited to 'Game/Code/Classes/UAudioPlayback_Bass.pas')
-rw-r--r-- | Game/Code/Classes/UAudioPlayback_Bass.pas | 430 |
1 files changed, 430 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..266a5ec3 --- /dev/null +++ b/Game/Code/Classes/UAudioPlayback_Bass.pas @@ -0,0 +1,430 @@ +unit UAudioPlayback_Bass; + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + + +uses + Classes, + SysUtils, + UMusic; + +implementation + +uses + UIni, + UMain, + ULog, + UAudioCore_Bass, + bass; + +type + TBassPlaybackStream = class(TAudioPlaybackStream) + private + Handle: HSTREAM; + Loop: boolean; + public + constructor Create(); overload; + constructor Create(stream: HSTREAM); overload; + + procedure Reset(); + + procedure Play(); override; + procedure Pause(); override; + procedure Stop(); override; + procedure Close(); override; + function GetLoop(): boolean; override; + procedure SetLoop(Enabled: boolean); override; + function GetLength(): real; override; + function GetStatus(): TStreamStatus; override; + function GetVolume(): integer; override; + procedure SetVolume(volume: integer); override; + + function GetPosition: real; + procedure SetPosition(Time: real); + + function IsLoaded(): boolean; + end; + +type + TAudioPlayback_Bass = class( TInterfacedObject, IAudioPlayback) + private + MusicStream: TBassPlaybackStream; + + function Load(Filename: string): TBassPlaybackStream; + public + function GetName: String; + + {IAudioOutput interface} + + function InitializePlayback(): boolean; + procedure SetVolume(Volume: integer); + procedure SetMusicVolume(Volume: integer); + procedure SetLoop(Enabled: boolean); + + function Open(Filename: 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); + + //Equalizer + procedure GetFFTData(var data: TFFTData); + + // Interface for Visualizer + function GetPCMData(var data: TPCMData): Cardinal; + + // Sounds + function OpenSound(const Filename: String): TAudioPlaybackStream; + procedure PlaySound(stream: TAudioPlaybackStream);
+ procedure StopSound(stream: TAudioPlaybackStream); + end; + +var + singleton_AudioPlaybackBass : IAudioPlayback; + + +constructor TBassPlaybackStream.Create(); +begin + inherited; + Reset(); +end; + +constructor TBassPlaybackStream.Create(stream: HSTREAM); +begin + Create(); + Handle := stream; +end; + +procedure TBassPlaybackStream.Reset(); +begin + Loop := false; + if (Handle <> 0) then + Bass_StreamFree(Handle); + Handle := 0; +end; + +procedure TBassPlaybackStream.Play(); +begin + BASS_ChannelPlay(Handle, Loop); +end; + +procedure TBassPlaybackStream.Pause(); +begin + BASS_ChannelPause(Handle); +end; + +procedure TBassPlaybackStream.Stop(); +begin + BASS_ChannelStop(Handle); +end; + +procedure TBassPlaybackStream.Close(); +begin + Reset(); +end; + +function TBassPlaybackStream.GetVolume(): integer; +begin + Result := 0; + BASS_ChannelSetAttributes(Handle, PInteger(nil)^, Result, PInteger(nil)^); +end; + +procedure TBassPlaybackStream.SetVolume(volume: integer); +begin + // clamp volume + if volume < 0 then + volume := 0; + if volume > 100 then + volume := 100; + // set volume + BASS_ChannelSetAttributes(Handle, -1, volume, -101); +end; + +function TBassPlaybackStream.GetPosition: real; +var + bytes: integer; +begin + bytes := BASS_ChannelGetPosition(Handle); + Result := BASS_ChannelBytes2Seconds(Handle, bytes); +end; + +procedure TBassPlaybackStream.SetPosition(Time: real); +var + bytes: integer; +begin + bytes := BASS_ChannelSeconds2Bytes(Handle, Time); + BASS_ChannelSetPosition(Handle, bytes); +end; + +function TBassPlaybackStream.GetLoop(): boolean; +begin + result := Loop; +end; + +procedure TBassPlaybackStream.SetLoop(Enabled: boolean); +begin + Loop := Enabled; +end; + +function TBassPlaybackStream.GetLength(): real; +var + bytes: integer; +begin + bytes := BASS_ChannelGetLength(Handle); + Result := BASS_ChannelBytes2Seconds(Handle, bytes); +end; + +function TBassPlaybackStream.GetStatus(): TStreamStatus; +var + state: DWORD; +begin + state := BASS_ChannelIsActive(Handle); + case state of + BASS_ACTIVE_PLAYING: + result := ssPlaying; + BASS_ACTIVE_PAUSED: + result := ssPaused; + BASS_ACTIVE_STALLED: + result := ssBlocked; + BASS_ACTIVE_STOPPED: + result := ssStopped; + else + result := ssUnknown; + end; +end; + +function TBassPlaybackStream.IsLoaded(): boolean; +begin + Result := (Handle <> 0); +end; + + +function TAudioPlayback_Bass.GetName: String; +begin + result := 'BASS_Playback'; +end; + +function TAudioPlayback_Bass.InitializePlayback(): boolean; +var + Pet: integer; + S: integer; +begin + result := false; + + //Log.BenchmarkStart(4); + //Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize'); + + 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); + + result := true; +end; + +function TAudioPlayback_Bass.Load(Filename: string): TBassPlaybackStream; +var + L: Integer; + stream: HSTREAM; +begin + Result := nil; + + //Log.LogStatus('Loading Sound: "' + Filename + '"', 'LoadSoundFromFile'); + stream := BASS_StreamCreateFile(False, pchar(Filename), 0, 0, 0); + if (stream = 0) then + begin + Log.LogError('Failed to open "' + Filename + '", ' + + TAudioCore_Bass.ErrorGetString(BASS_ErrorGetCode()), 'TAudioPlayback_Bass.Load'); + Exit; + end; + + Result := TBassPlaybackStream.Create(stream); +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 + if assigned(MusicStream) then + MusicStream.SetVolume(Volume); +end; + +procedure TAudioPlayback_Bass.SetLoop(Enabled: boolean); +begin + if assigned(MusicStream) then + MusicStream.Loop := Enabled; +end; + +function TAudioPlayback_Bass.Open(Filename: string): boolean; +var + stream: HSTREAM; +begin + Result := false; + + // free old MusicStream + if assigned(MusicStream) then + MusicStream.Free; + + MusicStream := Load(Filename); + if not assigned(MusicStream) then + Exit; + + //Set Max Volume + SetMusicVolume(100); + + Result := true; +end; + +procedure TAudioPlayback_Bass.Rewind; +begin + SetPosition(0); +end; + +procedure TAudioPlayback_Bass.Play; +begin + if assigned(MusicStream) then + MusicStream.Play(); +end; + +procedure TAudioPlayback_Bass.Pause; +begin + if assigned(MusicStream) then + MusicStream.Pause(); +end; + +procedure TAudioPlayback_Bass.Stop; +begin + if assigned(MusicStream) then + MusicStream.Stop(); +end; + +procedure TAudioPlayback_Bass.Close; +begin + if assigned(MusicStream) then + MusicStream.Close(); +end; + +function TAudioPlayback_Bass.Length: real; +var + bytes: integer; +begin + if assigned(MusicStream) then + Result := MusicStream.GetLength() + else + Result := -1; +end; + +function TAudioPlayback_Bass.GetPosition: real; +begin + if assigned(MusicStream) then + Result := MusicStream.GetPosition() + else + Result := -1; +end; + +procedure TAudioPlayback_Bass.SetPosition(Time: real); +begin + if assigned(MusicStream) then + MusicStream.SetPosition(Time); +end; + +function TAudioPlayback_Bass.Finished: boolean; +begin + if assigned(MusicStream) then + Result := (MusicStream.GetStatus() = ssStopped) + else + Result := true; +end; + +//Equalizer +procedure TAudioPlayback_Bass.GetFFTData(var data: TFFTData); +begin + //Get Channel Data Mono and 256 Values + BASS_ChannelGetData(MusicStream.Handle, @data, 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.Handle, info); + FillChar(data, sizeof(TPCMData), 0); + + if (info.chans = 1) then + begin + // mono file -> add stereo channel + nBytes := 0;//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.Handle, @data, sizeof(TPCMData)); + end; + if(nBytes <= 0) then + result := 0 + else + result := nBytes div sizeof(TPCMStereoSample); +end; + +function TAudioPlayback_Bass.OpenSound(const Filename: string): TAudioPlaybackStream; +begin + result := Load(Filename); +end; + +procedure TAudioPlayback_Bass.PlaySound(stream: TAudioPlaybackStream); +begin + if assigned(stream) then + stream.Play(); +end; + +procedure TAudioPlayback_Bass.StopSound(stream: TAudioPlaybackStream); +begin + if assigned(stream) then + stream.Stop(); +end; + + +initialization + singleton_AudioPlaybackBass := TAudioPlayback_Bass.create(); + AudioManager.add( singleton_AudioPlaybackBass ); + +finalization + AudioManager.Remove( singleton_AudioPlaybackBass ); + +end. |