aboutsummaryrefslogtreecommitdiffstats
path: root/Game/Code/Classes/UAudioPlayback_Bass.pas
diff options
context:
space:
mode:
authortobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c>2008-05-09 19:19:28 +0000
committertobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c>2008-05-09 19:19:28 +0000
commitb5a738fa52c8b0f2212deb5febd2d7f0b8f6544f (patch)
tree3c2812cffdd035b385d5b0f0f8f5ea0702973739 /Game/Code/Classes/UAudioPlayback_Bass.pas
parent37744cee627605db0675efd3a6e0c42bd51c48d6 (diff)
downloadusdx-b5a738fa52c8b0f2212deb5febd2d7f0b8f6544f.tar.gz
usdx-b5a738fa52c8b0f2212deb5febd2d7f0b8f6544f.tar.xz
usdx-b5a738fa52c8b0f2212deb5febd2d7f0b8f6544f.zip
- input-source selection works now (with bass or portaudio with portmixer)
- audio-effects (DSP) interface for audio-playback plus a simple voice removal example (does not sound that good) - FFMpeg support for BASS - audio-clock for FFMpeg for GetPosition and synchronisation - more compatible seeking in FFMpeg - clean termination of the audio interfaces/streams (especially ffmpeg) - Audio output device enumeration (selection will be added later to the sounds option screen) - display of threshold and volume in the record-options screen - threshold and volume can be changed with the 'T' (threshold) and '+'/'-' (source volume) keys - added a FadeIn() method to the IAudioPlayback interface - some minor changes to the audio classes/screens - new base-class for audio-playback classes (used by bass, portaudio and sdl) git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@1078 b956fd51-792f-4845-bead-9b4dfca2ff2c
Diffstat (limited to 'Game/Code/Classes/UAudioPlayback_Bass.pas')
-rw-r--r--Game/Code/Classes/UAudioPlayback_Bass.pas549
1 files changed, 358 insertions, 191 deletions
diff --git a/Game/Code/Classes/UAudioPlayback_Bass.pas b/Game/Code/Classes/UAudioPlayback_Bass.pas
index d47990a8..0fca9c72 100644
--- a/Game/Code/Classes/UAudioPlayback_Bass.pas
+++ b/Game/Code/Classes/UAudioPlayback_Bass.pas
@@ -8,36 +8,40 @@ interface
{$I switches.inc}
+implementation
uses
Classes,
SysUtils,
- UMusic;
-
-implementation
-
-uses
UIni,
UMain,
- ULog,
+ UMusic,
+ UAudioPlaybackBase,
UAudioCore_Bass,
+ ULog,
bass;
type
+ PHDSP = ^HDSP;
+
+type
+ // Playback-stream decoded internally by BASS
TBassPlaybackStream = class(TAudioPlaybackStream)
private
Handle: HSTREAM;
- Loop: boolean;
public
- constructor Create(); overload;
- constructor Create(stream: HSTREAM); overload;
+ constructor Create(stream: HSTREAM);
+ destructor Destroy(); override;
procedure Reset();
procedure Play(); override;
procedure Pause(); override;
procedure Stop(); override;
+ procedure FadeIn(Time: real; TargetVolume: integer); override;
+
procedure Close(); override;
+
function GetLoop(): boolean; override;
procedure SetLoop(Enabled: boolean); override;
function GetLength(): real; override;
@@ -45,79 +49,95 @@ type
function GetVolume(): integer; override;
procedure SetVolume(volume: integer); override;
- function GetPosition: real;
- procedure SetPosition(Time: real);
+ procedure AddSoundEffect(effect: TSoundEffect); override;
+ procedure RemoveSoundEffect(effect: TSoundEffect); override;
+
+ function GetPosition: real; override;
+ procedure SetPosition(Time: real); override;
- function IsLoaded(): boolean;
+ procedure GetFFTData(var data: TFFTData); override;
+ function GetPCMData(var data: TPCMData): Cardinal; override;
end;
-type
- TAudioPlayback_Bass = class( TInterfacedObject, IAudioPlayback)
+ // Playback-stream decoded by an external decoder e.g. FFmpeg
+ TBassExtDecoderPlaybackStream = class(TBassPlaybackStream)
private
- MusicStream: TBassPlaybackStream;
-
- function Load(const Filename: string): TBassPlaybackStream;
+ DecodeStream: TAudioDecodeStream;
public
- function GetName: String;
-
- {IAudioOutput interface}
-
- function InitializePlayback(): boolean;
- procedure SetVolume(Volume: integer);
- procedure SetMusicVolume(Volume: integer);
- procedure SetLoop(Enabled: boolean);
-
- function Open(const 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);
+ procedure Stop(); override;
+ procedure Close(); override;
+ function GetLength(): real; override;
+ function GetPosition: real; override;
+ procedure SetPosition(Time: real); override;
- //Equalizer
- procedure GetFFTData(var data: TFFTData);
+ function SetDecodeStream(decodeStream: TAudioDecodeStream): boolean;
+ end;
- // Interface for Visualizer
- function GetPCMData(var data: TPCMData): Cardinal;
+type
+ TAudioPlayback_Bass = class(TAudioPlaybackBase)
+ private
+ function EnumDevices(): boolean;
+ protected
+ function OpenStream(const Filename: string): TAudioPlaybackStream; override;
+ public
+ function GetName: String; override;
+ function InitializePlayback(): boolean; override;
+ function FinalizePlayback: boolean; override;
+ procedure SetAppVolume(Volume: integer); override;
+ end;
- // Sounds
- function OpenSound(const Filename: String): TAudioPlaybackStream;
- procedure PlaySound(stream: TAudioPlaybackStream);
- procedure StopSound(stream: TAudioPlaybackStream);
+ TBassOutputDevice = class(TAudioOutputDevice)
+ private
+ BassDeviceID: DWORD; // DeviceID used by BASS
end;
var
singleton_AudioPlaybackBass : IAudioPlayback;
-constructor TBassPlaybackStream.Create();
+{ TBassPlaybackStream }
+
+constructor TBassPlaybackStream.Create(stream: HSTREAM);
begin
- inherited;
+ inherited Create();
Reset();
+ Handle := stream;
end;
-constructor TBassPlaybackStream.Create(stream: HSTREAM);
+destructor TBassPlaybackStream.Destroy();
begin
- Create();
- Handle := stream;
+ Close();
+ inherited;
end;
procedure TBassPlaybackStream.Reset();
begin
- Loop := false;
if (Handle <> 0) then
+ begin
Bass_StreamFree(Handle);
+ end;
Handle := 0;
end;
procedure TBassPlaybackStream.Play();
+var
+ restart: boolean;
begin
- BASS_ChannelPlay(Handle, Loop);
+ if (BASS_ChannelIsActive(Handle) = BASS_ACTIVE_PAUSED) then
+ restart := false // resume from last position
+ else
+ restart := true; // start from the beginning
+
+ BASS_ChannelPlay(Handle, restart);
+end;
+
+procedure TBassPlaybackStream.FadeIn(Time: real; TargetVolume: integer);
+begin
+ // start stream
+ BASS_ChannelPlay(Handle, true);
+
+ // start fade-in: slide from fadeStart- to fadeEnd-volume in FadeInTime
+ BASS_ChannelSlideAttributes(Handle, -1, TargetVolume, -101, Trunc(Time * 1000));
end;
procedure TBassPlaybackStream.Pause();
@@ -136,9 +156,11 @@ begin
end;
function TBassPlaybackStream.GetVolume(): integer;
+var
+ volume: cardinal;
begin
- Result := 0;
- BASS_ChannelSetAttributes(Handle, PInteger(nil)^, Result, PInteger(nil)^);
+ BASS_ChannelGetAttributes(Handle, PCardinal(nil)^, volume, PInteger(nil)^);
+ Result := volume;
end;
procedure TBassPlaybackStream.SetVolume(volume: integer);
@@ -168,19 +190,9 @@ begin
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;
+ bytes: integer;
begin
bytes := BASS_ChannelGetLength(Handle);
Result := BASS_ChannelBytes2Seconds(Handle, bytes);
@@ -205,212 +217,367 @@ begin
end;
end;
-function TBassPlaybackStream.IsLoaded(): boolean;
-begin
- Result := (Handle <> 0);
-end;
-
-
-function TAudioPlayback_Bass.GetName: String;
+function TBassPlaybackStream.GetLoop(): boolean;
+var
+ info: BASS_CHANNELINFO;
begin
- result := 'BASS_Playback';
+ if not BASS_ChannelGetInfo(Handle, info) then
+ begin
+ Log.LogError('BASS_ChannelGetInfo: ' + TAudioCore_Bass.ErrorGetString(), 'TBassPlaybackStream.GetLoop');
+ Result := false;
+ Exit;
+ end;
+ Result := (info.flags and BASS_SAMPLE_LOOP) <> 0;
end;
-function TAudioPlayback_Bass.InitializePlayback(): boolean;
+procedure TBassPlaybackStream.SetLoop(Enabled: boolean);
var
- Pet: integer;
- S: integer;
+ info: BASS_CHANNELINFO;
begin
- result := false;
-
- //Log.BenchmarkStart(4);
- //Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize');
-
- if not BASS_Init(1, 44100, 0, 0, nil) then
+ // retrieve old flag-bits
+ if not BASS_ChannelGetInfo(Handle, info) then
begin
- Log.LogError('Could not initialize BASS', 'Error');
+ Log.LogError('BASS_ChannelGetInfo:' + TAudioCore_Bass.ErrorGetString(), 'TBassPlaybackStream.SetLoop');
Exit;
end;
- //Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4);
+ // set/unset loop-flag
+ if (Enabled) then
+ info.flags := info.flags or BASS_SAMPLE_LOOP
+ else
+ info.flags := info.flags and not BASS_SAMPLE_LOOP;
- // config playing buffer
- //BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10);
- //BASS_SetConfig(BASS_CONFIG_BUFFER, 100);
+ // set new flag-bits
+ if not BASS_ChannelSetFlags(Handle, info.flags) then
+ begin
+ Log.LogError('BASS_ChannelSetFlags: ' + TAudioCore_Bass.ErrorGetString(), 'TBassPlaybackStream.SetLoop');
+ Exit;
+ end;
+end;
- result := true;
+procedure DSPProcHandler(handle: HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
+var
+ effect: TSoundEffect;
+begin
+ effect := TSoundEffect(user);
+ if assigned(effect) then
+ effect.Callback(buffer, length);
end;
-function TAudioPlayback_Bass.Load(const Filename: string): TBassPlaybackStream;
+procedure TBassPlaybackStream.AddSoundEffect(effect: TSoundEffect);
var
- L: Integer;
- stream: HSTREAM;
+ dspHandle: HDSP;
begin
- Result := nil;
+ if assigned(effect.engineData) then
+ begin
+ Log.LogError('TSoundEffect.engineData already set', 'TBassPlaybackStream.AddSoundEffect');
+ Exit;
+ end;
- //Log.LogStatus('Loading Sound: "' + Filename + '"', 'LoadSoundFromFile');
- stream := BASS_StreamCreateFile(False, pchar(Filename), 0, 0, 0);
- if (stream = 0) then
+ // FIXME: casting of a pointer to Uint32 will fail on 64bit systems
+ dspHandle := BASS_ChannelSetDSP(Handle, @DSPProcHandler, DWORD(effect), 0);
+ if (dspHandle = 0) then
begin
- Log.LogError('Failed to open "' + Filename + '", ' +
- TAudioCore_Bass.ErrorGetString(BASS_ErrorGetCode()), 'TAudioPlayback_Bass.Load');
+ Log.LogError(TAudioCore_Bass.ErrorGetString(), 'TBassPlaybackStream.AddSoundEffect');
Exit;
end;
- Result := TBassPlaybackStream.Create(stream);
+ GetMem(effect.engineData, SizeOf(HDSP));
+ PHDSP(effect.engineData)^ := dspHandle;
end;
-procedure TAudioPlayback_Bass.SetVolume(Volume: integer);
+procedure TBassPlaybackStream.RemoveSoundEffect(effect: TSoundEffect);
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;
+ if not assigned(effect.EngineData) then
+ begin
+ Log.LogError('TSoundEffect.engineData invalid', 'TBassPlaybackStream.RemoveSoundEffect');
+ Exit;
+ end;
-procedure TAudioPlayback_Bass.SetMusicVolume(Volume: Integer);
-begin
- if assigned(MusicStream) then
- MusicStream.SetVolume(Volume);
+ if not BASS_ChannelRemoveDSP(Handle, PHDSP(effect.EngineData)^) then
+ begin
+ Log.LogError(TAudioCore_Bass.ErrorGetString(), 'TBassPlaybackStream.RemoveSoundEffect');
+ Exit;
+ end;
+
+ FreeMem(effect.engineData);
+ effect.engineData := nil;
end;
-procedure TAudioPlayback_Bass.SetLoop(Enabled: boolean);
+procedure TBassPlaybackStream.GetFFTData(var data: TFFTData);
begin
- if assigned(MusicStream) then
- MusicStream.Loop := Enabled;
+ // Get Channel Data Mono and 256 Values
+ BASS_ChannelGetData(Handle, @data, BASS_DATA_FFT512);
end;
-function TAudioPlayback_Bass.Open(const Filename: string): boolean;
+{*
+ * Copies interleaved PCM SInt16 stereo samples into data.
+ * Returns the number of frames
+ *}
+function TBassPlaybackStream.GetPCMData(var data: TPCMData): Cardinal;
var
- stream: HSTREAM;
+ info: BASS_CHANNELINFO;
+ nBytes: DWORD;
begin
- Result := false;
+ Result := 0;
- // free old MusicStream
- if assigned(MusicStream) then
- MusicStream.Free;
+ // Get Channel Data Mono and 256 Values
+ BASS_ChannelGetInfo(Handle, info);
+ FillChar(data, sizeof(TPCMData), 0);
- MusicStream := Load(Filename);
- if not assigned(MusicStream) then
+ // no support for non-stereo files at the moment
+ if (info.chans <> 2) then
Exit;
- //Set Max Volume
- SetMusicVolume(100);
-
- Result := true;
+ nBytes := BASS_ChannelGetData(Handle, @data, sizeof(TPCMData));
+ if(nBytes <= 0) then
+ result := 0
+ else
+ result := nBytes div sizeof(TPCMStereoSample);
end;
-procedure TAudioPlayback_Bass.Rewind;
-begin
- SetPosition(0);
-end;
-procedure TAudioPlayback_Bass.Play;
-begin
- if assigned(MusicStream) then
- MusicStream.Play();
-end;
+{ TBassExtDecoderPlaybackStream }
-procedure TAudioPlayback_Bass.Pause;
+procedure TBassExtDecoderPlaybackStream.Stop();
begin
- if assigned(MusicStream) then
- MusicStream.Pause();
+ inherited;
+ // rewind
+ if assigned(DecodeStream) then
+ DecodeStream.Position := 0;
end;
-procedure TAudioPlayback_Bass.Stop;
+procedure TBassExtDecoderPlaybackStream.Close();
begin
- if assigned(MusicStream) then
- MusicStream.Stop();
+ // wake-up waiting audio-callback threads in the ReadData()-function
+ if assigned(decodeStream) then
+ DecodeStream.Close();
+ // stop audio-callback on this stream
+ inherited;
+ // free decoder-data
+ FreeAndNil(DecodeStream);
end;
-procedure TAudioPlayback_Bass.Close;
+function TBassExtDecoderPlaybackStream.GetLength(): real;
begin
- if assigned(MusicStream) then
- MusicStream.Close();
+ if assigned(DecodeStream) then
+ result := DecodeStream.Length
+ else
+ result := -1;
end;
-function TAudioPlayback_Bass.Length: real;
-var
- bytes: integer;
+function TBassExtDecoderPlaybackStream.GetPosition: real;
begin
- if assigned(MusicStream) then
- Result := MusicStream.GetLength()
+ if assigned(DecodeStream) then
+ result := DecodeStream.Position
else
- Result := -1;
+ result := -1;
end;
-function TAudioPlayback_Bass.GetPosition: real;
+procedure TBassExtDecoderPlaybackStream.SetPosition(Time: real);
begin
- if assigned(MusicStream) then
- Result := MusicStream.GetPosition()
- else
- Result := -1;
+ if assigned(DecodeStream) then
+ DecodeStream.Position := Time;
end;
-procedure TAudioPlayback_Bass.SetPosition(Time: real);
+function TBassExtDecoderPlaybackStream.SetDecodeStream(decodeStream: TAudioDecodeStream): boolean;
begin
- if assigned(MusicStream) then
- MusicStream.SetPosition(Time);
+ result := false;
+
+ BASS_ChannelStop(Handle);
+
+ if not assigned(decodeStream) then
+ Exit;
+ Self.DecodeStream := decodeStream;
+
+ result := true;
end;
-function TAudioPlayback_Bass.Finished: boolean;
+
+{ TAudioPlayback_Bass }
+
+function TAudioPlayback_Bass.GetName: String;
begin
- if assigned(MusicStream) then
- Result := (MusicStream.GetStatus() = ssStopped)
- else
- Result := true;
+ result := 'BASS_Playback';
end;
-// Equalizer
-procedure TAudioPlayback_Bass.GetFFTData(var data: TFFTData);
+function TAudioPlayback_Bass.EnumDevices(): boolean;
+var
+ BassDeviceID: DWORD;
+ DeviceIndex: integer;
+ Device: TBassOutputDevice;
+ Description: PChar;
begin
- // Get Channel Data Mono and 256 Values
- BASS_ChannelGetData(MusicStream.Handle, @data, BASS_DATA_FFT512);
+ ClearOutputDeviceList();
+
+ // skip "no sound"-device (ID = 0)
+ BassDeviceID := 1;
+
+ while true do
+ begin
+ // Check for device
+ Description := BASS_GetDeviceDescription(BassDeviceID);
+ if (Description = nil) then
+ break;
+
+ // Set device info
+ Device := TBassOutputDevice.Create();
+ Device.Name := Description;
+ Device.BassDeviceID := BassDeviceID;
+
+ // Add device to list
+ SetLength(OutputDeviceList, BassDeviceID);
+ OutputDeviceList[BassDeviceID-1] := Device;
+
+ Inc(BassDeviceID);
+ end;
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;
+function TAudioPlayback_Bass.InitializePlayback(): boolean;
var
- info: BASS_CHANNELINFO;
- nBytes: DWORD;
+ Pet: integer;
+ S: integer;
begin
- Result := 0;
+ result := false;
- // Get Channel Data Mono and 256 Values
- BASS_ChannelGetInfo(MusicStream.Handle, info);
- FillChar(data, sizeof(TPCMData), 0);
+ EnumDevices();
- // no support for non-stereo files at the moment
- if (info.chans <> 2) then
+ //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;
- nBytes := BASS_ChannelGetData(MusicStream.Handle, @data, sizeof(TPCMData));
- if(nBytes <= 0) then
- result := 0
+ //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 DecodeStreamHandler(handle: HSTREAM; buffer: Pointer; length: DWORD; user: DWORD): DWORD; stdcall;
+var
+ decodeStream: TAudioDecodeStream;
+ bytes: integer;
+begin
+ decodeStream := TAudioDecodeStream(user);
+ bytes := decodeStream.ReadData(buffer, length);
+ // handle errors
+ if (bytes < 0) then
+ Result := BASS_STREAMPROC_END
+ // handle EOF
+ else if (DecodeStream.EOF) then
+ Result := bytes or BASS_STREAMPROC_END
else
- result := nBytes div sizeof(TPCMStereoSample);
+ Result := bytes;
end;
-function TAudioPlayback_Bass.OpenSound(const Filename: string): TAudioPlaybackStream;
+function TAudioPlayback_Bass.FinalizePlayback(): boolean;
begin
- result := Load(Filename);
+ Close;
+ BASS_Free;
+ inherited FinalizePlayback();
+ Result := true;
end;
-procedure TAudioPlayback_Bass.PlaySound(stream: TAudioPlaybackStream);
+function TAudioPlayback_Bass.OpenStream(const Filename: string): TAudioPlaybackStream;
+var
+ L: Integer;
+ stream: HSTREAM;
+ playbackStream: TBassExtDecoderPlaybackStream;
+ decodeStream: TAudioDecodeStream;
+ formatInfo: TAudioFormatInfo;
+ formatFlags: DWORD;
+ channelInfo: BASS_CHANNELINFO;
+ fileExt: string;
begin
- if assigned(stream) then
- stream.Play();
+ Result := nil;
+
+ //Log.LogStatus('Loading Sound: "' + Filename + '"', 'LoadSoundFromFile');
+ stream := BASS_StreamCreateFile(False, PChar(Filename), 0, 0, 0);
+
+ // check if BASS opened some erroneously recognized file-formats
+ if (stream <> 0) then
+ begin
+ if BASS_ChannelGetInfo(stream, channelInfo) then
+ begin
+ fileExt := ExtractFileExt(Filename);
+ // BASS opens FLV-files although it cannot handle them
+ if ((fileExt = '.flv') and (channelInfo.ctype = BASS_CTYPE_STREAM_MP1)) then
+ begin
+ BASS_StreamFree(stream);
+ stream := 0;
+ end;
+ end;
+ end;
+
+ // Check if BASS can handle the format or try another decoder otherwise
+ if (stream <> 0) then
+ begin
+ Result := TBassPlaybackStream.Create(stream);
+ end
+ else
+ begin
+ if (AudioDecoder = nil) then
+ begin
+ Log.LogError('Failed to open "' + Filename + '", ' +
+ TAudioCore_Bass.ErrorGetString(BASS_ErrorGetCode()), 'TAudioPlayback_Bass.Load');
+ Exit;
+ end;
+
+ decodeStream := AudioDecoder.Open(Filename);
+ if not assigned(decodeStream) then
+ begin
+ Log.LogStatus('Sound not found "' + Filename + '"', 'TAudioPlayback_Bass.Load');
+ Exit;
+ end;
+
+ formatInfo := decodeStream.GetAudioFormatInfo();
+ if (not TAudioCore_Bass.ConvertAudioFormatToBASSFlags(formatInfo.Format, formatFlags)) then
+ begin
+ Log.LogError('Unhandled sample-format in "' + Filename + '"', 'TAudioPlayback_Bass.Load');
+ FreeAndNil(decodeStream);
+ Exit;
+ end;
+
+ // FIXME: casting of a pointer to Uint32 will fail on 64bit systems
+ stream := BASS_StreamCreate(Round(formatInfo.SampleRate), formatInfo.Channels, formatFlags,
+ @DecodeStreamHandler, DWORD(decodeStream));
+ if (stream = 0) then
+ begin
+ Log.LogError('Failed to open "' + Filename + '", ' +
+ TAudioCore_Bass.ErrorGetString(BASS_ErrorGetCode()), 'TAudioPlayback_Bass.Load');
+ FreeAndNil(decodeStream);
+ Exit;
+ end;
+
+ playbackStream := TBassExtDecoderPlaybackStream.Create(stream);
+ if (not assigned(playbackStream)) then
+ begin
+ FreeAndNil(decodeStream);
+ Exit;
+ end;
+
+ if (not playbackStream.SetDecodeStream(decodeStream)) then
+ begin
+ FreeAndNil(playbackStream);
+ FreeAndNil(decodeStream);
+ Exit;
+ end;
+
+ Result := playbackStream;
+ end;
end;
-procedure TAudioPlayback_Bass.StopSound(stream: TAudioPlaybackStream);
+procedure TAudioPlayback_Bass.SetAppVolume(Volume: integer);
begin
- if assigned(stream) then
- stream.Stop();
+ // Sets Volume only for this Application
+ BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume);
end;