| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613 |
- //
- // This unit is part of the GLScene Engine, http://glscene.org
- //
- unit GLSound;
- (* Base classes and interface for Sound System *)
- interface
- uses
- System.Classes,
- System.SysUtils,
- System.Types,
- GLVectorTypes,
- GLSoundFileObjects,
- GLScene,
- XCollection,
- GLVectorGeometry,
- GLCadencer,
- GLBaseClasses,
- GLS.Utils;
- {$I GLScene.inc}
- type
- // Stores a single PCM coded sound sample.
- TGLSoundSample = class(TCollectionItem)
- private
- FName: string;
- FData: TGLSoundFile;
- FTag: Integer;
- protected
- procedure DefineProperties(Filer: TFiler); override;
- procedure ReadData(Stream: TStream); virtual;
- procedure WriteData(Stream: TStream); virtual;
- function GetDisplayName: string; override;
- procedure SetData(const val: TGLSoundFile);
- public
- constructor Create(Collection: TCollection); override;
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- procedure LoadFromFile(const fileName: string);
- procedure PlayOnWaveOut;
- function Sampling: TGLSoundSampling;
- function LengthInBytes: Integer;
- function LengthInSamples: Integer;
- function LengthInSec: Single;
- // This Tag is reserved for sound manager use only
- property ManagerTag: Integer read FTag write FTag;
- published
- property Name: string read FName write FName;
- property Data: TGLSoundFile read FData write SetData stored False;
- end;
- TGLSoundSamples = class(TCollection)
- protected
- owner: TComponent;
- function GetOwner: TPersistent; override;
- procedure SetItems(index: Integer; const val: TGLSoundSample);
- function GetItems(index: Integer): TGLSoundSample;
- public
- constructor Create(AOwner: TComponent);
- function Add: TGLSoundSample;
- function FindItemID(ID: Integer): TGLSoundSample;
- property Items[index: Integer]: TGLSoundSample read GetItems write SetItems; default;
- function GetByName(const aName: string): TGLSoundSample;
- function AddFile(const fileName: string; const sampleName: string = ''): TGLSoundSample;
- end;
- TGLSoundLibrary = class(TComponent)
- private
- FSamples: TGLSoundSamples;
- protected
- procedure SetSamples(const val: TGLSoundSamples);
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- published
- property Samples: TGLSoundSamples read FSamples write SetSamples;
- end;
- TGLSoundSourceChange = (sscTransformation, sscSample, sscStatus);
- TGLSoundSourceChanges = set of TGLSoundSourceChange;
- TGLBSoundEmitter = class;
- // Base class for origin of sound playback.
- TGLBaseSoundSource = class(TCollectionItem)
- private
- FBehaviourToNotify: TGLBSoundEmitter;
- // private only, NOT persistent, not assigned
- FPriority: Integer;
- FOrigin: TGLBaseSceneObject; // NOT persistent
- FVolume: Single;
- FMinDistance, FMaxDistance: Single;
- FInsideConeAngle, FOutsideConeAngle: Single;
- FConeOutsideVolume: Single;
- FSoundLibraryName: string; // used for persistence
- FSoundLibrary: TGLSoundLibrary; // persistence via name
- FSoundName: string;
- FMute: Boolean;
- FPause: Boolean;
- FChanges: TGLSoundSourceChanges; // NOT persistent, not assigned
- FNbLoops: Integer;
- FTag: Cardinal; // NOT persistent, not assigned
- FFrequency: Integer;
- protected
- procedure WriteToFiler(writer: TWriter);
- procedure ReadFromFiler(reader: TReader);
- function GetDisplayName: string; override;
- procedure SetPriority(const val: Integer);
- procedure SetOrigin(const val: TGLBaseSceneObject);
- procedure SetVolume(const val: Single);
- procedure SetMinDistance(const val: Single);
- procedure SetMaxDistance(const val: Single);
- procedure SetInsideConeAngle(const val: Single);
- procedure SetOutsideConeAngle(const val: Single);
- procedure SetConeOutsideVolume(const val: Single);
- function GetSoundLibrary: TGLSoundLibrary;
- procedure SetSoundLibrary(const val: TGLSoundLibrary);
- procedure SetSoundName(const val: string);
- procedure SetMute(const val: Boolean);
- procedure SetPause(const val: Boolean);
- procedure SetNbLoops(const val: Integer);
- procedure SetFrequency(const val: Integer);
- public
- constructor Create(Collection: TCollection); override;
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- property Changes: TGLSoundSourceChanges read FChanges;
- function Sample: TGLSoundSample;
- // This Tag is reserved for sound manager use only
- property ManagerTag: Cardinal read FTag write FTag;
- (* Origin object for the sound sources.
- Absolute object position/orientation are taken into account, the
- object's TGLBInertia is considered if any.
- If origin is nil, the source is assumed to be static at the origin.
- Note : since TCollectionItem do not support the "Notification"
- scheme, it is up to the Origin object to take care of updating this
- property prior to release/destruction. *)
- property Origin: TGLBaseSceneObject read FOrigin write SetOrigin;
- published
- property SoundLibrary: TGLSoundLibrary read GetSoundLibrary write SetSoundLibrary;
- property SoundName: string read FSoundName write SetSoundName;
- // Volume of the source, [0.0; 1.0] range
- property Volume: Single read FVolume write SetVolume;
- // Nb of playing loops.
- property NbLoops: Integer read FNbLoops write SetNbLoops default 1;
- property Mute: Boolean read FMute write SetMute default False;
- property Pause: Boolean read FPause write SetPause default False;
- (* Sound source priority, the higher the better.
- When maximum number of sound sources is reached, only the sources
- with the highest priority will continue to play, however, even
- non-playing sources should be tracked by the manager, thus allowing
- an "unlimited" amount of sources from the application point of view. *)
- property Priority: Integer read FPriority write SetPriority default 0;
- // Min distance before spatial attenuation occurs. 1.0 by default
- property MinDistance: Single read FMinDistance write SetMinDistance;
- //Max distance, if source is further away, it will not be heard. 100.0 by default
- property MaxDistance: Single read FMaxDistance write SetMaxDistance;
- (* Inside cone angle, [0°; 360°].
- Sound volume is maximal within this cone. See DirectX SDK for details. *)
- property InsideConeAngle: Single read FInsideConeAngle write SetInsideConeAngle;
- (* Outside cone angle, [0°; 360°].
- Between inside and outside cone, sound volume decreases between max
- and cone outside volume. See DirectX SDK for details. *)
- property OutsideConeAngle: Single read FOutsideConeAngle write SetOutsideConeAngle;
- // Cone outside volume, [0.0; 1.0] range. See DirectX SDK for details.
- property ConeOutsideVolume: Single read FConeOutsideVolume write SetConeOutsideVolume;
- // Sample custom playback frequency. Values null or negative are interpreted as 'default frequency'.
- property Frequency: Integer read FFrequency write SetFrequency default -1;
- end;
- (* Origin of sound playback.
- Just publishes the 'Origin' property.
- Note that the "orientation" is the the source's Direction, ie. the "Z" vector. *)
- TGLSoundSource = class(TGLBaseSoundSource)
- public
- destructor Destroy; override;
- published
- property Origin;
- end;
- TGLSoundSources = class(TCollection)
- protected
- owner: TComponent;
- function GetOwner: TPersistent; override;
- procedure SetItems(index: Integer; const val: TGLSoundSource);
- function GetItems(index: Integer): TGLSoundSource;
- function Add: TGLSoundSource;
- function FindItemID(ID: Integer): TGLSoundSource;
- public
- constructor Create(AOwner: TComponent);
- property Items[index: Integer]: TGLSoundSource read GetItems write SetItems; default;
- end;
- // EAX standard sound environments.
- TGLSoundEnvironment = (seDefault, sePaddedCell, seRoom, seBathroom,
- seLivingRoom, seStoneroom, seAuditorium,
- seConcertHall, seCave, seArena, seHangar,
- seCarpetedHallway, seHallway, seStoneCorridor,
- seAlley, seForest, seCity, seMountains, seQuarry,
- sePlain, seParkingLot, seSewerPipe, seUnderWater,
- seDrugged, seDizzy, sePsychotic);
- (* Base class for sound manager components.
- The sound manager component is the interface to a low-level audio API
- (like DirectSound), there can only be one active manager at any time
- (this class takes care of this).
- Subclass should override the DoActivate and DoDeActivate protected methods
- to "initialize/unitialize" their sound layer, actual data releases should
- occur in destructor however. *)
- TGLSoundManager = class(TGLCadenceAbleComponent)
- private
- FActive: Boolean;
- FMute: Boolean;
- FPause: Boolean;
- FMasterVolume: Single;
- FListener: TGLBaseSceneObject;
- FLastListenerPosition: TVector;
- FSources: TGLSoundSources;
- FMaxChannels: Integer;
- FOutputFrequency: Integer;
- FUpdateFrequency: Single;
- FDistanceFactor: Single;
- FRollOffFactor: Single;
- FDopplerFactor: Single;
- FSoundEnvironment: TGLSoundEnvironment;
- FLastUpdateTime, FLastDeltaTime: Single;
- // last time UpdateSources was fired, not persistent
- FCadencer: TGLCadencer;
- procedure SetActive(const val: Boolean);
- procedure SetMute(const val: Boolean);
- procedure SetPause(const val: Boolean);
- procedure WriteDoppler(writer: TWriter);
- procedure ReadDoppler(reader: TReader);
- protected
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- procedure SetSources(const val: TGLSoundSources);
- procedure SetMasterVolume(const val: Single);
- procedure SetListener(const val: TGLBaseSceneObject);
- procedure SetMaxChannels(const val: Integer);
- procedure SetOutputFrequency(const val: Integer);
- procedure SetUpdateFrequency(const val: Single);
- function StoreUpdateFrequency: Boolean;
- procedure SetCadencer(const val: TGLCadencer);
- procedure SetDistanceFactor(const val: Single);
- function StoreDistanceFactor: Boolean;
- procedure SetRollOffFactor(const val: Single);
- function StoreRollOffFactor: Boolean;
- procedure SetDopplerFactor(const val: Single);
- procedure SetSoundEnvironment(const val: TGLSoundEnvironment);
- procedure Loaded; override;
- procedure DefineProperties(Filer: TFiler); override;
- procedure ListenerCoordinates(var position, velocity, direction, up: TVector);
- function DoActivate: Boolean; virtual;
- // Invoked AFTER all sources have been stopped
- procedure DoDeActivate; virtual;
- (* Effect mute of all sounds.
- Default implementation call MuteSource for all non-muted sources
- with "True" as parameter. *)
- function DoMute: Boolean; virtual;
- (* Effect un-mute of all sounds.
- Default implementation call MuteSource for all non-muted sources
- with "False" as parameter. *)
- procedure DoUnMute; virtual;
- (* Effect pause of all sounds.
- Default implementation call PauseSource for all non-paused sources
- with "True" as parameter. *)
- function DoPause: Boolean; virtual;
- (* Effect un-pause of all sounds.
- Default implementation call PauseSource for all non-paused sources
- with "True" as parameter. *)
- procedure DoUnPause; virtual;
- procedure NotifyMasterVolumeChange; virtual;
- procedure Notify3DFactorsChanged; virtual;
- procedure NotifyEnvironmentChanged; virtual;
- // Called when a source will be freed
- procedure KillSource(aSource: TGLBaseSoundSource); virtual;
- (* Request to update source's data in low-level sound API.
- Default implementation just clears the "Changes" flags. *)
- procedure UpdateSource(aSource: TGLBaseSoundSource); virtual;
- procedure MuteSource(aSource: TGLBaseSoundSource; muted: Boolean); virtual;
- procedure PauseSource(aSource: TGLBaseSoundSource; paused: Boolean); virtual;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- (* Manual request to update all sources to reflect changes.
- Default implementation invokes UpdateSource for all known sources. *)
- procedure UpdateSources; virtual;
- // Stop and free all sources.
- procedure StopAllSources;
- (* Progress notification for time synchronization.
- This method will call UpdateSources depending on the last time
- it was performed and the value of the UpdateFrequency property. *)
- procedure DoProgress(const progressTime: TGLProgressTimes); override;
- // Sound manager API reported CPU Usage. Returns -1 when unsupported.
- function CPUUsagePercent: Single; virtual;
- // True if EAX is supported.
- function EAXSupported: Boolean; virtual;
- published
- // Activation/deactivation of the low-level sound API
- property Active: Boolean read FActive write SetActive default False;
- (* Maximum number of sound output channels.
- While some drivers will just ignore this value, others cannot
- dynamically adjust the maximum number of channels (you need to
- de-activate and re-activate the manager for this property to be
- taken into account). *)
- property MaxChannels: Integer read FMaxChannels write SetMaxChannels default 8;
- (* Sound output mixing frequency.
- Commonly used values ar 11025, 22050 and 44100.
- Note that most driver cannot dynamically adjust the output frequency
- (you need to de-ativate and re-activate the manager for this property
- to be taken into account). *)
- property OutputFrequency: Integer read FOutputFrequency write SetOutputFrequency default 44100;
- (* Request to mute all sounds.
- All sound requests should be handled as if sound is unmuted though,
- however drivers should try to take a CPU advantage of mute over
- MasterVolume=0 *)
- property Mute: Boolean read FMute write SetMute default False;
- (* Request to pause all sound, sound output should be muted too.
- When unpausing, all sound should resume at the point they were paused. *)
- property Pause: Boolean read FPause write SetPause default False;
- (* Master Volume adjustement in the [0.0; 1.0] range.
- Driver should take care of properly clamping the master volume. *)
- property MasterVolume: Single read FMasterVolume write SetMasterVolume;
- (* Scene object that materializes the listener.
- The sceneobject's AbsolutePosition and orientation are used to define
- the listener coordinates, velocity is automatically calculated
- (if you're using DoProgress or connected the manager to a cadencer).
- If this property is nil, the listener is assumed to be static at
- the NullPoint coordinate, facing Z axis, with up being Y (ie. the
- default GLScene orientation). *)
- property Listener: TGLBaseSceneObject read FListener write SetListener;
- // Currently active and playing sound sources.
- property Sources: TGLSoundSources read FSources write SetSources;
- (* Update frequency for time-based control (DoProgress).
- Default value is 10 Hz (frequency is clamped in the 1Hz-60Hz range). *)
- property UpdateFrequency: Single read FUpdateFrequency write SetUpdateFrequency stored StoreUpdateFrequency;
- // Cadencer for time-based control.
- property Cadencer: TGLCadencer read FCadencer write SetCadencer;
- (* Engine relative distance factor, compared to 1.0 meters.
- Equates to 'how many units per meter' your engine has. *)
- property DistanceFactor: Single read FDistanceFactor write SetDistanceFactor stored StoreDistanceFactor;
- (* Sets the global attenuation rolloff factor.
- Normally volume for a sample will scale at 1 / distance.
- This gives a logarithmic attenuation of volume as the source gets
- further away (or closer).
- Setting this value makes the sound drop off faster or slower.
- The higher the value, the faster volume will fall off. *)
- property RollOffFactor: Single read FRollOffFactor write SetRollOffFactor stored StoreRollOffFactor;
- (* Engine relative Doppler factor, compared to 1.0 meters.
- Equates to 'how many units per meter' your engine has. *)
- property DopplerFactor: Single read FDopplerFactor write SetDopplerFactor stored False;
- // Sound environment (requires EAX compatible soundboard).
- property Environment: TGLSoundEnvironment read FSoundEnvironment write SetSoundEnvironment default seDefault;
- end;
- (* A sound emitter behaviour, plug it on any object to make it noisy.
- This behaviour is just an interface to a TGLSoundSource, for editing convenience. *)
- TGLBSoundEmitter = class(TGLBehaviour)
- private
- FPlaying: Boolean; // used at design-time ONLY
- FSource: TGLBaseSoundSource;
- FPlayingSource: TGLSoundSource;
- protected
- procedure WriteToFiler(writer: TWriter); override;
- procedure ReadFromFiler(reader: TReader); override;
- procedure Loaded; override;
- procedure SetSource(const val: TGLBaseSoundSource);
- procedure SetPlaying(const val: Boolean);
- function GetPlaying: Boolean;
- procedure NotifySourceDestruction(aSource: TGLSoundSource);
- public
- constructor Create(AOwner: TXCollection); override;
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- class function FriendlyName: String; override;
- class function FriendlyDescription: String; override;
- class function UniqueItem: Boolean; override;
- procedure DoProgress(const progressTime: TGLProgressTimes); override;
- property PlayingSource: TGLSoundSource read FPlayingSource;
- published
- property Source: TGLBaseSoundSource read FSource write SetSource;
- property Playing: Boolean read GetPlaying write SetPlaying default False;
- end;
- function ActiveSoundManager: TGLSoundManager;
- function GetSoundLibraryByName(const aName: string): TGLSoundLibrary;
- function GetOrCreateSoundEmitter(behaviours: TGLBehaviours): TGLBSoundEmitter; overload;
- function GetOrCreateSoundEmitter(obj: TGLBaseSceneObject): TGLBSoundEmitter; overload;
- var
- // If this variable is true, errors in GLSM may be displayed to the user
- vVerboseGLSMErrors: Boolean = True;
- // ------------------------------------------------------------------
- implementation
- // ------------------------------------------------------------------
- var
- vActiveSoundManager: TGLSoundManager;
- vSoundLibraries: TList;
- function ActiveSoundManager: TGLSoundManager;
- begin
- Result := vActiveSoundManager;
- end;
- function GetSoundLibraryByName(const aName: string): TGLSoundLibrary;
- var
- i: Integer;
- begin
- Result := nil;
- if Assigned(vSoundLibraries) then
- for i := 0 to vSoundLibraries.Count - 1 do
- if TGLSoundLibrary(vSoundLibraries[i]).Name = aName then
- begin
- Result := TGLSoundLibrary(vSoundLibraries[i]);
- Break;
- end;
- end;
- function GetOrCreateSoundEmitter(behaviours: TGLBehaviours): TGLBSoundEmitter;
- var
- i: Integer;
- begin
- i := behaviours.IndexOfClass(TGLBSoundEmitter);
- if i >= 0 then
- Result := TGLBSoundEmitter(behaviours[i])
- else
- Result := TGLBSoundEmitter.Create(behaviours);
- end;
- function GetOrCreateSoundEmitter(obj: TGLBaseSceneObject): TGLBSoundEmitter;
- begin
- Result := GetOrCreateSoundEmitter(obj.Behaviours);
- end;
- // ------------------
- // ------------------ TGLSoundSample ------------------
- // ------------------
- constructor TGLSoundSample.Create(Collection: TCollection);
- begin
- inherited Create(Collection);
- end;
- destructor TGLSoundSample.Destroy;
- begin
- FData.Free;
- inherited Destroy;
- end;
- procedure TGLSoundSample.Assign(Source: TPersistent);
- begin
- if Source is TGLSoundSample then
- begin
- FName := TGLSoundSample(Source).Name;
- FData.Free;
- FData := TGLSoundFile(TGLSoundSample(Source).Data.CreateCopy(Self));
- end
- else
- inherited Assign(Source); // Assign error
- end;
- procedure TGLSoundSample.DefineProperties(Filer: TFiler);
- begin
- Filer.DefineBinaryProperty('BinData', ReadData, WriteData, Assigned(FData));
- end;
- procedure TGLSoundSample.ReadData(Stream: TStream);
- var
- n: Integer;
- clName: AnsiString;
- begin
- with Stream do
- begin
- Read(n, SizeOf(Integer));
- SetLength(clName, n);
- if n > 0 then
- Read(clName[1], n);
- FData := TGLSoundFileClass(FindClass(string(clName))).Create(Self);
- FData.LoadFromStream(Stream);
- end;
- end;
- procedure TGLSoundSample.WriteData(Stream: TStream);
- var
- n: Integer;
- buf: AnsiString;
- begin
- with Stream do
- begin
- n := Length(FData.ClassName);
- Write(n, SizeOf(Integer));
- buf := AnsiString(FData.ClassName);
- if n > 0 then
- Write(buf[1], n);
- FData.SaveToStream(Stream);
- end;
- end;
- function TGLSoundSample.GetDisplayName: string;
- var
- s: string;
- begin
- if Assigned(FData) then
- begin
- if Data.Sampling.NbChannels > 1 then
- s := 's'
- else
- s := '';
- Result := Format('%s (%d Hz, %d bits, %d channel%s, %.2f sec)',
- [Name, Data.Sampling.Frequency,
- Data.Sampling.BitsPerSample,
- Data.Sampling.NbChannels, s, LengthInSec])
- end
- else
- Result := Format('%s (empty)', [Name]);
- end;
- procedure TGLSoundSample.LoadFromFile(const fileName: string);
- var
- sfc: TGLSoundFileClass;
- begin
- FData.Free;
- sfc := GetGLSoundFileFormats.FindExt(ExtractFileExt(fileName));
- if Assigned(sfc) then
- begin
- FData := sfc.Create(Self);
- FData.LoadFromFile(fileName);
- end
- else
- FData := nil;
- Assert(Data <> nil, 'Could not load ' + fileName +
- ', make sure you include the unit required to load this format in your uses clause.');
- Name := ExtractFileName(fileName);
- end;
- procedure TGLSoundSample.PlayOnWaveOut;
- begin
- if Assigned(FData) then
- FData.PlayOnWaveOut;
- end;
- function TGLSoundSample.Sampling: TGLSoundSampling;
- begin
- if Assigned(FData) then
- Result := FData.Sampling
- else
- Result := nil;
- end;
- function TGLSoundSample.LengthInBytes: Integer;
- begin
- if Assigned(FData) then
- Result := FData.LengthInBytes
- else
- Result := 0;
- end;
- function TGLSoundSample.LengthInSamples: Integer;
- begin
- if Assigned(FData) then
- Result := FData.LengthInSamples
- else
- Result := 0;
- end;
- function TGLSoundSample.LengthInSec: Single;
- begin
- if Assigned(FData) then
- Result := FData.LengthInSec
- else
- Result := 0;
- end;
- procedure TGLSoundSample.SetData(const val: TGLSoundFile);
- begin
- FData.Free;
- if Assigned(val) then
- FData := TGLSoundFile(val.CreateCopy(Self))
- else
- FData := nil;
- end;
- // ------------------
- // ------------------ TGLSoundSamples ------------------
- // ------------------
- constructor TGLSoundSamples.Create(AOwner: TComponent);
- begin
- Owner := AOwner;
- inherited Create(TGLSoundSample);
- end;
- function TGLSoundSamples.GetOwner: TPersistent;
- begin
- Result := Owner;
- end;
- procedure TGLSoundSamples.SetItems(index: Integer; const val: TGLSoundSample);
- begin
- inherited Items[index] := val;
- end;
- function TGLSoundSamples.GetItems(index: Integer): TGLSoundSample;
- begin
- Result := TGLSoundSample(inherited Items[index]);
- end;
- function TGLSoundSamples.Add: TGLSoundSample;
- begin
- Result := (inherited Add) as TGLSoundSample;
- end;
- function TGLSoundSamples.FindItemID(ID: Integer): TGLSoundSample;
- begin
- Result := (inherited FindItemID(ID)) as TGLSoundSample;
- end;
- function TGLSoundSamples.GetByName(const aName: string): TGLSoundSample;
- var
- i: Integer;
- begin
- Result := nil;
- for i := 0 to Count - 1 do
- if CompareText(Items[i].Name, aName) = 0 then
- begin
- Result := Items[i];
- Break;
- end;
- end;
- function TGLSoundSamples.AddFile(const fileName: string; const sampleName: string
- = ''): TGLSoundSample;
- begin
- Result := Add;
- Result.LoadFromFile(fileName);
- if sampleName <> '' then
- Result.Name := sampleName;
- end;
- // ------------------
- // ------------------ TGLSoundLibrary ------------------
- // ------------------
- constructor TGLSoundLibrary.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FSamples := TGLSoundSamples.Create(Self);
- vSoundLibraries.Add(Self);
- end;
- destructor TGLSoundLibrary.Destroy;
- begin
- vSoundLibraries.Remove(Self);
- FSamples.Free;
- inherited Destroy;
- end;
- procedure TGLSoundLibrary.Notification(AComponent: TComponent; Operation:
- TOperation);
- begin
- inherited;
- end;
- procedure TGLSoundLibrary.SetSamples(const val: TGLSoundSamples);
- begin
- FSamples.Assign(val);
- end;
- // ------------------
- // ------------------ TGLBaseSoundSource ------------------
- // ------------------
- constructor TGLBaseSoundSource.Create(Collection: TCollection);
- begin
- inherited Create(Collection);
- FChanges := [sscTransformation, sscSample, sscStatus];
- FVolume := 1.0;
- FMinDistance := 1.0;
- FMaxDistance := 100.0;
- FInsideConeAngle := 360;
- FOutsideConeAngle := 360;
- FConeOutsideVolume := 0.0;
- FNbLoops := 1;
- FFrequency := -1;
- end;
- destructor TGLBaseSoundSource.Destroy;
- begin
- inherited Destroy;
- end;
- function TGLBaseSoundSource.GetDisplayName: string;
- begin
- Result := Format('%s', [FSoundName]);
- end;
- procedure TGLBaseSoundSource.Assign(Source: TPersistent);
- begin
- if Source is TGLBaseSoundSource then
- begin
- FPriority := TGLBaseSoundSource(Source).FPriority;
- FOrigin := TGLBaseSoundSource(Source).FOrigin;
- FVolume := TGLBaseSoundSource(Source).FVolume;
- FMinDistance := TGLBaseSoundSource(Source).FMinDistance;
- FMaxDistance := TGLBaseSoundSource(Source).FMaxDistance;
- FInsideConeAngle := TGLBaseSoundSource(Source).FInsideConeAngle;
- FOutsideConeAngle := TGLBaseSoundSource(Source).FOutsideConeAngle;
- FConeOutsideVolume := TGLBaseSoundSource(Source).FConeOutsideVolume;
- FSoundLibraryName := TGLBaseSoundSource(Source).FSoundLibraryName;
- FSoundLibrary := TGLBaseSoundSource(Source).FSoundLibrary;
- FSoundName := TGLBaseSoundSource(Source).FSoundName;
- FMute := TGLBaseSoundSource(Source).FMute;
- FPause := TGLBaseSoundSource(Source).FPause;
- FChanges := [sscTransformation, sscSample, sscStatus];
- FNbLoops := TGLBaseSoundSource(Source).FNbLoops;
- FFrequency := TGLBaseSoundSource(Source).FFrequency;
- end
- else
- inherited Assign(Source);
- end;
- procedure TGLBaseSoundSource.WriteToFiler(writer: TWriter);
- begin
- inherited;
- with writer do
- begin
- WriteInteger(0); // Archive Version 0
- WriteInteger(FPriority);
- WriteFloat(FVolume);
- WriteFloat(FMinDistance);
- WriteFloat(FMaxDistance);
- WriteFloat(FInsideConeAngle);
- WriteFloat(FOutsideConeAngle);
- WriteFloat(FConeOutsideVolume);
- if Assigned(FSoundLibrary) then
- WriteString(FSoundLibrary.Name)
- else
- WriteString(FSoundLibraryName);
- WriteString(FSoundName);
- WriteBoolean(FMute);
- WriteBoolean(FPause);
- WriteInteger(FNbLoops);
- // WriteInteger(FFrequency);
- end;
- end;
- procedure TGLBaseSoundSource.ReadFromFiler(reader: TReader);
- begin
- inherited;
- with reader do
- begin
- ReadInteger; // ignore archiveVersion
- FPriority := ReadInteger;
- FVolume := ReadFloat;
- FMinDistance := ReadFloat;
- FMaxDistance := ReadFloat;
- FInsideConeAngle := ReadFloat;
- FOutsideConeAngle := ReadFloat;
- FConeOutsideVolume := ReadFloat;
- FSoundLibraryName := ReadString;
- FSoundLibrary := nil;
- FSoundName := ReadString;
- FMute := ReadBoolean;
- FPause := ReadBoolean;
- FChanges := [sscTransformation, sscSample, sscStatus];
- FNbLoops := ReadInteger;
- // FFrequency:=ReadInteger;
- end;
- end;
- function TGLBaseSoundSource.Sample: TGLSoundSample;
- begin
- if SoundLibrary <> nil then
- Result := FSoundLibrary.Samples.GetByName(FSoundName)
- else
- Result := nil;
- end;
- procedure TGLBaseSoundSource.SetPriority(const val: Integer);
- begin
- if val <> FPriority then
- begin
- FPriority := val;
- Include(FChanges, sscStatus);
- end;
- end;
- procedure TGLBaseSoundSource.SetOrigin(const val: TGLBaseSceneObject);
- begin
- if val <> FOrigin then
- begin
- FOrigin := val;
- Include(FChanges, sscTransformation);
- end;
- end;
- procedure TGLBaseSoundSource.SetVolume(const val: Single);
- begin
- if val <> FVolume then
- begin
- FVolume := ClampValue(val, 0, 1);
- Include(FChanges, sscStatus);
- end;
- end;
- procedure TGLBaseSoundSource.SetMinDistance(const val: Single);
- begin
- if val <> FMinDistance then
- begin
- FMinDistance := ClampValue(val, 0);
- Include(FChanges, sscStatus);
- end;
- end;
- procedure TGLBaseSoundSource.SetMaxDistance(const val: Single);
- begin
- if val <> FMaxDistance then
- begin
- FMaxDistance := ClampValue(val, 0);
- Include(FChanges, sscStatus);
- end;
- end;
- procedure TGLBaseSoundSource.SetInsideConeAngle(const val: Single);
- begin
- if val <> FInsideConeAngle then
- begin
- FInsideConeAngle := ClampValue(val, 0, 360);
- Include(FChanges, sscStatus);
- end;
- end;
- procedure TGLBaseSoundSource.SetOutsideConeAngle(const val: Single);
- begin
- if val <> FOutsideConeAngle then
- begin
- FOutsideConeAngle := ClampValue(val, 0, 360);
- Include(FChanges, sscStatus);
- end;
- end;
- procedure TGLBaseSoundSource.SetConeOutsideVolume(const val: Single);
- begin
- if val <> FConeOutsideVolume then
- begin
- FConeOutsideVolume := ClampValue(val, 0, 1);
- Include(FChanges, sscStatus);
- end;
- end;
- function TGLBaseSoundSource.GetSoundLibrary: TGLSoundLibrary;
- begin
- if (FSoundLibrary = nil) and (FSoundLibraryName <> '') then
- FSoundLibrary := GetSoundLibraryByName(FSoundLibraryName);
- Result := FSoundLibrary;
- end;
- procedure TGLBaseSoundSource.SetSoundLibrary(const val: TGLSoundLibrary);
- begin
- if val <> FSoundLibrary then
- begin
- FSoundLibrary := val;
- if Assigned(FSoundLibrary) then
- FSoundLibraryName := FSoundLibrary.Name
- else
- FSoundLibraryName := '';
- Include(FChanges, sscSample);
- end;
- end;
- procedure TGLBaseSoundSource.SetSoundName(const val: string);
- begin
- if val <> FSoundName then
- begin
- FSoundName := val;
- Include(FChanges, sscSample);
- end;
- end;
- procedure TGLBaseSoundSource.SetPause(const val: Boolean);
- begin
- if val <> FPause then
- begin
- FPause := val;
- if Collection <> nil then
- TGLSoundManager(TGLSoundSources(Collection).owner).PauseSource(Self, FPause);
- end;
- end;
- procedure TGLBaseSoundSource.SetNbLoops(const val: Integer);
- begin
- if val <> FNbLoops then
- begin
- FNbLoops := val;
- Include(FChanges, sscSample);
- end;
- end;
- procedure TGLBaseSoundSource.SetFrequency(const val: integer);
- begin
- if val <> FFrequency then
- begin
- FFrequency := val;
- Include(FChanges, sscStatus);
- end;
- end;
- procedure TGLBaseSoundSource.SetMute(const val: Boolean);
- begin
- if val <> FMute then
- begin
- FMute := val;
- if Collection <> nil then
- TGLSoundManager(TGLSoundSources(Collection).owner).MuteSource(Self,
- FMute);
- end;
- end;
- // ------------------
- // ------------------ TGLSoundSource ------------------
- // ------------------
- destructor TGLSoundSource.Destroy;
- begin
- if Assigned(FBehaviourToNotify) then
- FBehaviourToNotify.NotifySourceDestruction(Self);
- if Collection <> nil then
- ((Collection as TGLSoundSources).Owner as TGLSoundManager).KillSource(Self);
- inherited;
- end;
- // ------------------
- // ------------------ TGLSoundSources ------------------
- // ------------------
- constructor TGLSoundSources.Create(AOwner: TComponent);
- begin
- Owner := AOwner;
- inherited Create(TGLSoundSource);
- end;
- function TGLSoundSources.GetOwner: TPersistent;
- begin
- Result := Owner;
- end;
- procedure TGLSoundSources.SetItems(index: Integer; const val: TGLSoundSource);
- begin
- inherited Items[index] := val;
- end;
- function TGLSoundSources.GetItems(index: Integer): TGLSoundSource;
- begin
- Result := TGLSoundSource(inherited Items[index]);
- end;
- function TGLSoundSources.Add: TGLSoundSource;
- begin
- Result := (inherited Add) as TGLSoundSource;
- end;
- function TGLSoundSources.FindItemID(ID: Integer): TGLSoundSource;
- begin
- Result := (inherited FindItemID(ID)) as TGLSoundSource;
- end;
- // ------------------
- // ------------------ TGLSoundManager ------------------
- // ------------------
- constructor TGLSoundManager.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FSources := TGLSoundSources.Create(Self);
- FMasterVolume := 1.0;
- FOutputFrequency := 44100;
- FMaxChannels := 8;
- FUpdateFrequency := 10;
- FLastUpdateTime := -1e30;
- FDistanceFactor := 1.0;
- FRollOffFactor := 1.0;
- FDopplerFactor := 1.0;
- end;
- destructor TGLSoundManager.Destroy;
- begin
- Active := False;
- Listener := nil;
- FSources.Free;
- inherited Destroy;
- end;
- procedure TGLSoundManager.Notification(AComponent: TComponent; Operation:
- TOperation);
- begin
- if Operation = opRemove then
- begin
- if AComponent = FListener then
- Listener := nil;
- if AComponent = FCadencer then
- Cadencer := nil;
- end;
- inherited;
- end;
- procedure TGLSoundManager.SetActive(const val: Boolean);
- begin
- if (csDesigning in ComponentState) or (csLoading in ComponentState) then
- FActive := val
- else if val <> FActive then
- begin
- if val then
- begin
- if Assigned(vActiveSoundManager) then
- vActiveSoundManager.Active := False;
- if DoActivate then
- begin
- FActive := True;
- vActiveSoundManager := Self;
- end;
- end
- else
- begin
- try
- StopAllSources;
- DoDeActivate;
- finally
- FActive := val;
- vActiveSoundManager := nil;
- end;
- end;
- end;
- end;
- function TGLSoundManager.DoActivate: Boolean;
- begin
- Result := True;
- end;
- procedure TGLSoundManager.DoDeActivate;
- begin
- StopAllSources;
- end;
- procedure TGLSoundManager.SetMute(const val: Boolean);
- begin
- if val <> FMute then
- begin
- if val then
- begin
- if DoMute then
- FMute := True
- end
- else
- begin
- DoUnMute;
- FMute := False;
- end;
- end;
- end;
- function TGLSoundManager.DoMute: Boolean;
- var
- i: Integer;
- begin
- for i := 0 to Sources.Count - 1 do
- if not Sources[i].Mute then
- MuteSource(Sources[i], True);
- Result := True;
- end;
- procedure TGLSoundManager.DoUnMute;
- var
- i: Integer;
- begin
- for i := 0 to Sources.Count - 1 do
- if not Sources[i].Mute then
- MuteSource(Sources[i], False);
- end;
- procedure TGLSoundManager.SetPause(const val: Boolean);
- begin
- if val <> FPause then
- begin
- if val then
- begin
- if DoPause then
- FPause := True
- end
- else
- begin
- DoUnPause;
- FPause := False;
- end;
- end;
- end;
- procedure TGLSoundManager.Loaded;
- begin
- inherited;
- if Active and (not (csDesigning in ComponentState)) then
- begin
- FActive := False;
- Active := True;
- end;
- end;
- procedure TGLSoundManager.DefineProperties(Filer: TFiler);
- begin
- inherited;
- Filer.DefineProperty('Doppler', ReadDoppler, WriteDoppler, (DopplerFactor <>
- 1));
- end;
- procedure TGLSoundManager.WriteDoppler(writer: TWriter);
- begin
- writer.WriteFloat(DopplerFactor);
- end;
- procedure TGLSoundManager.ReadDoppler(reader: TReader);
- begin
- FDopplerFactor := reader.ReadFloat;
- end;
- function TGLSoundManager.DoPause: Boolean;
- var
- i: Integer;
- begin
- for i := 0 to Sources.Count - 1 do
- if not Sources[i].Pause then
- PauseSource(Sources[i], True);
- Result := True;
- end;
- procedure TGLSoundManager.DoUnPause;
- var
- i: Integer;
- begin
- for i := 0 to Sources.Count - 1 do
- if not Sources[i].Pause then
- PauseSource(Sources[i], False);
- end;
- procedure TGLSoundManager.SetMasterVolume(const val: Single);
- begin
- if val < 0 then
- FMasterVolume := 0
- else if val > 1 then
- FMasterVolume := 1
- else
- FMasterVolume := val;
- NotifyMasterVolumeChange;
- end;
- procedure TGLSoundManager.SetMaxChannels(const val: Integer);
- begin
- if val <> FMaxChannels then
- begin
- if val < 1 then
- FMaxChannels := 1
- else
- FMaxChannels := val;
- end;
- end;
- procedure TGLSoundManager.SetOutputFrequency(const val: Integer);
- begin
- if val <> FOutputFrequency then
- begin
- if val < 11025 then
- FOutputFrequency := 11025
- else
- FOutputFrequency := val;
- end;
- end;
- procedure TGLSoundManager.SetUpdateFrequency(const val: Single);
- begin
- FUpdateFrequency := ClampValue(val, 1, 60);
- end;
- function TGLSoundManager.StoreUpdateFrequency: Boolean;
- begin
- Result := (FUpdateFrequency <> 10);
- end;
- procedure TGLSoundManager.SetCadencer(const val: TGLCadencer);
- begin
- if val <> FCadencer then
- begin
- if Assigned(FCadencer) then
- FCadencer.UnSubscribe(Self);
- FCadencer := val;
- if Assigned(FCadencer) then
- FCadencer.Subscribe(Self);
- end;
- end;
- procedure TGLSoundManager.SetDistanceFactor(const val: Single);
- begin
- if val <= 0 then
- FDistanceFactor := 1
- else
- FDistanceFactor := val;
- Notify3DFactorsChanged;
- end;
- function TGLSoundManager.StoreDistanceFactor: Boolean;
- begin
- Result := (FDistanceFactor <> 1);
- end;
- procedure TGLSoundManager.SetRollOffFactor(const val: Single);
- begin
- if val <= 0 then
- FRollOffFactor := 1
- else
- FRollOffFactor := val;
- Notify3DFactorsChanged;
- end;
- function TGLSoundManager.StoreRollOffFactor: Boolean;
- begin
- Result := (FRollOffFactor <> 1);
- end;
- procedure TGLSoundManager.SetDopplerFactor(const val: Single);
- begin
- if val < 0 then
- FDopplerFactor := 0
- else if val > 10 then
- FDopplerFactor := 10
- else
- FDopplerFactor := val;
- Notify3DFactorsChanged;
- end;
- procedure TGLSoundManager.SetSoundEnvironment(const val: TGLSoundEnvironment);
- begin
- if val <> FSoundEnvironment then
- begin
- FSoundEnvironment := val;
- NotifyEnvironmentChanged;
- end;
- end;
- procedure TGLSoundManager.ListenerCoordinates(var position, velocity, direction,
- up: TVector);
- var
- right: TVector;
- begin
- if Listener <> nil then
- begin
- position := Listener.AbsolutePosition;
- if FLastDeltaTime <> 0 then
- begin
- velocity := VectorSubtract(position, FLastListenerPosition);
- ScaleVector(velocity, 1 / FLastDeltaTime);
- end;
- FLastListenerPosition := position;
- if (Listener is TGLCamera) and (TGLCamera(Listener).TargetObject <> nil)
- then
- begin
- // special case of the camera targeting something
- direction := TGLCamera(Listener).AbsoluteVectorToTarget;
- NormalizeVector(direction);
- up := Listener.AbsoluteYVector;
- right := VectorCrossProduct(direction, up);
- up := VectorCrossProduct(right, direction);
- end
- else
- begin
- direction := Listener.AbsoluteZVector;
- up := Listener.AbsoluteYVector;
- end;
- end
- else
- begin
- position := NullHmgPoint;
- velocity := NullHmgVector;
- direction := ZHmgVector;
- up := YHmgVector;
- end;
- end;
- procedure TGLSoundManager.NotifyMasterVolumeChange;
- begin
- // nothing
- end;
- procedure TGLSoundManager.Notify3DFactorsChanged;
- begin
- // nothing
- end;
- procedure TGLSoundManager.NotifyEnvironmentChanged;
- begin
- // nothing
- end;
- procedure TGLSoundManager.SetListener(const val: TGLBaseSceneObject);
- begin
- if Assigned(FListener) then
- FListener.RemoveFreeNotification(Self);
- FListener := val;
- if Assigned(FListener) then
- FListener.FreeNotification(Self);
- end;
- procedure TGLSoundManager.SetSources(const val: TGLSoundSources);
- begin
- FSources.Assign(val);
- end;
- procedure TGLSoundManager.KillSource(aSource: TGLBaseSoundSource);
- begin
- // nothing
- end;
- procedure TGLSoundManager.UpdateSource(aSource: TGLBaseSoundSource);
- begin
- aSource.FChanges := [];
- end;
- procedure TGLSoundManager.MuteSource(aSource: TGLBaseSoundSource; muted: Boolean);
- begin
- // nothing
- end;
- procedure TGLSoundManager.PauseSource(aSource: TGLBaseSoundSource; paused: Boolean);
- begin
- // nothing
- end;
- procedure TGLSoundManager.UpdateSources;
- var
- i: Integer;
- begin
- for i := Sources.Count - 1 downto 0 do
- UpdateSource(Sources[i]);
- end;
- procedure TGLSoundManager.StopAllSources;
- var
- i: Integer;
- begin
- for i := Sources.Count - 1 downto 0 do
- Sources.Delete(i);
- end;
- procedure TGLSoundManager.DoProgress(const progressTime: TGLProgressTimes);
- begin
- if not Active then
- Exit;
- with progressTime do
- if newTime - FLastUpdateTime > 1 / FUpdateFrequency then
- begin
- FLastDeltaTime := newTime - FLastUpdateTime;
- FLastUpdateTime := newTime;
- UpdateSources;
- end;
- end;
- function TGLSoundManager.CPUUsagePercent: Single;
- begin
- Result := -1;
- end;
- function TGLSoundManager.EAXSupported: Boolean;
- begin
- Result := False;
- end;
- // ------------------
- // ------------------ TGLBSoundEmitter ------------------
- // ------------------
- constructor TGLBSoundEmitter.Create(aOwner: TXCollection);
- begin
- inherited Create(aOwner);
- FSource := TGLSoundSource.Create(nil);
- end;
-
- destructor TGLBSoundEmitter.Destroy;
- begin
- if Assigned(FPlayingSource) then
- FPlayingSource.Free;
- FSource.Free;
- inherited Destroy;
- end;
- procedure TGLBSoundEmitter.Assign(Source: TPersistent);
- begin
- if Source is TGLBSoundEmitter then
- begin
- FSource.Assign(TGLBSoundEmitter(Source).FSource);
- end;
- inherited Assign(Source);
- end;
- procedure TGLBSoundEmitter.WriteToFiler(writer: TWriter);
- begin
- inherited;
- with writer do
- begin
- WriteInteger(0); // Archive Version 0
- FSource.WriteToFiler(writer);
- WriteBoolean(FPlaying);
- end;
- end;
- procedure TGLBSoundEmitter.ReadFromFiler(reader: TReader);
- begin
- inherited;
- with reader do
- begin
- ReadInteger; // ignore archiveVersion
- FSource.ReadFromFiler(reader);
- FPlaying := ReadBoolean;
- end;
- end;
- procedure TGLBSoundEmitter.Loaded;
- begin
- inherited;
- if not (csDesigning in OwnerBaseSceneObject.ComponentState) then
- SetPlaying(FPlaying);
- end;
-
- class function TGLBSoundEmitter.FriendlyName: string;
- begin
- Result := 'Sound Emitter';
- end;
- class function TGLBSoundEmitter.FriendlyDescription: string;
- begin
- Result := 'A simple sound emitter behaviour';
- end;
- class function TGLBSoundEmitter.UniqueItem: Boolean;
- begin
- Result := False;
- end;
- procedure TGLBSoundEmitter.DoProgress(const progressTime: TGLProgressTimes);
- begin
- // nothing, yet
- end;
- procedure TGLBSoundEmitter.SetSource(const val: TGLBaseSoundSource);
- begin
- FSource.Assign(val);
- end;
- procedure TGLBSoundEmitter.SetPlaying(const val: Boolean);
- begin
- if csDesigning in OwnerBaseSceneObject.ComponentState then
- FPlaying := val
- else if ActiveSoundManager <> nil then
- begin
- if val <> Playing then
- begin
- if val then
- begin
- FPlayingSource := ActiveSoundManager.Sources.Add;
- FPlayingSource.FBehaviourToNotify := Self;
- FPlayingSource.Assign(FSource);
- FPlayingSource.Origin := OwnerBaseSceneObject;
- end
- else
- FPlayingSource.Free;
- end;
- end
- else if vVerboseGLSMErrors then
- InformationDlg('No Active Sound Manager.'#13#10'Make sure manager is created before emitter');
- end;
- function TGLBSoundEmitter.GetPlaying: Boolean;
- begin
- if csDesigning in OwnerBaseSceneObject.ComponentState then
- Result := FPlaying
- else
- Result := Assigned(FPlayingSource);
- end;
- procedure TGLBSoundEmitter.NotifySourceDestruction(aSource: TGLSoundSource);
- begin
- Assert(FPlayingSource = aSource);
- FPlayingSource := nil;
- end;
- // ------------------------------------------------------------------
- initialization
- // ------------------------------------------------------------------
- // class registrations
- RegisterClasses([TGLSoundLibrary]);
- RegisterXCollectionItemClass(TGLBSoundEmitter);
- vSoundLibraries := TList.Create;
- // ------------------------------------------------------------------
- finalization
- // ------------------------------------------------------------------
- if Assigned(vActiveSoundManager) then
- vActiveSoundManager.Active := False;
- vSoundLibraries.Free;
- vSoundLibraries := nil;
- UnregisterXCollectionItemClass(TGLBSoundEmitter);
- end.
|