| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- //
- // This unit is part of the GLScene Engine, http://glscene.org
- //
- unit GLSoundFileObjects;
- (*
- Support classes for loading various fileformats.
- These classes work together like vector file formats or Delphi's TGraphic classes.
- *)
- interface
- {$I GLScene.inc}
- uses
- Winapi.MMSystem,
- System.Classes,
- System.SysUtils,
- VCL.Consts,
- GLApplicationFileIO,
- GLCrossPlatform;
- type
- {Defines a sound sampling quality. }
- TGLSoundSampling = class (TPersistent)
- private
- FOwner : TPersistent;
- FFrequency : Integer;
- FNbChannels : Integer;
- FBitsPerSample : Integer;
- protected
- function GetOwner : TPersistent; override;
- public
- constructor Create(AOwner: TPersistent);
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- function BytesPerSec : Integer;
- function BytesPerSample : Integer;
- function WaveFormat : TWaveFormatEx;
- published
- {Sampling frequency in Hz (= samples per sec) }
- property Frequency : Integer read FFrequency write FFrequency default 22050;
- {Nb of sampling channels.
- 1 = mono, 2 = stereo, etc. }
- property NbChannels : Integer read FNbChannels write FNbChannels default 1;
- {Nb of bits per sample.
- Common values are 8 and 16 bits. }
- property BitsPerSample : Integer read FBitsPerSample write FBitsPerSample default 8;
- end;
- {Abstract base class for different Sound file formats.
- The actual implementation for these files (WAV, RAW...) must be done
- seperately. The concept for TGLSoundFile is very similar to TGraphic
- (see Delphi Help).
- Default implementation for LoadFromFile/SaveToFile are to directly call the
- relevent stream-based methods, ie. you will just have to override the stream
- methods in most cases. }
- TGLSoundFile = class (TGLDataFile)
- private
- FSampling : TGLSoundSampling;
- protected
- procedure SetSampling(const val : TGLSoundSampling);
- public
- constructor Create(AOwner: TPersistent); override;
- destructor Destroy; override;
- procedure PlayOnWaveOut; virtual;
- {Returns a pointer to the sample data viewed as an in-memory WAV File. }
- function WAVData : Pointer; virtual; abstract;
- {Returns the size (in bytes) of the WAVData. }
- function WAVDataSize : Integer; virtual; abstract;
- {Returns a pointer to the sample data viewed as an in-memory PCM buffer. }
- function PCMData : Pointer; virtual; abstract;
- {Length of PCM data, in bytes. }
- function LengthInBytes : Integer; virtual; abstract;
- {Nb of intensity samples in the sample. }
- function LengthInSamples : Integer;
- {Length of play of the sample at nominal speed in seconds. }
- function LengthInSec : Single;
- property Sampling : TGLSoundSampling read FSampling write SetSampling;
- end;
- TGLSoundFileClass = class of TGLSoundFile;
- TGLSoundFileFormat = record
- SoundFileClass : TGLSoundFileClass;
- Extension : String;
- Description : String;
- DescResID : Integer;
- end;
- PSoundFileFormat = ^TGLSoundFileFormat;
- TGLSoundFileFormatsList = class(TList)
- public
- destructor Destroy; override;
- procedure Add(const Ext, Desc: String; DescID: Integer; AClass: TGLSoundFileClass);
- function FindExt(Ext: string): TGLSoundFileClass;
- procedure Remove(AClass: TGLSoundFileClass);
- procedure BuildFilterStrings(SoundFileClass: TGLSoundFileClass; out Descriptions, Filters: string);
- end;
- function GetGLSoundFileFormats : TGLSoundFileFormatsList;
- procedure RegisterSoundFileFormat(const AExtension, ADescription: String; AClass: TGLSoundFileClass);
- procedure UnregisterSoundFileClass(AClass: TGLSoundFileClass);
- // ------------------------------------------------------------------
- implementation
- // ------------------------------------------------------------------
- var
- vSoundFileFormats : TGLSoundFileFormatsList;
- function GetGLSoundFileFormats : TGLSoundFileFormatsList;
- begin
- if not Assigned(vSoundFileFormats)then
- vSoundFileFormats := TGLSoundFileFormatsList.Create;
- Result := vSoundFileFormats;
- end;
- procedure RegisterSoundFileFormat(const AExtension, ADescription: String; AClass: TGLSoundFileClass);
- begin
- RegisterClass(AClass);
- GetGLSoundFileFormats.Add(AExtension, ADescription, 0, AClass);
- end;
- procedure UnregisterSoundFileClass(AClass: TGLSoundFileClass);
- begin
- if Assigned(vSoundFileFormats) then
- vSoundFileFormats.Remove(AClass);
- end;
- // ------------------
- // ------------------ TGLSoundSampling ------------------
- // ------------------
- constructor TGLSoundSampling.Create(AOwner: TPersistent);
- begin
- inherited Create;
- FOwner:=AOwner;
- FFrequency:=22050;
- FNbChannels:=1;
- FBitsPerSample:=8;
- end;
- destructor TGLSoundSampling.Destroy;
- begin
- inherited Destroy;
- end;
- procedure TGLSoundSampling.Assign(Source: TPersistent);
- begin
- if Source is TGLSoundSampling then begin
- FFrequency:=TGLSoundSampling(Source).Frequency;
- FNbChannels:=TGLSoundSampling(Source).NbChannels;
- FBitsPerSample:=TGLSoundSampling(Source).BitsPerSample;
- end else inherited;
- end;
- function TGLSoundSampling.GetOwner : TPersistent;
- begin
- Result:=FOwner;
- end;
- function TGLSoundSampling.BytesPerSec : Integer;
- begin
- Result:=(FFrequency*FBitsPerSample*FNbChannels) shr 3;
- end;
- function TGLSoundSampling.BytesPerSample : Integer;
- begin
- Result:=FBitsPerSample shr 3;
- end;
- function TGLSoundSampling.WaveFormat : TWaveFormatEx;
- begin
- Result.nSamplesPerSec:=Frequency;
- Result.nChannels:=NbChannels;
- Result.wFormatTag:=Wave_Format_PCM;
- Result.nAvgBytesPerSec:=BytesPerSec;
- Result.wBitsPerSample:=BitsPerSample;
- Result.nBlockAlign:=NbChannels*BytesPerSample;
- Result.cbSize:=0;
- end;
- // ------------------
- // ------------------ TGLSoundFile ------------------
- // ------------------
- constructor TGLSoundFile.Create(AOwner: TPersistent);
- begin
- inherited;
- FSampling:=TGLSoundSampling.Create(Self);
- end;
- destructor TGLSoundFile.Destroy;
- begin
- FSampling.Free;
- inherited;
- end;
- procedure TGLSoundFile.SetSampling(const val : TGLSoundSampling);
- begin
- FSampling.Assign(val);
- end;
- procedure TGLSoundFile.PlayOnWaveOut;
- begin
- // GLSoundFileObjects.PlayOnWaveOut(PCMData, LengthInSamples, Sampling);
- end;
- function TGLSoundFile.LengthInSamples : Integer;
- var
- d : Integer;
- begin
- d:=Sampling.BytesPerSample*Sampling.NbChannels;
- if d>0 then
- Result:=LengthInBytes div d
- else Result:=0;
- end;
- function TGLSoundFile.LengthInSec : Single;
- begin
- Result:=LengthInBytes/Sampling.BytesPerSec;
- end;
- // ------------------
- // ------------------ TGLSoundFileFormatsList ------------------
- // ------------------
- destructor TGLSoundFileFormatsList.Destroy;
- var
- i : Integer;
- begin
- for i:=0 to Count-1 do Dispose(PSoundFileFormat(Items[i]));
- inherited;
- end;
- procedure TGLSoundFileFormatsList.Add(const Ext, Desc: String; DescID: Integer;
- AClass: TGLSoundFileClass);
- var
- newRec: PSoundFileFormat;
- begin
- New(newRec);
- with newRec^ do begin
- Extension := AnsiLowerCase(Ext);
- SoundFileClass := AClass;
- Description := Desc;
- DescResID := DescID;
- end;
- inherited Add(NewRec);
- end;
- function TGLSoundFileFormatsList.FindExt(Ext: string): TGLSoundFileClass;
- var
- i : Integer;
- begin
- Ext := AnsiLowerCase(Ext);
- for I := Count-1 downto 0 do with PSoundFileFormat(Items[I])^ do
- if (Extension = Ext) or ('.'+Extension = Ext) then begin
- Result := SoundFileClass;
- Exit;
- end;
- Result := nil;
- end;
- procedure TGLSoundFileFormatsList.Remove(AClass: TGLSoundFileClass);
- var
- i : Integer;
- p : PSoundFileFormat;
- begin
- for I := Count-1 downto 0 do begin
- P := PSoundFileFormat(Items[I]);
- if P^.SoundFileClass.InheritsFrom(AClass) then begin
- Dispose(P);
- Delete(I);
- end;
- end;
- end;
- procedure TGLSoundFileFormatsList.BuildFilterStrings(SoundFileClass: TGLSoundFileClass;
- out Descriptions, Filters: string);
- var
- c, i : Integer;
- p : PSoundFileFormat;
- begin
- Descriptions := '';
- Filters := '';
- C := 0;
- for I := Count-1 downto 0 do begin
- P := PSoundFileFormat(Items[I]);
- if P^.SoundFileClass.InheritsFrom(SoundFileClass) and (P^.Extension <> '') then
- with P^ do begin
- if C <> 0 then begin
- Descriptions := Descriptions+'|';
- Filters := Filters+';';
- end;
- if (Description = '') and (DescResID <> 0) then
- Description := LoadStr(DescResID);
- FmtStr(Descriptions, '%s%s (*.%s)|*.%2:s',
- [Descriptions, Description, Extension]);
- FmtStr(Filters, '%s*.%s', [Filters, Extension]);
- Inc(C);
- end;
- end;
- if C > 1 then
- FmtStr(Descriptions, '%s (%s)|%1:s|%s', [sAllFilter, Filters, Descriptions]);
- end;
- // ------------------------------------------------------------------
- initialization
- // ------------------------------------------------------------------
- finalization
- FreeAndNil(vSoundFileFormats);
- end.
|