LZScene

Форк
0
/
GLFileWAV.pas 
227 строк · 5.9 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
   Support for Windows WAV format.
6

7
	 History :  
8
       17/11/09 - DaStr - Improved Unix compatibility
9
                             (thanks Predator) (BugtrackerID = 2893580)
10
       25/07/09 - DaStr - Added $I GLScene.inc
11
       26/05/09 - DanB - Fix for LengthInBytes when chunks occur after data chunk
12
       06/05/09 - DanB - Creation from split from GLSoundFileObjects.pas
13
	 
14
}
15
unit GLFileWAV;
16

17
interface
18

19
{$I GLScene.inc}
20

21
uses
22
  Classes, GLApplicationFileIO, GLSoundFileObjects{$IFDEF MSWINDOWS} ,MMSystem{$ENDIF};
23

24
type
25

26
   // TGLWAVFile
27
   //
28
   { Support for Windows WAV format. }
29
   TGLWAVFile = class (TGLSoundFile)
30
      private
31
          
32
         {$IFDEF MSWINDOWS}
33
         waveFormat : TWaveFormatEx;
34
         pcmOffset : Integer;
35
         {$ENDIF}
36
         FPCMDataLength: Integer;
37
         data : array of Byte; // used to store WAVE bitstream
38

39
      protected
40
          
41

42
      public
43
          
44
         function CreateCopy(AOwner: TPersistent) : TGLDataFile; override;
45

46
         class function Capabilities : TGLDataFileCapabilities; override;
47

48
         procedure LoadFromStream(Stream: TStream); override;
49
         procedure SaveToStream(Stream: TStream); override;
50

51
         procedure PlayOnWaveOut; override;
52

53
	      function WAVData : Pointer; override;
54
         function WAVDataSize : Integer; override;
55
	      function PCMData : Pointer; override;
56
	      function LengthInBytes : Integer; override;
57
   end;
58

59
implementation
60

61
 {$IFDEF MSWINDOWS}
62
type
63
   TRIFFChunkInfo = packed record
64
      ckID : FOURCC;
65
      ckSize : LongInt;
66
   end;
67

68
const
69
  WAVE_Format_ADPCM = 2;
70
  {$ENDIF}
71
// ------------------
72
// ------------------ TGLWAVFile ------------------
73
// ------------------
74

75
// CreateCopy
76
//
77
function TGLWAVFile.CreateCopy(AOwner: TPersistent) : TGLDataFile;
78
begin
79
   Result:=inherited CreateCopy(AOwner);
80
   if Assigned(Result) then begin
81
      {$IFDEF MSWINDOWS}
82
      TGLWAVFile(Result).waveFormat:=waveFormat;
83
      {$ENDIF}
84
      TGLWAVFile(Result).data := Copy(data);
85
   end;
86
end;
87

88
// Capabilities
89
//
90
class function TGLWAVFile.Capabilities : TGLDataFileCapabilities;
91
begin
92
   Result:=[dfcRead, dfcWrite];
93
end;
94

95
// LoadFromStream
96
//
97
procedure TGLWAVFile.LoadFromStream(stream : TStream);
98
{$IFDEF MSWINDOWS}
99
var
100
   ck : TRIFFChunkInfo;
101
   dw, bytesToGo, startPosition, totalSize : Integer;
102
   id : Cardinal;
103
   dwDataOffset, dwDataSamples, dwDataLength : Integer;
104
begin
105
   // this WAVE loading code is an adaptation of the 'minimalist' sample from
106
   // the Microsoft DirectX SDK.
107
   Assert(Assigned(stream));
108
   dwDataOffset:=0;
109
   dwDataLength:=0;
110
   dwDataSamples := 0;
111
   // Check RIFF Header
112
   startPosition:=stream.Position;
113
   stream.Read(ck, SizeOf(TRIFFChunkInfo));
114
   Assert((ck.ckID=mmioStringToFourCC('RIFF',0)), 'RIFF required');
115
   totalSize:=ck.ckSize+SizeOf(TRIFFChunkInfo);
116
   stream.Read(id, SizeOf(Integer));
117
   Assert((id=mmioStringToFourCC('WAVE',0)), 'RIFF-WAVE required');
