2
// This unit is part of the GLScene Engine https://github.com/glscene
5
BASS based sound-manager (http://www.un4seen.com/music/, free for freeware).
7
Unsupported feature(s) :
9
looping (sounds are played either once or forever)
10
source priorities (not relevant, channels are not limited)
14
14/01/14 - PW - Updated to BASS 2.4 thanks to Ian Luck
15
07/01/10 - DaStr - Fixed a bug with an initial Paused or Muted state of
16
sound source and with sscSample in aSource.Changes
17
07/11/09 - DaStr - Improved FPC compatibility
18
(thanks Predator) (BugtrackerID = 2893580)
19
21/03/08 - DanB - Updated to BASS Version 2.3
20
15/03/08 - DaStr - Added $I GLScene.inc
21
09/05/04 - GAK - Updated to BASS Version 2.0, and swapped to Dynamic DLL loading
22
24/09/02 - EG - BASS activation errors no longer result in Asserts (ignored)
23
27/02/02 - EG - Added 3D Factors and Environment support
24
05/02/02 - EG - BASS 1.4 compatibility
25
05/02/01 - EG - Fixed TGLSMBASS.CPUUsagePercent
26
13/01/01 - EG - Creation (compat BASS 0.8)
36
Classes, SysUtils, Forms, Controls,
39
GLSound, GLScene, Bass, GLVectorGeometry;
45
TBASS3DAlgorithm = (algDefault, algOff, algFull, algLight);
49
TGLSMBASS = class (TGLSoundManager)
53
FAlgorithm3D : TBASS3DAlgorithm;
57
function DoActivate : Boolean; override;
58
procedure DoDeActivate; override;
59
procedure NotifyMasterVolumeChange; override;
60
procedure Notify3DFactorsChanged; override;
61
procedure NotifyEnvironmentChanged; override;
63
procedure KillSource(aSource : TGLBaseSoundSource); override;
64
procedure UpdateSource(aSource : TGLBaseSoundSource); override;
65
procedure MuteSource(aSource : TGLBaseSoundSource; muted : Boolean); override;
66
procedure PauseSource(aSource : TGLBaseSoundSource; paused : Boolean); override;
68
function GetDefaultFrequency(aSource : TGLBaseSoundSource) : Integer;
72
constructor Create(AOwner : TComponent); override;
73
destructor Destroy; override;
75
procedure UpdateSources; override;
77
function CPUUsagePercent : Single; override;
78
function EAXSupported : Boolean; override;
82
property Algorithm3D : TBASS3DAlgorithm read FAlgorithm3D write FAlgorithm3D default algDefault;
87
// ---------------------------------------------------------------------
88
// ---------------------------------------------------------------------
89
// ---------------------------------------------------------------------
91
// ---------------------------------------------------------------------
92
// ---------------------------------------------------------------------
93
// ---------------------------------------------------------------------
100
PBASSInfo = ^TBASSInfo;
104
RegisterComponents('GLScene', [TGLSMBASS]);
109
procedure VectorToBASSVector(const aVector : TVector; var aBASSVector : BASS_3DVECTOR);
111
aBASSVector.x:=aVector.X;
112
aBASSVector.y:=aVector.Y;
113
aBASSVector.z:=-aVector.Z;
117
// ------------------ TGLSMBASS ------------------
122
constructor TGLSMBASS.Create(AOwner : TComponent);
124
inherited Create(AOwner);
131
destructor TGLSMBASS.Destroy;
139
function TGLSMBASS.DoActivate : Boolean;
141
c3DAlgo : array [algDefault..algLight] of Integer =
142
(BASS_3DALG_DEFAULT, BASS_3DALG_OFF, BASS_3DALG_FULL, BASS_3DALG_LIGHT);
144
Assert(bass_isloaded,'BASS DLL is not present');
146
if not BASS_Init(1, OutputFrequency, BASS_DEVICE_3D, Pointer(TWinControl(Owner).Handle), nil) then
152
if not BASS_Start then begin
157
BASS_SetConfig(BASS_CONFIG_3DALGORITHM, c3DAlgo[FAlgorithm3D]);
158
NotifyMasterVolumeChange;
159
Notify3DFactorsChanged;
160
if Environment<>seDefault then
161
NotifyEnvironmentChanged;
167
procedure TGLSMBASS.DoDeActivate;
174
// NotifyMasterVolumeChange
176
procedure TGLSMBASS.NotifyMasterVolumeChange;
179
BASS_SetVolume(Round(MasterVolume*100));
182
// Notify3DFactorsChanged
184
procedure TGLSMBASS.Notify3DFactorsChanged;
187
BASS_Set3DFactors(DistanceFactor, RollOffFactor, DopplerFactor);
190
// NotifyEnvironmentChanged
192
procedure TGLSMBASS.NotifyEnvironmentChanged;
195
cEnvironmentToBASSConstant : array [seDefault..sePsychotic] of Integer = (
196
EAX_ENVIRONMENT_GENERIC, EAX_ENVIRONMENT_PADDEDCELL, EAX_ENVIRONMENT_ROOM,
197
EAX_ENVIRONMENT_BATHROOM, EAX_ENVIRONMENT_LIVINGROOM, EAX_ENVIRONMENT_STONEROOM,
198
EAX_ENVIRONMENT_AUDITORIUM, EAX_ENVIRONMENT_CONCERTHALL, EAX_ENVIRONMENT_CAVE,
199
EAX_ENVIRONMENT_ARENA, EAX_ENVIRONMENT_HANGAR, EAX_ENVIRONMENT_CARPETEDHALLWAY,
200
EAX_ENVIRONMENT_HALLWAY, EAX_ENVIRONMENT_STONECORRIDOR, EAX_ENVIRONMENT_ALLEY,
201
EAX_ENVIRONMENT_FOREST, EAX_ENVIRONMENT_CITY, EAX_ENVIRONMENT_MOUNTAINS,
202
EAX_ENVIRONMENT_QUARRY, EAX_ENVIRONMENT_PLAIN, EAX_ENVIRONMENT_PARKINGLOT,
203
EAX_ENVIRONMENT_SEWERPIPE, EAX_ENVIRONMENT_UNDERWATER, EAX_ENVIRONMENT_DRUGGED,
204
EAX_ENVIRONMENT_DIZZY, EAX_ENVIRONMENT_PSYCHOTIC);
206
if FActivated and EAXSupported then
207
BASS_SetEAXParameters(cEnvironmentToBASSConstant[Environment],-1,-1,-1);
216
procedure TGLSMBASS.KillSource(aSource : TGLBaseSoundSource);
220
if aSource.ManagerTag<>0 then begin
221
p:=PBASSInfo(aSource.ManagerTag);
223
if not BASS_ChannelStop(p.channel) then Assert(False);
224
BASS_SampleFree(p.sample);
226
aSource.ManagerTag:=0;
232
procedure TGLSMBASS.UpdateSource(aSource : TGLBaseSoundSource);
236
objPos, objOri, objVel : TVector;
237
position, orientation, velocity : BASS_3DVECTOR;
240
if (sscSample in aSource.Changes) then
245
if (aSource.Sample=nil) or (aSource.Sample.Data=nil) or
246
(aSource.Sample.Data.WAVDataSize=0) then Exit;
247
if aSource.ManagerTag<>0 then begin
248
p:=PBASSInfo(aSource.ManagerTag);
249
if BASS_ChannelIsActive(p.channel)=0 then begin
255
p:=AllocMem(SizeOf(TBASSInfo));
257
i:=BASS_SAMPLE_VAM+BASS_SAMPLE_3D+BASS_SAMPLE_OVER_DIST;
258
if aSource.NbLoops>1 then
259
i:=i+BASS_SAMPLE_LOOP;
260
p.sample:=BASS_SampleLoad(True, aSource.Sample.Data.WAVData, 0,
261
aSource.Sample.Data.WAVDataSize,
263
Assert(p.sample<>0, 'BASS Error '+IntToStr(Integer(BASS_ErrorGetCode)));
264
aSource.ManagerTag:=Integer(p);
265
if aSource.Frequency<=0 then
266
aSource.Frequency:=-1;
268
if aSource.Origin<>nil then begin
269
objPos:=aSource.Origin.AbsolutePosition;
270
objOri:=aSource.Origin.AbsoluteZVector;
271
objVel:=NullHmgVector;
273
objPos:=NullHmgPoint;
275
objVel:=NullHmgVector;
277
VectorToBASSVector(objPos, position);
278
VectorToBASSVector(objVel, velocity);
279
VectorToBASSVector(objOri, orientation);
280
if p.channel=0 then begin
281
p.channel:=BASS_SampleGetChannel(p.sample,false);
282
Assert(p.channel<>0);
283
BASS_ChannelSet3DPosition(p.channel,position, orientation, velocity);
284
BASS_ChannelSet3DAttributes(p.channel, BASS_3DMODE_NORMAL,
285
aSource.MinDistance, aSource.MaxDistance,
286
Round(aSource.InsideConeAngle),
287
Round(aSource.OutsideConeAngle),
288
Round(aSource.ConeOutsideVolume*100));
289
if not aSource.Pause then
290
BASS_ChannelPlay(p.channel,true);
292
end else BASS_ChannelSet3DPosition(p.channel, position, orientation, velocity);
296
res := BASS_ChannelSetAttribute(p.channel, BASS_ATTRIB_FREQ, 0);
299
res := BASS_ChannelSetAttribute(p.channel, BASS_ATTRIB_VOL, 0)
301
res := BASS_ChannelSetAttribute(p.channel, BASS_ATTRIB_VOL, aSource.Volume);
303
end else aSource.Free;
304
inherited UpdateSource(aSource);
309
procedure TGLSMBASS.MuteSource(aSource : TGLBaseSoundSource; muted : Boolean);
314
if aSource.ManagerTag<>0 then begin
315
p:=PBASSInfo(aSource.ManagerTag);
317
res:=BASS_ChannelSetAttribute(p.channel, BASS_ATTRIB_VOL, 0)
318
else res:=BASS_ChannelSetAttribute(p.channel, BASS_ATTRIB_VOL, aSource.Volume);
325
procedure TGLSMBASS.PauseSource(aSource : TGLBaseSoundSource; paused : Boolean);
329
if aSource.ManagerTag<>0 then begin
330
p:=PBASSInfo(aSource.ManagerTag);
332
BASS_ChannelPause(p.channel)
333
else BASS_ChannelPlay(p.channel,false);
339
procedure TGLSMBASS.UpdateSources;
341
objPos, objVel, objDir, objUp : TVector;
342
position, velocity, fwd, top : BASS_3DVECTOR;
345
ListenerCoordinates(objPos, objVel, objDir, objUp);
346
VectorToBASSVector(objPos, position);
347
VectorToBASSVector(objVel, velocity);
348
VectorToBASSVector(objDir, fwd);
349
VectorToBASSVector(objUp, top);
350
if not BASS_Set3DPosition(position, velocity, fwd, top) then Assert(False);
353
{if not }BASS_Apply3D;{ then Assert(False);}
358
function TGLSMBASS.CPUUsagePercent : Single;
360
Result:=BASS_GetCPU*100;
365
function TGLSMBASS.EAXSupported : Boolean;
371
Result:=BASS_GetEAXParameters(c, s, s, s);
378
// GetDefaultFrequency
380
function TGLSMBASS.GetDefaultFrequency(aSource : TGLBaseSoundSource): integer;
383
sampleInfo : BASS_Sample;
386
p:=PBASSInfo(aSource.ManagerTag);
387
BASS_SampleGetInfo(p.sample, sampleInfo);
388
Result:=sampleInfo.freq;