118
   // lookup for 'fmt '
119
   repeat
120
      stream.Read(ck, SizeOf(TRIFFChunkInfo));
121
      bytesToGo:=ck.ckSize;
122
      if (ck.ckID = mmioStringToFourCC('fmt ',0)) then begin
123
         if waveFormat.wFormatTag=0 then begin
124
            dw:=ck.ckSize;
125
            if dw>SizeOf(TWaveFormatEx) then
126
               dw:=SizeOf(TWaveFormatEx);
127
            stream.Read(waveFormat, dw);
128
            bytesToGo:=ck.ckSize-dw;
129
         end;
130
         // other 'fmt ' chunks are ignored (?)
131
      end else if (ck.ckID = mmioStringToFourCC('fact',0)) then begin
132
         if (dwDataSamples = 0) and (waveFormat.wFormatTag = WAVE_Format_ADPCM) then begin
133
            stream.Read(dwDataSamples, SizeOf(LongInt));
134
            Dec(bytesToGo, SizeOf(LongInt));
135
         end;
136
         // other 'fact' chunks are ignored (?)
137
      end else if (ck.ckID = mmioStringToFourCC('data',0)) then begin
138
         dwDataOffset:=stream.Position-startPosition;
139
         dwDataLength := ck.ckSize;
140
         Break;
141
      end;
142
      // all other sub-chunks are ignored, move to the next chunk
143
      stream.Seek(bytesToGo, soFromCurrent);
144
   until Stream.Position = 2048; // this should never be reached
145
   // Only PCM wave format is recognized
146
//   Assert((waveFormat.wFormatTag=Wave_Format_PCM), 'PCM required');
147
   // seek start of data
148
   pcmOffset:=dwDataOffset;
149
   FPCMDataLength:=dwDataLength;
150
   SetLength(data, totalSize);
151
   stream.Position:=startPosition;
152
   if totalSize>0 then
153
      stream.Read(data[0], totalSize);
154
   // update Sampling data
155
   with waveFormat do begin
156
      Sampling.Frequency:=nSamplesPerSec;
157
      Sampling.NbChannels:=nChannels;
158
      Sampling.BitsPerSample:=wBitsPerSample;
159
   end;
160
{$ELSE}
161
begin
162
   Assert(Assigned(stream));
163
   SetLength(data, stream.Size);
164
   if Length(data)>0 then
165
      stream.Read(data[0], Length(data));
166
{$ENDIF}
167
end;
168

169
// SaveToStream
170
//
171
procedure TGLWAVFile.SaveToStream(stream: TStream);
172
begin
173
   if Length(data)>0 then
174
      stream.Write(data[0], Length(data));
175
end;
176

177
// PlayOnWaveOut
178
//
179
procedure TGLWAVFile.PlayOnWaveOut;
180
begin
181
{$IFDEF MSWINDOWS}
182
   PlaySound(WAVData, 0, SND_ASYNC+SND_MEMORY);
183
{$ENDIF}
184
//   GLSoundFileObjects.PlayOnWaveOut(PCMData, LengthInBytes, waveFormat);
185
end;
186

187
// WAVData
188
//
189
function TGLWAVFile.WAVData : Pointer;
190
begin
191
   if Length(data)>0 then
192
      Result:=@data[0]
193
   else Result:=nil;
194
end;
195

196
// WAVDataSize
197
//
198
function TGLWAVFile.WAVDataSize : Integer;
199
begin
200
   Result:=Length(data);
201
end;
202

203
// PCMData
204
//
205
function TGLWAVFile.PCMData : Pointer;
206
begin
207
{$IFDEF MSWINDOWS}
208
   if Length(data)>0 then
209
      Result:=@data[pcmOffset]
210
   else Result:=nil;
211
{$ELSE}
212
   Result:=nil;
213
{$ENDIF}
214
end;
215

216
// LengthInBytes
217
//
218
function TGLWAVFile.LengthInBytes : Integer;
219
begin
220
   Result:=FPCMDataLength;
221
end;
222

223
initialization
224

225
  RegisterSoundFileFormat('wav', 'Windows WAV files', TGLWAVFile);
226

227
end.
228

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.