xue@0
|
1 /*
|
xue@0
|
2 Harmonic Visualiser
|
xue@0
|
3
|
xue@0
|
4 An audio file viewer and editor.
|
xue@0
|
5 Centre for Digital Music, Queen Mary, University of London.
|
xue@0
|
6 This file copyright 2011 Wen Xue.
|
xue@0
|
7
|
xue@0
|
8 This program is free software; you can redistribute it and/or
|
xue@0
|
9 modify it under the terms of the GNU General Public License as
|
xue@0
|
10 published by the Free Software Foundation; either version 2 of the
|
xue@0
|
11 License, or (at your option) any later version.
|
xue@0
|
12 */
|
xue@0
|
13 //---------------------------------------------------------------------------
|
xue@0
|
14 #include <vcl.h>
|
xue@0
|
15 #pragma hdrstop
|
xue@0
|
16
|
xue@0
|
17 #include "AudioPac.h"
|
xue@0
|
18 #include <math.h>
|
xue@0
|
19
|
xue@0
|
20 #pragma package(smart_init)
|
xue@0
|
21 //---------------------------------------------------------------------------
|
xue@0
|
22 void DoubleToInt(void* out, int BytesPerSample, double* in, int Count)
|
xue@0
|
23 {
|
xue@0
|
24 if (BytesPerSample==1){unsigned char* out8=(unsigned char*)out; for (int k=0; k<Count; k++) *(out8++)=*(in++)+128.5;}
|
xue@0
|
25 else if (BytesPerSample==2) {__int16* out16=(__int16*)out; for (int k=0; k<Count; k++) *(out16++)=floor(*(in++)+0.5);}
|
xue@0
|
26 else {__pint24 out24=(__pint24)out; for (int k=0; k<Count; k++) {*(out24++)=floor(*(in++)+0.5);}}
|
xue@0
|
27 }
|
xue@0
|
28
|
xue@0
|
29 void IntToDouble(double* out, void* in, int BytesPerSample, int Count)
|
xue@0
|
30 {
|
xue@0
|
31 if (BytesPerSample==1){unsigned char* in8=(unsigned char*)in; for (int k=0; k<Count; k++) *(out++)=*(in8++)-128.0;}
|
xue@0
|
32 else if (BytesPerSample==2) {__int16* in16=(__int16*)in; for (int k=0; k<Count; k++) *(out++)=*(in16++);}
|
xue@0
|
33 else {__pint24 in24=(__pint24)in; for (int k=0; k<Count; k++) {*(out++)=*(in24++);}}
|
xue@0
|
34 }
|
xue@0
|
35
|
xue@0
|
36 void DoubleToIntInterleave(void* out, int BytesPerSample, double* in1, double* in2, int Count)
|
xue@0
|
37 {
|
xue@0
|
38 if (BytesPerSample==1)
|
xue@0
|
39 {
|
xue@0
|
40 unsigned char* out8=(unsigned char*)out;
|
xue@0
|
41 for (int k=0; k<Count; k++) {*(out8++)=*(in1++)+128; *(out8++)=*(in2++)+128;}
|
xue@0
|
42 }
|
xue@0
|
43 else if (BytesPerSample==2)
|
xue@0
|
44 {
|
xue@0
|
45 __int16* out16=(__int16*)out;
|
xue@0
|
46 for (int k=0; k<Count; k++) {*(out16++)=*(in1++); *(out16++)=*(in2++);}
|
xue@0
|
47 }
|
xue@0
|
48 else if (BytesPerSample==3)
|
xue@0
|
49 {
|
xue@0
|
50 __pint24 out24=(__pint24)out;
|
xue@0
|
51 for (int k=0; k<Count; k++) {*(out24++)=*(in1++); *(out24++)=*(in2++); }
|
xue@0
|
52 }
|
xue@0
|
53 }
|
xue@0
|
54
|
xue@0
|
55 void IntToDoubleInterleave(double* out1, double* out2, void* in, int BytesPerSample, int Count)
|
xue@0
|
56 {
|
xue@0
|
57 if (BytesPerSample==1)
|
xue@0
|
58 {
|
xue@0
|
59 unsigned char* in8=(unsigned char*)in;
|
xue@0
|
60 for (int k=0; k<Count; k++) {*(out1++)=*(in8++)-128.0; *(out2++)=*(in8++)-128.0;}
|
xue@0
|
61 }
|
xue@0
|
62 else if (BytesPerSample==2)
|
xue@0
|
63 {
|
xue@0
|
64 __int16* in16=(__int16*)in;
|
xue@0
|
65 for (int k=0; k<Count; k++) {*(out1++)=*(in16++); *(out2++)=*(in16++);}
|
xue@0
|
66 }
|
xue@0
|
67 else if (BytesPerSample==3)
|
xue@0
|
68 {
|
xue@0
|
69 __pint24 in24=(__pint24)in;
|
xue@0
|
70 for (int k=0; k<Count; k++) {*(out1++)=*(in24++); *(out2++)=*(in24++);}
|
xue@0
|
71 }
|
xue@0
|
72 }
|
xue@0
|
73
|
xue@0
|
74 int IntToIntInterleave(void* dest, int bytesperunit, void* block1, void* block2, int Count)
|
xue@0
|
75 {
|
xue@0
|
76 if (bytesperunit==1)
|
xue@0
|
77 {
|
xue@0
|
78 char* Dest=(char*)dest;
|
xue@0
|
79 char* Block1=(char*)block1;
|
xue@0
|
80 char* Block2=(char*)block2;
|
xue@0
|
81 for (int i=0; i<Count; i++)
|
xue@0
|
82 {
|
xue@0
|
83 *(Dest++)=*(Block1++);
|
xue@0
|
84 *(Dest++)=*(Block2++);
|
xue@0
|
85 }
|
xue@0
|
86 return 2*Count;
|
xue@0
|
87 }
|
xue@0
|
88 else if (bytesperunit==2)
|
xue@0
|
89 {
|
xue@0
|
90 __int16* Dest=(__int16*)dest;
|
xue@0
|
91 __int16* Block1=(__int16*)block1;
|
xue@0
|
92 __int16* Block2=(__int16*)block2;
|
xue@0
|
93 for (int i=0; i<Count; i++)
|
xue@0
|
94 {
|
xue@0
|
95 *(Dest++)=*(Block1++);
|
xue@0
|
96 *(Dest++)=*(Block2++);
|
xue@0
|
97 }
|
xue@0
|
98 return 4*Count;
|
xue@0
|
99 }
|
xue@0
|
100 else if (bytesperunit==3)
|
xue@0
|
101 {
|
xue@0
|
102 __pint24 Dest=(__pint24)dest;
|
xue@0
|
103 __pint24 Block1=(__pint24)block1;
|
xue@0
|
104 __pint24 Block2=(__pint24)block2;
|
xue@0
|
105 for (int i=0; i<Count; i++)
|
xue@0
|
106 {
|
xue@0
|
107 *(Dest++)=*(Block1++);
|
xue@0
|
108 *(Dest++)=*(Block2++);
|
xue@0
|
109 }
|
xue@0
|
110 return 6*Count;
|
xue@0
|
111 }
|
xue@0
|
112 else
|
xue@0
|
113 return 0;
|
xue@0
|
114 }
|
xue@0
|
115
|
xue@0
|
116 int IntToIntInterleave(void* dest1, void* dest2, int bytesperunit, void* block, int Count)
|
xue@0
|
117 {
|
xue@0
|
118 if (bytesperunit==1)
|
xue@0
|
119 {
|
xue@0
|
120 char* Dest1=(char*)dest1;
|
xue@0
|
121 char* Dest2=(char*)dest2;
|
xue@0
|
122 char* Block=(char*)block;
|
xue@0
|
123 for (int i=0; i<Count; i++)
|
xue@0
|
124 {
|
xue@0
|
125 *(Dest1++)=*(Block++);
|
xue@0
|
126 *(Dest2++)=*(Block++);
|
xue@0
|
127 }
|
xue@0
|
128 return 2*Count;
|
xue@0
|
129 }
|
xue@0
|
130 else if (bytesperunit==2)
|
xue@0
|
131 {
|
xue@0
|
132 __int16* Dest1=(__int16*)dest1;
|
xue@0
|
133 __int16* Dest2=(__int16*)dest2;
|
xue@0
|
134 __int16* Block=(__int16*)block;
|
xue@0
|
135 for (int i=0; i<Count; i++)
|
xue@0
|
136 {
|
xue@0
|
137 *(Dest1++)=*(Block++);
|
xue@0
|
138 *(Dest2++)=*(Block++);
|
xue@0
|
139 }
|
xue@0
|
140 return 4*Count;
|
xue@0
|
141 }
|
xue@0
|
142 else if (bytesperunit==2)
|
xue@0
|
143 {
|
xue@0
|
144 __pint24 Dest1=(__pint24)dest1;
|
xue@0
|
145 __pint24 Dest2=(__pint24)dest2;
|
xue@0
|
146 __pint24 Block=(__pint24)block;
|
xue@0
|
147 for (int i=0; i<Count; i++)
|
xue@0
|
148 {
|
xue@0
|
149 *(Dest1++)=*(Block++);
|
xue@0
|
150 *(Dest2++)=*(Block++);
|
xue@0
|
151 }
|
xue@0
|
152 return 6*Count;
|
xue@0
|
153 }
|
xue@0
|
154 else
|
xue@0
|
155 return 0;
|
xue@0
|
156 }
|
xue@0
|
157
|
xue@0
|
158 int IntToIntMultiSingle(void* dest, int bytesperunit, int channels, int offset, void* block, int Count)
|
xue@0
|
159 {
|
xue@0
|
160 if (channels==1)
|
xue@0
|
161 {
|
xue@0
|
162 memcpy(dest, &((char*)block)[offset*bytesperunit], bytesperunit*Count);
|
xue@0
|
163 return Count;
|
xue@0
|
164 }
|
xue@0
|
165 else if (channels==2)
|
xue@0
|
166 {
|
xue@0
|
167 if (bytesperunit==1)
|
xue@0
|
168 {
|
xue@0
|
169 char* Dest=(char*)dest;
|
xue@0
|
170 char* Block=&((char*)block)[offset];
|
xue@0
|
171 for (int i=0; i<Count; i++)
|
xue@0
|
172 {
|
xue@0
|
173 *(Dest++)=*Block;
|
xue@0
|
174 Block+=2;
|
xue@0
|
175 }
|
xue@0
|
176 return Count;
|
xue@0
|
177 }
|
xue@0
|
178 else if (bytesperunit==2)
|
xue@0
|
179 {
|
xue@0
|
180 __int16* Dest=(__int16*)dest;
|
xue@0
|
181 __int16* Block=(__int16*)(&((char*)block)[offset*2]);
|
xue@0
|
182 for (int i=0; i<Count; i++)
|
xue@0
|
183 {
|
xue@0
|
184 *(Dest++)=*Block;
|
xue@0
|
185 Block+=2;
|
xue@0
|
186 }
|
xue@0
|
187 return Count*2;
|
xue@0
|
188 }
|
xue@0
|
189 else if (bytesperunit==3)
|
xue@0
|
190 {
|
xue@0
|
191 __pint24 Dest=(__pint24)dest;
|
xue@0
|
192 __pint24 Block=(__pint24)(&((char*)block)[offset*3]);
|
xue@0
|
193 for (int i=0; i<Count; i++)
|
xue@0
|
194 {
|
xue@0
|
195 *(Dest++)=*Block;
|
xue@0
|
196 Block+=2;
|
xue@0
|
197 }
|
xue@0
|
198 return Count*3;
|
xue@0
|
199 }
|
xue@0
|
200 else
|
xue@0
|
201 return 0;
|
xue@0
|
202 }
|
xue@0
|
203 else
|
xue@0
|
204 {
|
xue@0
|
205 if (bytesperunit==1)
|
xue@0
|
206 {
|
xue@0
|
207 char* Dest=(char*)dest;
|
xue@0
|
208 char* Block=&((char*)block)[offset];
|
xue@0
|
209 for (int i=0; i<Count; i++)
|
xue@0
|
210 {
|
xue@0
|
211 *(Dest++)=*Block;
|
xue@0
|
212 Block+=channels;
|
xue@0
|
213 }
|
xue@0
|
214 return Count;
|
xue@0
|
215 }
|
xue@0
|
216 else if (bytesperunit==2)
|
xue@0
|
217 {
|
xue@0
|
218 __int16* Dest=(__int16*)dest;
|
xue@0
|
219 __int16* Block=(__int16*)(&((char*)block)[offset*2]);
|
xue@0
|
220 for (int i=0; i<Count; i++)
|
xue@0
|
221 {
|
xue@0
|
222 *(Dest++)=*Block;
|
xue@0
|
223 Block+=channels;
|
xue@0
|
224 }
|
xue@0
|
225 return Count*2;
|
xue@0
|
226 }
|
xue@0
|
227 else if (bytesperunit==3)
|
xue@0
|
228 {
|
xue@0
|
229 __pint24 Dest=(__pint24)dest;
|
xue@0
|
230 __pint24 Block=(__pint24)(&((char*)block)[offset*3]);
|
xue@0
|
231 for (int i=0; i<Count; i++)
|
xue@0
|
232 {
|
xue@0
|
233 *(Dest++)=*Block;
|
xue@0
|
234 Block+=channels;
|
xue@0
|
235 }
|
xue@0
|
236 return Count*3;
|
xue@0
|
237 }
|
xue@0
|
238 else return 0;
|
xue@0
|
239 }
|
xue@0
|
240 }
|
xue@0
|
241
|
xue@0
|
242 int IntToIntMultiChannel(int C, void** dest, int bytesperunit, int channels, void* block, int count)
|
xue@0
|
243 {
|
xue@0
|
244 int tail=channels-C;
|
xue@0
|
245 if (bytesperunit==1)
|
xue@0
|
246 {
|
xue@0
|
247 char* data=(char*)block;
|
xue@0
|
248 for (int i=0; i<count; i++)
|
xue@0
|
249 {
|
xue@0
|
250 for (int c=0; c<C; c++) *(((char*)dest[c])++)=*(data++);
|
xue@0
|
251 data=&data[tail];
|
xue@0
|
252 }
|
xue@0
|
253 return count;
|
xue@0
|
254 }
|
xue@0
|
255 else if (bytesperunit==2)
|
xue@0
|
256 {
|
xue@0
|
257 __int16* data=(__int16*)block;
|
xue@0
|
258 for (int i=0; i<count; i++)
|
xue@0
|
259 {
|
xue@0
|
260 for (int c=0; c<C; c++) *(((__int16*)dest[c])++)=*(data++);
|
xue@0
|
261 data=&data[tail];
|
xue@0
|
262 }
|
xue@0
|
263 return count*2;
|
xue@0
|
264 }
|
xue@0
|
265 else if (bytesperunit==3)
|
xue@0
|
266 {
|
xue@0
|
267 __pint24 data=(__pint24)block;
|
xue@0
|
268 for (int i=0; i<count; i++)
|
xue@0
|
269 {
|
xue@0
|
270 for (int c=0; c<C; c++) {*(((__pint24)dest[c])++)=*(data++); }
|
xue@0
|
271 data=&data[tail];
|
xue@0
|
272 }
|
xue@0
|
273 return count*3;
|
xue@0
|
274 }
|
xue@0
|
275 else
|
xue@0
|
276 return 0;
|
xue@0
|
277 }
|
xue@0
|
278
|
xue@0
|
279 __fastcall TAttachFileStream::TAttachFileStream(TFileStream* AFile)
|
xue@0
|
280 : TStream()
|
xue@0
|
281 {
|
xue@0
|
282 File=AFile;
|
xue@0
|
283 StartOffset=0;
|
xue@0
|
284 EndOffset=0;
|
xue@0
|
285 }
|
xue@0
|
286
|
xue@0
|
287 __fastcall TAttachFileStream::~TAttachFileStream()
|
xue@0
|
288 {
|
xue@0
|
289 delete File;
|
xue@0
|
290 }
|
xue@0
|
291
|
xue@0
|
292 int __fastcall TAttachFileStream::Read(void *Buffer, int Count)
|
xue@0
|
293 {
|
xue@0
|
294 return File->Read(Buffer, Count);
|
xue@0
|
295 }
|
xue@0
|
296
|
xue@0
|
297 int __fastcall TAttachFileStream::Seek(int AnOffset, Word Origin)
|
xue@0
|
298 {
|
xue@0
|
299 if (!File) return 0;
|
xue@0
|
300 if (Origin==soFromBeginning)
|
xue@0
|
301 return File->Seek(AnOffset+StartOffset, soFromBeginning)-StartOffset;
|
xue@0
|
302 else if (Origin==soFromCurrent)
|
xue@0
|
303 return File->Seek(AnOffset, soFromCurrent)-StartOffset;
|
xue@0
|
304 else
|
xue@0
|
305 return File->Seek(AnOffset+EndOffset, soFromEnd)-StartOffset;
|
xue@0
|
306 }
|
xue@0
|
307
|
xue@0
|
308 __int64 __fastcall TAttachFileStream::Seek(const __int64 AnOffset, TSeekOrigin Origin)
|
xue@0
|
309 {
|
xue@0
|
310 return Seek((int)AnOffset, (Word)Origin);
|
xue@0
|
311 }
|
xue@0
|
312
|
xue@0
|
313 int __fastcall TAttachFileStream::Write(const void *Buffer, int Count)
|
xue@0
|
314 {
|
xue@0
|
315 return File->Write(Buffer, Count);
|
xue@0
|
316 }
|
xue@0
|
317
|
xue@0
|
318 //---------------------------------------------------------------------------
|
xue@0
|
319 // ValidCtrCheck is used to assure that the components created do not have
|
xue@0
|
320 // any pure virtual functions.
|
xue@0
|
321 //
|
xue@0
|
322
|
xue@0
|
323 static inline void ValidCtrCheck(TWaveAudio *)
|
xue@0
|
324 {
|
xue@0
|
325 new TWaveAudio(NULL);
|
xue@0
|
326 }
|
xue@0
|
327 //---------------------------------------------------------------------------
|
xue@0
|
328 __fastcall TWaveAudio::~TWaveAudio()
|
xue@0
|
329 {
|
xue@0
|
330 delete FMemoryStream;
|
xue@0
|
331 delete FFileStream;
|
xue@0
|
332 DeallocateHWnd(HWndOut);
|
xue@0
|
333 DeallocateHWnd(HWndIn);
|
xue@0
|
334 }
|
xue@0
|
335
|
xue@0
|
336 //---------------------------------------------------------------------------
|
xue@0
|
337 void __fastcall TWaveAudio::Clear(TObject* Sender)
|
xue@0
|
338 {
|
xue@0
|
339 if (!FUseMemoryStream)
|
xue@0
|
340 {
|
xue@0
|
341 FUseMemoryStream=true;
|
xue@0
|
342 delete FFileStream->File;
|
xue@0
|
343 FFileStream->File=0;
|
xue@0
|
344 FFileName="";
|
xue@0
|
345 }
|
xue@0
|
346 FMemoryStream->Position=0;
|
xue@0
|
347 FMemoryStream->Size=0;
|
xue@0
|
348 if (FOnAudioChange) FOnAudioChange(this);
|
xue@0
|
349 }
|
xue@0
|
350
|
xue@0
|
351 //---------------------------------------------------------------------------
|
xue@0
|
352 void __fastcall TWaveAudio::CloseFile(bool Close)
|
xue@0
|
353 {
|
xue@0
|
354 if (UseMemoryStream) return;
|
xue@0
|
355 int Position=FFileStream->Position;
|
xue@0
|
356 delete FFileStream->File;
|
xue@0
|
357 FFileStream->File=new TFileStream(FFileName, fmOpenWrite);
|
xue@0
|
358 SaveHeader(FFileStream->File);
|
xue@0
|
359 delete FFileStream->File;
|
xue@0
|
360 FFileStream->File=0;
|
xue@0
|
361 if (!Close)
|
xue@0
|
362 {
|
xue@0
|
363 FFileStream->File=new TFileStream(FFileName, fmOpenRead);
|
xue@0
|
364 FFileStream->Position=Position;
|
xue@0
|
365 }
|
xue@0
|
366 }
|
xue@0
|
367
|
xue@0
|
368 //---------------------------------------------------------------------------
|
xue@0
|
369 void TWaveAudio::CopyFrom(TStream* AStream, int Count)
|
xue@0
|
370 {
|
xue@0
|
371 WaveStream->CopyFrom(AStream, Count);
|
xue@0
|
372 if (FOnAudioChange) FOnAudioChange(this);
|
xue@0
|
373 }
|
xue@0
|
374
|
xue@0
|
375 void TWaveAudio::CopyFrom(TWaveAudio* AWaveAudio, int Count)
|
xue@0
|
376 {
|
xue@0
|
377 WaveStream->CopyFrom(AWaveAudio->WaveStream, Count);
|
xue@0
|
378 if (FOnAudioChange) FOnAudioChange(this);
|
xue@0
|
379 }
|
xue@0
|
380
|
xue@0
|
381 //---------------------------------------------------------------------------
|
xue@0
|
382 void TWaveAudio::CopySamplesFrom(TStream* AStream, int Count)
|
xue@0
|
383 {
|
xue@0
|
384 WaveStream->CopyFrom(AStream, Count*FChannels*(BitsPerSample/8));
|
xue@0
|
385 if (FOnAudioChange) FOnAudioChange(this);
|
xue@0
|
386 }
|
xue@0
|
387
|
xue@0
|
388 void TWaveAudio::CopySamplesFrom(TWaveAudio* AWaveAudio, int Count)
|
xue@0
|
389 {
|
xue@0
|
390 WaveStream->CopyFrom(AWaveAudio->WaveStream, Count*FChannels*(BitsPerSample/8));
|
xue@0
|
391 if (FOnAudioChange) FOnAudioChange(this);
|
xue@0
|
392 }
|
xue@0
|
393
|
xue@0
|
394 //---------------------------------------------------------------------------
|
xue@0
|
395 void TWaveAudio::CreateFile(AnsiString FileName)
|
xue@0
|
396 {
|
xue@0
|
397 UseMemoryStream=false;
|
xue@0
|
398
|
xue@0
|
399 TFileStream* OpenFile=new TFileStream(FileName, fmCreate);
|
xue@0
|
400 SaveHeader(OpenFile);
|
xue@0
|
401 delete OpenFile;
|
xue@0
|
402
|
xue@0
|
403 delete FFileStream->File;
|
xue@0
|
404 FFileStream->File=new TFileStream(FileName, fmOpenReadWrite);
|
xue@0
|
405 FFileStream->StartOffset=FFileStream->File->Size;
|
xue@0
|
406 FFileStream->Position=0;
|
xue@0
|
407 FFileName=FileName;
|
xue@0
|
408 }
|
xue@0
|
409
|
xue@0
|
410 //---------------------------------------------------------------------------
|
xue@0
|
411 int __fastcall TWaveAudio::FillBlock(void* Block)
|
xue@0
|
412 {
|
xue@0
|
413 return Stream->Read(Block, FBlockSize);
|
xue@0
|
414 }
|
xue@0
|
415
|
xue@0
|
416 //---------------------------------------------------------------------------
|
xue@0
|
417 int __fastcall TWaveAudio::GetBytesPerSample()
|
xue@0
|
418 {
|
xue@0
|
419 return FBitsPerSample/8;
|
xue@0
|
420 }
|
xue@0
|
421
|
xue@0
|
422 //---------------------------------------------------------------------------
|
xue@0
|
423 __int32 __fastcall TWaveAudio::GetLength()
|
xue@0
|
424 {
|
xue@0
|
425 return Stream->Size/FBlockAlign;
|
xue@0
|
426 }
|
xue@0
|
427
|
xue@0
|
428 //---------------------------------------------------------------------------
|
xue@0
|
429 TStream* __fastcall TWaveAudio::GetStream()
|
xue@0
|
430 {
|
xue@0
|
431 if (FUseMemoryStream) return FMemoryStream;
|
xue@0
|
432 else return FFileStream;
|
xue@0
|
433 }
|
xue@0
|
434
|
xue@0
|
435 //---------------------------------------------------------------------------
|
xue@0
|
436 void TWaveAudio::GetWaveProperties(TWaveAudio* WaveAudio1)
|
xue@0
|
437 {
|
xue@0
|
438 FFormatTag=WaveAudio1->FormatTag;
|
xue@0
|
439 SamplesPerSec=WaveAudio1->SamplesPerSec;
|
xue@0
|
440 BitsPerSample=WaveAudio1->BitsPerSample;
|
xue@0
|
441 Channels=WaveAudio1->Channels;
|
xue@0
|
442 BlockSize=WaveAudio1->BlockSize;
|
xue@0
|
443 }
|
xue@0
|
444
|
xue@0
|
445 //---------------------------------------------------------------------------
|
xue@0
|
446 bool __fastcall TWaveAudio::ReadHeader(TStream* AStream, __int32& length, bool allowunfinisheddata)
|
xue@0
|
447 {
|
xue@0
|
448 bool success=true;
|
xue@0
|
449 char s[10];
|
xue@0
|
450 __int32 headerlen;
|
xue@0
|
451 __int32 headerstart;
|
xue@0
|
452
|
xue@0
|
453 __int16 formattag;
|
xue@0
|
454 __int16 channels;
|
xue@0
|
455 __int32 samplespersec;
|
xue@0
|
456 __int32 avgbytespersec;
|
xue@0
|
457 __int16 blockalign;
|
xue@0
|
458 __int16 bitspersample;
|
xue@0
|
459
|
xue@0
|
460 int rc=AStream->Read(s, 4); s[4]=0;
|
xue@0
|
461 success=success&&(rc==4)&&!strcmp(s, "RIFF");
|
xue@0
|
462 if (!success) return success;
|
xue@0
|
463
|
xue@0
|
464 rc=AStream->Read(&length, 4);
|
xue@0
|
465 success=success&&(rc==4);
|
xue@0
|
466
|
xue@0
|
467 rc=AStream->Read(s, 4); if (rc!=4) return false;
|
xue@0
|
468 s[4]=0;
|
xue@0
|
469 success=success&&(rc==4)&&!strcmp(s, "WAVE");
|
xue@0
|
470 if (!success) return success;
|
xue@0
|
471
|
xue@0
|
472 rc=AStream->Read(s, 4); s[4]=0;
|
xue@0
|
473 while(rc==4 && strcmp(s, "fmt "))
|
xue@0
|
474 {
|
xue@0
|
475 AStream->Read(&length, 4);
|
xue@0
|
476 AStream->Seek(length, soFromCurrent);
|
xue@0
|
477 rc=AStream->Read(s, 4); s[4]=0;
|
xue@0
|
478 }
|
xue@0
|
479 success=success&&(rc==4);
|
xue@0
|
480 if (!success) return success;
|
xue@0
|
481
|
xue@0
|
482 rc=AStream->Read(&headerlen, 4);
|
xue@0
|
483 headerstart=AStream->Position;
|
xue@0
|
484
|
xue@0
|
485 AStream->Read(&formattag, 2);
|
xue@0
|
486 AStream->Read(&channels, 2);
|
xue@0
|
487 AStream->Read(&samplespersec, 4);
|
xue@0
|
488 AStream->Read(&avgbytespersec, 4);
|
xue@0
|
489 AStream->Read(&blockalign, 2);
|
xue@0
|
490 AStream->Read(&bitspersample, 2);
|
xue@0
|
491 success=success&&(formattag==1);
|
xue@0
|
492 success=success&&(rc==4)&&(blockalign*8==channels*bitspersample);
|
xue@0
|
493 success=success&&(avgbytespersec==samplespersec*blockalign);
|
xue@0
|
494
|
xue@0
|
495 if (!success) return success;
|
xue@0
|
496 AStream->Seek(headerlen+headerstart, soFromBeginning);
|
xue@0
|
497
|
xue@0
|
498 rc=AStream->Read(s, 4); s[4]=0;
|
xue@0
|
499 while(rc==4 && strcmp(s, "data"))
|
xue@0
|
500 {
|
xue@0
|
501 AStream->Read(&length, 4);
|
xue@0
|
502 AStream->Seek(length, soFromCurrent);
|
xue@0
|
503 rc=AStream->Read(s, 4); s[4]=0;
|
xue@0
|
504 }
|
xue@0
|
505 success=success&&(rc==4);
|
xue@0
|
506 if (!success) return success;
|
xue@0
|
507
|
xue@0
|
508 rc=AStream->Read(&length, 4);
|
xue@0
|
509 success=success&&(rc==4);
|
xue@0
|
510 if (!success) return success;
|
xue@0
|
511
|
xue@0
|
512 if (AStream->Position+length>AStream->Size)
|
xue@0
|
513 {
|
xue@0
|
514 if (allowunfinisheddata) length=(AStream->Size-AStream->Position)/blockalign*blockalign;
|
xue@0
|
515 else success=false;
|
xue@0
|
516 }
|
xue@0
|
517 if (!success) return success;
|
xue@0
|
518
|
xue@0
|
519 FFormatTag=formattag;
|
xue@0
|
520 FChannels=channels;
|
xue@0
|
521 FSamplesPerSec=samplespersec;
|
xue@0
|
522 FAvgBytesPerSec=avgbytespersec;
|
xue@0
|
523 FBlockAlign=blockalign;
|
xue@0
|
524 FBitsPerSample=bitspersample;
|
xue@0
|
525
|
xue@0
|
526 return success;
|
xue@0
|
527 }
|
xue@0
|
528
|
xue@0
|
529 void TWaveAudio::InsertFromFile(AnsiString FileName)
|
xue@0
|
530 {
|
xue@0
|
531 TFileStream* OpenFile=new TFileStream(FileName, fmOpenRead|fmShareDenyNone);
|
xue@0
|
532
|
xue@0
|
533 __int32 length;
|
xue@0
|
534 bool success=ReadHeader(OpenFile, length);
|
xue@0
|
535
|
xue@0
|
536 if (success)
|
xue@0
|
537 {
|
xue@0
|
538 FFileName=FileName;
|
xue@0
|
539 if (FUseMemoryStream)
|
xue@0
|
540 {
|
xue@0
|
541 if (length>0)
|
xue@0
|
542 {
|
xue@0
|
543 FMemoryStream->Size=length;
|
xue@0
|
544 OpenFile->Read(FMemoryStream->Memory, length);
|
xue@0
|
545 }
|
xue@0
|
546 delete OpenFile;
|
xue@0
|
547 }
|
xue@0
|
548 else
|
xue@0
|
549 {
|
xue@0
|
550 delete FFileStream->File;
|
xue@0
|
551 FFileStream->File=OpenFile;
|
xue@0
|
552 FFileStream->StartOffset=OpenFile->Position;
|
xue@0
|
553 FFileStream->EndOffset=OpenFile->Position+length-OpenFile->Size;
|
xue@0
|
554 }
|
xue@0
|
555
|
xue@0
|
556 if (FStreamLimit>0 && Stream->Size>=FStreamLimit && OnStreamFull) OnStreamFull(this);
|
xue@0
|
557 if (FOnAudioChange) FOnAudioChange(this);
|
xue@0
|
558 }
|
xue@0
|
559 else
|
xue@0
|
560 {
|
xue@0
|
561 delete OpenFile;
|
xue@0
|
562 throw EReadError("PCM error ecountered reading "+FileName);
|
xue@0
|
563 }
|
xue@0
|
564 }
|
xue@0
|
565
|
xue@0
|
566 //---------------------------------------------------------------------------
|
xue@0
|
567 bool TWaveAudio::IsValidWave(AnsiString FileName)
|
xue@0
|
568 {
|
xue@0
|
569 bool success=true;
|
xue@0
|
570 char s[10];
|
xue@0
|
571 __int32 headerlen;
|
xue@0
|
572 __int32 headerstart;
|
xue@0
|
573
|
xue@0
|
574 __int16 formattag;
|
xue@0
|
575 __int16 channels;
|
xue@0
|
576 __int32 samplespersec;
|
xue@0
|
577 __int32 avgbytespersec;
|
xue@0
|
578 __int16 blockalign;
|
xue@0
|
579 __int16 bitspersample;
|
xue@0
|
580 __int32 length;
|
xue@0
|
581
|
xue@0
|
582
|
xue@0
|
583 TFileStream* OpenFile=new TFileStream(FileName,fmOpenRead|fmShareDenyNone);
|
xue@0
|
584
|
xue@0
|
585 OpenFile->Read(s, 4);
|
xue@0
|
586 s[4]=0;
|
xue@0
|
587 success=success&&!strcmp(s, "RIFF");
|
xue@0
|
588
|
xue@0
|
589 OpenFile->Read(&length, 4);
|
xue@0
|
590 success=success&&(length+OpenFile->Position==OpenFile->Size);
|
xue@0
|
591
|
xue@0
|
592 OpenFile->Read(s, 8);
|
xue@0
|
593 s[8]=0;
|
xue@0
|
594 success=success&&!strcmp(s, "WAVEfmt ");
|
xue@0
|
595
|
xue@0
|
596 OpenFile->Read(&headerlen, 4);
|
xue@0
|
597 headerstart=OpenFile->Position;
|
xue@0
|
598
|
xue@0
|
599 OpenFile->Read(&formattag, 2);
|
xue@0
|
600 success=success&&(formattag==1);
|
xue@0
|
601
|
xue@0
|
602 OpenFile->Read(&channels, 2);
|
xue@0
|
603 OpenFile->Read(&samplespersec, 4);
|
xue@0
|
604 OpenFile->Read(&avgbytespersec, 4);
|
xue@0
|
605 OpenFile->Read(&blockalign, 2);
|
xue@0
|
606 OpenFile->Read(&bitspersample, 2);
|
xue@0
|
607 success=success&&(blockalign*8==channels*bitspersample);
|
xue@0
|
608 success=success&&(avgbytespersec==samplespersec*blockalign);
|
xue@0
|
609
|
xue@0
|
610 OpenFile->Seek(headerlen+headerstart, soFromBeginning);
|
xue@0
|
611 OpenFile->Read(s, 4);
|
xue@0
|
612 s[4]=0;
|
xue@0
|
613 success=success&&!strcmp(s, "data");
|
xue@0
|
614
|
xue@0
|
615 OpenFile->Read(&length, 4);
|
xue@0
|
616 success=success&&(length+OpenFile->Position==OpenFile->Size);
|
xue@0
|
617
|
xue@0
|
618 delete OpenFile;
|
xue@0
|
619 return success;
|
xue@0
|
620 }
|
xue@0
|
621
|
xue@0
|
622 //---------------------------------------------------------------------------
|
xue@0
|
623 void TWaveAudio::LoadFromFile(AnsiString FileName)
|
xue@0
|
624 {
|
xue@0
|
625 if (FOnBeforeLoad) FOnBeforeLoad(this);
|
xue@0
|
626 if (FAutoUseMemoryStream) UseMemoryStream=false;
|
xue@0
|
627 if (FUseMemoryStream) FMemoryStream->Clear();
|
xue@0
|
628 InsertFromFile(FileName);
|
xue@0
|
629 if (FOnLoad) FOnLoad(this);
|
xue@0
|
630 }
|
xue@0
|
631
|
xue@0
|
632 //---------------------------------------------------------------------------
|
xue@0
|
633 void __fastcall TWaveAudio::OnWimClose(TMessage& Message)
|
xue@0
|
634 {
|
xue@0
|
635 waveInUnprepareHeader(WaveIn,WaveHdr1,sizeof(WAVEHDR));
|
xue@0
|
636 waveInUnprepareHeader(WaveIn,WaveHdr2,sizeof(WAVEHDR));
|
xue@0
|
637 delete WaveHdr1;
|
xue@0
|
638 delete WaveHdr2;
|
xue@0
|
639 delete[] Buffer1;
|
xue@0
|
640 delete[] Buffer2;
|
xue@0
|
641 FRecording=false;
|
xue@0
|
642 if (ResetInStream && FOnStreamFull)
|
xue@0
|
643 FOnStreamFull(this);
|
xue@0
|
644 ResetInStream=false;
|
xue@0
|
645 ResetInUser=false;
|
xue@0
|
646 if (FOnRecordingDone) FOnRecordingDone(this);
|
xue@0
|
647 if (FOnAudioChange) FOnAudioChange(this);
|
xue@0
|
648 }
|
xue@0
|
649
|
xue@0
|
650 //---------------------------------------------------------------------------
|
xue@0
|
651 void __fastcall TWaveAudio::OnWimData(TMessage& Message)
|
xue@0
|
652 {
|
xue@0
|
653 WAVEHDR* WaveHdr=(WAVEHDR*)Message.LParam;
|
xue@0
|
654 if (!FRecording) return;
|
xue@0
|
655
|
xue@0
|
656 if (!ResetInStream)
|
xue@0
|
657 {
|
xue@0
|
658 ReleaseBlock(WaveHdr->lpData,WaveHdr->dwBytesRecorded);
|
xue@0
|
659 if (FStreamLimit>0 && Stream->Size>=FStreamLimit)
|
xue@0
|
660 ResetInStream=true;
|
xue@0
|
661 waveInAddBuffer(WaveIn,WaveHdr,sizeof(WAVEHDR));
|
xue@0
|
662 if (FOnInAddBuffer) FOnInAddBuffer(this);
|
xue@0
|
663 if (ResetInUser)
|
xue@0
|
664 {
|
xue@0
|
665 waveInReset(WaveIn);
|
xue@0
|
666 waveInClose(WaveIn);
|
xue@0
|
667 }
|
xue@0
|
668 }
|
xue@0
|
669 else
|
xue@0
|
670 {
|
xue@0
|
671 waveInReset(WaveIn);
|
xue@0
|
672 waveInClose(WaveIn);
|
xue@0
|
673 }
|
xue@0
|
674 }
|
xue@0
|
675
|
xue@0
|
676 //---------------------------------------------------------------------------
|
xue@0
|
677 void __fastcall TWaveAudio::OnWimOpen(TMessage& Message)
|
xue@0
|
678 {
|
xue@0
|
679 //
|
xue@0
|
680 }
|
xue@0
|
681
|
xue@0
|
682 //---------------------------------------------------------------------------
|
xue@0
|
683 void __fastcall TWaveAudio::OnWomClose(TMessage& Message)
|
xue@0
|
684 {
|
xue@0
|
685 waveOutUnprepareHeader(WaveOut,WaveHdr1,sizeof(WAVEHDR));
|
xue@0
|
686 waveOutUnprepareHeader(WaveOut,WaveHdr2,sizeof(WAVEHDR));
|
xue@0
|
687 delete WaveHdr1;
|
xue@0
|
688 delete WaveHdr2;
|
xue@0
|
689 delete[] Buffer1;
|
xue@0
|
690 delete[] Buffer2;
|
xue@0
|
691 WaveHdr1=WaveHdr2=0;
|
xue@0
|
692 Buffer1=Buffer2=0;
|
xue@0
|
693 FPlaying=false;
|
xue@0
|
694 FPaused=false;
|
xue@0
|
695 ResetOut=false;
|
xue@0
|
696 ResetOutUser=false;
|
xue@0
|
697 if (FOnPlaybackProgress) FOnPlaybackProgress(this, 1);
|
xue@0
|
698 if (FOnPlaybackProg) FOnPlaybackProg(this, -2);
|
xue@0
|
699
|
xue@0
|
700 if (OnPlaybackDone) OnPlaybackDone(this);
|
xue@0
|
701 }
|
xue@0
|
702
|
xue@0
|
703 //---------------------------------------------------------------------------
|
xue@0
|
704 void __fastcall TWaveAudio::OnWomDone(TMessage& Message)
|
xue@0
|
705 {
|
xue@0
|
706 WAVEHDR* WaveHdr=(WAVEHDR*)Message.LParam;
|
xue@0
|
707
|
xue@0
|
708 if (ResetOut)
|
xue@0
|
709 {
|
xue@0
|
710 if (WaveHdr->dwBufferLength!=(unsigned)FBlockSize)
|
xue@0
|
711 {
|
xue@0
|
712 waveOutClose(WaveOut);
|
xue@0
|
713 }
|
xue@0
|
714 }
|
xue@0
|
715 else
|
xue@0
|
716 {
|
xue@0
|
717 int rc;
|
xue@0
|
718
|
xue@0
|
719 if (ResetOutUser) rc=0;
|
xue@0
|
720 else rc=FillBlock(WaveHdr->lpData);
|
xue@0
|
721
|
xue@0
|
722 if (rc!=FBlockSize)
|
xue@0
|
723 {
|
xue@0
|
724 ResetOut=true;
|
xue@0
|
725 WaveHdr->dwBufferLength=rc;
|
xue@0
|
726 if (BitsPerSample==8) memset(&WaveHdr->lpData[rc],0x80,FBlockSize-rc);
|
xue@0
|
727 else memset(&WaveHdr->lpData[rc],0,FBlockSize-rc);
|
xue@0
|
728 waveOutUnprepareHeader(WaveOut, WaveHdr, sizeof(WAVEHDR));
|
xue@0
|
729 waveOutPrepareHeader(WaveOut, WaveHdr, sizeof(WAVEHDR));
|
xue@0
|
730 }
|
xue@0
|
731 waveOutWrite(WaveOut,WaveHdr,sizeof(WAVEHDR));
|
xue@0
|
732 if (FOnPlaybackProgress)
|
xue@0
|
733 FOnPlaybackProgress(this, (Stream->Position-FBlockSize)*1.0/Stream->Size);
|
xue@0
|
734 if (FOnPlaybackProg)
|
xue@0
|
735 FOnPlaybackProg(this, Stream->Position-FBlockSize);
|
xue@0
|
736 if (FOnOutWrite) FOnOutWrite(this);
|
xue@0
|
737 }
|
xue@0
|
738 }
|
xue@0
|
739
|
xue@0
|
740 //---------------------------------------------------------------------------
|
xue@0
|
741 void __fastcall TWaveAudio::OnWomOpen(TMessage& Message)
|
xue@0
|
742 {
|
xue@0
|
743 //
|
xue@0
|
744 }
|
xue@0
|
745
|
xue@0
|
746 //---------------------------------------------------------------------------
|
xue@0
|
747 void __fastcall TWaveAudio::Pause(TObject* Sender)
|
xue@0
|
748 {
|
xue@0
|
749 if (FPlaying)
|
xue@0
|
750 {
|
xue@0
|
751 waveOutPause(WaveOut);
|
xue@0
|
752 FPaused=true;
|
xue@0
|
753 }
|
xue@0
|
754 }
|
xue@0
|
755
|
xue@0
|
756 //---------------------------------------------------------------------------
|
xue@0
|
757 void __fastcall TWaveAudio::PausePlayback(TObject* Sender)
|
xue@0
|
758 {
|
xue@0
|
759 if (Playing) ResetOutUser=true;
|
xue@0
|
760 }
|
xue@0
|
761
|
xue@0
|
762 //---------------------------------------------------------------------------
|
xue@0
|
763 void __fastcall TWaveAudio::PauseRecording(TObject* Sender)
|
xue@0
|
764 {
|
xue@0
|
765 if (Recording) ResetInUser=true;
|
xue@0
|
766 }
|
xue@0
|
767
|
xue@0
|
768 //---------------------------------------------------------------------------
|
xue@0
|
769 void __fastcall TWaveAudio::Play(TObject* Sender)
|
xue@0
|
770 {
|
xue@0
|
771 Rewind(this);
|
xue@0
|
772 StartPlayback(this);
|
xue@0
|
773 }
|
xue@0
|
774
|
xue@0
|
775 void __fastcall TWaveAudio::Play(TNotifyEvent AnOnPlaybackDone)
|
xue@0
|
776 {
|
xue@0
|
777 Rewind(this);
|
xue@0
|
778 OnPlaybackDone=AnOnPlaybackDone;
|
xue@0
|
779 StartPlayback(this);
|
xue@0
|
780 }
|
xue@0
|
781
|
xue@0
|
782 //---------------------------------------------------------------------------
|
xue@0
|
783 int __fastcall TWaveAudio::Read(void* Buffer, int Count)
|
xue@0
|
784 {
|
xue@0
|
785 return Stream->Read(Buffer, Count);
|
xue@0
|
786 }
|
xue@0
|
787
|
xue@0
|
788 int __fastcall TWaveAudio::ReadSamples(void* Buffer, int Count)
|
xue@0
|
789 {
|
xue@0
|
790 return Stream->Read(Buffer, Count*FChannels*(BitsPerSample/8));
|
xue@0
|
791 }
|
xue@0
|
792
|
xue@0
|
793 int __fastcall TWaveAudio::ReadSamples(double* Buffer, int Count)
|
xue@0
|
794 {
|
xue@0
|
795 int FBytesPerSample=FBitsPerSample/8;
|
xue@0
|
796 int countavailable=(Stream->Size-Stream->Position)/FBytesPerSample;
|
xue@0
|
797 if (Count>countavailable) Count=countavailable;
|
xue@0
|
798 if (FUseMemoryStream)
|
xue@0
|
799 {
|
xue@0
|
800 int Position=FMemoryStream->Position;
|
xue@0
|
801 IntToDouble(Buffer, &((char*)FMemoryStream->Memory)[Position], FBytesPerSample, Count);
|
xue@0
|
802 FMemoryStream->Position=Position+Count*FBytesPerSample;
|
xue@0
|
803 }
|
xue@0
|
804 else
|
xue@0
|
805 {
|
xue@0
|
806 void *data=new char[FBlockSize];
|
xue@0
|
807 double *Data=Buffer;
|
xue@0
|
808 int CountPF=FBlockSize/FBytesPerSample;
|
xue@0
|
809 int Fr=(Count/CountPF);
|
xue@0
|
810 for (int i=0; i<Fr; i++)
|
xue@0
|
811 {
|
xue@0
|
812 Stream->Read(data, FBlockSize);
|
xue@0
|
813 IntToDouble(Data, data, FBytesPerSample, CountPF);
|
xue@0
|
814 Data=&Data[CountPF];
|
xue@0
|
815 }
|
xue@0
|
816 int CountLastF=Count%CountPF;
|
xue@0
|
817 int lastblocksize=CountLastF*FBytesPerSample;
|
xue@0
|
818 Stream->Read(data, lastblocksize);
|
xue@0
|
819 IntToDouble(Data, data, FBytesPerSample, CountLastF);
|
xue@0
|
820 delete[] data;
|
xue@0
|
821 }
|
xue@0
|
822
|
xue@0
|
823 return Count*FBytesPerSample;
|
xue@0
|
824 }
|
xue@0
|
825
|
xue@0
|
826 int __fastcall TWaveAudio::ReadSamplesInterleave(void* Buffer1, void* Buffer2, int Count)
|
xue@0
|
827 {
|
xue@0
|
828 int FBytesPerSample=FBitsPerSample/8;
|
xue@0
|
829 int SampleSize=FBytesPerSample*2;
|
xue@0
|
830 int countavailable=(Stream->Size-Stream->Position)/SampleSize;
|
xue@0
|
831 if (Count>countavailable) Count=countavailable;
|
xue@0
|
832 if (FUseMemoryStream)
|
xue@0
|
833 {
|
xue@0
|
834 int Position=FMemoryStream->Position;
|
xue@0
|
835 IntToIntInterleave(Buffer1, Buffer2, FBytesPerSample, &((char*)FMemoryStream->Memory)[Position], Count);
|
xue@0
|
836 FMemoryStream->Position=Position+Count*SampleSize;
|
xue@0
|
837 }
|
xue@0
|
838 else
|
xue@0
|
839 {
|
xue@0
|
840 void *Data1=Buffer1, *Data2=Buffer2, *data=new char[FBlockSize];
|
xue@0
|
841 int HBlockSize=FBlockSize/2, CountPF=FBlockSize/SampleSize;
|
xue@0
|
842 int Fr=Count/CountPF;
|
xue@0
|
843 for (int i=0; i<Fr; i++)
|
xue@0
|
844 {
|
xue@0
|
845 Stream->Read(data, FBlockSize);
|
xue@0
|
846 IntToIntInterleave(Data1, Data2, FBytesPerSample, data, CountPF);
|
xue@0
|
847 Data1=&((char*)Data1)[HBlockSize], Data2=&((char*)Data2)[HBlockSize];
|
xue@0
|
848 }
|
xue@0
|
849 int CountLastF=Count%CountPF;
|
xue@0
|
850 int lastblocksize=CountLastF*SampleSize;
|
xue@0
|
851 Stream->Read(data, lastblocksize);
|
xue@0
|
852 IntToIntInterleave(Data1, Data2, FBytesPerSample, data, CountLastF);
|
xue@0
|
853 delete[] data;
|
xue@0
|
854 }
|
xue@0
|
855 return Count*SampleSize;
|
xue@0
|
856 }
|
xue@0
|
857
|
xue@0
|
858 int __fastcall TWaveAudio::ReadSamplesInterleave(double* Buffer1, double* Buffer2, int Count)
|
xue@0
|
859 {
|
xue@0
|
860 int FBytesPerSample=FBitsPerSample/8;
|
xue@0
|
861 int SampleSize=FBytesPerSample*2;
|
xue@0
|
862 int countavailable=(Stream->Size-Stream->Position)/SampleSize;
|
xue@0
|
863 if (Count>countavailable) Count=countavailable;
|
xue@0
|
864 if (FUseMemoryStream)
|
xue@0
|
865 {
|
xue@0
|
866 int Position=FMemoryStream->Position;
|
xue@0
|
867 IntToDoubleInterleave(Buffer1, Buffer2, &((char*)FMemoryStream->Memory)[Position], FBytesPerSample, Count);
|
xue@0
|
868 FMemoryStream->Position=Position+Count*SampleSize;
|
xue@0
|
869 }
|
xue@0
|
870 else
|
xue@0
|
871 {
|
xue@0
|
872 double *Data1=Buffer1, *Data2=Buffer2;
|
xue@0
|
873 void *data=new char[FBlockSize];
|
xue@0
|
874 int CountPF=FBlockSize/SampleSize;
|
xue@0
|
875 int Fr=Count/CountPF;
|
xue@0
|
876 for (int i=0; i<Fr; i++)
|
xue@0
|
877 {
|
xue@0
|
878 Stream->Read(data, FBlockSize);
|
xue@0
|
879 IntToDoubleInterleave(Data1, Data2, data, FBytesPerSample, CountPF);
|
xue@0
|
880 Data1=&Data1[CountPF], Data2=&Data2[CountPF];
|
xue@0
|
881 }
|
xue@0
|
882 int CountLastF=Count%CountPF;
|
xue@0
|
883 int lastblocksize=CountLastF*SampleSize;
|
xue@0
|
884 Stream->Read(data, lastblocksize);
|
xue@0
|
885 IntToDoubleInterleave(Data1, Data2, data, FBytesPerSample, CountLastF);
|
xue@0
|
886 delete[] data;
|
xue@0
|
887 }
|
xue@0
|
888 return Count*SampleSize;
|
xue@0
|
889 }
|
xue@0
|
890
|
xue@0
|
891 int __fastcall TWaveAudio::ReadSamplesMultiSingle(void* Buffer, int Channel, int Count)
|
xue@0
|
892 {
|
xue@0
|
893 int FBytesPerSample=FBitsPerSample/8;
|
xue@0
|
894 int SampleSize=FBytesPerSample*FChannels;
|
xue@0
|
895 int countavailable=(Stream->Size-Stream->Position)/SampleSize;
|
xue@0
|
896 if (Count>countavailable) Count=countavailable;
|
xue@0
|
897 if (FUseMemoryStream)
|
xue@0
|
898 {
|
xue@0
|
899 int Position=FMemoryStream->Position;
|
xue@0
|
900 IntToIntMultiSingle(Buffer, FBytesPerSample, FChannels, Channel, &((char*)FMemoryStream->Memory)[Position], Count);
|
xue@0
|
901 FMemoryStream->Position=Position+Count*SampleSize;
|
xue@0
|
902 }
|
xue@0
|
903 else
|
xue@0
|
904 {
|
xue@0
|
905 int CountPF=FBlockSize/SampleSize;
|
xue@0
|
906 int ReadSize=CountPF*SampleSize, WriteSize=CountPF*FBytesPerSample;
|
xue@0
|
907 int Fr=Count/CountPF;
|
xue@0
|
908 void *Data=Buffer, *data=new char[ReadSize];
|
xue@0
|
909 for (int i=0; i<Fr; i++)
|
xue@0
|
910 {
|
xue@0
|
911 Stream->Read(data, ReadSize);
|
xue@0
|
912 IntToIntMultiSingle(Data, FBytesPerSample, FChannels, Channel, data, CountPF);
|
xue@0
|
913 Data=&((char*)Data)[WriteSize];
|
xue@0
|
914 }
|
xue@0
|
915 int CountLastF=Count%CountPF;
|
xue@0
|
916 ReadSize=CountLastF*SampleSize;
|
xue@0
|
917 Stream->Read(data, ReadSize);
|
xue@0
|
918 IntToIntMultiSingle(Data, FBytesPerSample, FChannels, Channel, data, CountLastF);
|
xue@0
|
919 delete[] data;
|
xue@0
|
920 }
|
xue@0
|
921 return Count*FBytesPerSample;
|
xue@0
|
922 }
|
xue@0
|
923
|
xue@0
|
924 int __fastcall TWaveAudio::ReadSamplesMultiChannel(int C, void** Buffer, int Count)
|
xue@0
|
925 {
|
xue@0
|
926 if (C>FChannels) C=FChannels;
|
xue@0
|
927 int FBytesPerSample=FBitsPerSample/8;
|
xue@0
|
928 int SampleSize=FBytesPerSample*FChannels;
|
xue@0
|
929 int countavailable=(Stream->Size-Stream->Position)/SampleSize;
|
xue@0
|
930 if (Count>countavailable) Count=countavailable;
|
xue@0
|
931 if (FUseMemoryStream)
|
xue@0
|
932 {
|
xue@0
|
933 int Position=FMemoryStream->Position;
|
xue@0
|
934 IntToIntMultiChannel(C, Buffer, FBytesPerSample, FChannels, &((char*)FMemoryStream->Memory)[Position], Count);
|
xue@0
|
935 FMemoryStream->Position=Position+Count*SampleSize;
|
xue@0
|
936 }
|
xue@0
|
937 else
|
xue@0
|
938 {
|
xue@0
|
939 int CountPF=FBlockSize/SampleSize;
|
xue@0
|
940 int ReadSize=CountPF*SampleSize, WriteSize=CountPF*FBytesPerSample;
|
xue@0
|
941 int Fr=Count/CountPF;
|
xue@0
|
942 void* data=new char[ReadSize];
|
xue@0
|
943 for (int i=0; i<Fr; i++)
|
xue@0
|
944 {
|
xue@0
|
945 Stream->Read(data, ReadSize);
|
xue@0
|
946 IntToIntMultiChannel(C, Buffer, FBytesPerSample, FChannels, data, CountPF);
|
xue@0
|
947 for (int c=0; c<C; c++) Buffer[c]=&((char*)Buffer[c])[WriteSize];
|
xue@0
|
948 }
|
xue@0
|
949 int CountLastF=Count*CountPF;
|
xue@0
|
950 ReadSize=CountLastF*SampleSize;
|
xue@0
|
951 Stream->Read(data, ReadSize);
|
xue@0
|
952 IntToIntMultiChannel(C, Buffer, FBytesPerSample, FChannels, data, CountLastF);
|
xue@0
|
953 }
|
xue@0
|
954 return Count*SampleSize;
|
xue@0
|
955 }
|
xue@0
|
956
|
xue@0
|
957 //---------------------------------------------------------------------------
|
xue@0
|
958 void __fastcall TWaveAudio::ReleaseBlock(void* Block, int BytesRecorded)
|
xue@0
|
959 {
|
xue@0
|
960 Stream->Write(Block, BytesRecorded);
|
xue@0
|
961 }
|
xue@0
|
962
|
xue@0
|
963 //---------------------------------------------------------------------------
|
xue@0
|
964 void __fastcall TWaveAudio::Restart(TObject* Sender)
|
xue@0
|
965 {
|
xue@0
|
966 if (FPlaying)
|
xue@0
|
967 {
|
xue@0
|
968 waveOutRestart(WaveOut);
|
xue@0
|
969 FPaused=false;
|
xue@0
|
970 }
|
xue@0
|
971 }
|
xue@0
|
972
|
xue@0
|
973 //---------------------------------------------------------------------------
|
xue@0
|
974 void __fastcall TWaveAudio::Rewind(TObject* Sender)
|
xue@0
|
975 {
|
xue@0
|
976 Stream->Seek(0,soFromBeginning);
|
xue@0
|
977 }
|
xue@0
|
978
|
xue@0
|
979 //---------------------------------------------------------------------------
|
xue@0
|
980 void __fastcall TWaveAudio::SaveHeader(TStream* AStream)
|
xue@0
|
981 {
|
xue@0
|
982 __int32 s32;
|
xue@0
|
983 __int16 s16;
|
xue@0
|
984
|
xue@0
|
985 AStream->Write("RIFF",4);
|
xue@0
|
986 s32=Stream->Size+38;
|
xue@0
|
987 AStream->Write(&s32,4);
|
xue@0
|
988 AStream->Write("WAVEfmt ",8);
|
xue@0
|
989 s32=0x12;
|
xue@0
|
990 AStream->Write(&s32,4);
|
xue@0
|
991 s16=FFormatTag;
|
xue@0
|
992 AStream->Write(&s16,2);
|
xue@0
|
993 s16=FChannels;
|
xue@0
|
994 AStream->Write(&s16,2);
|
xue@0
|
995 s32=FSamplesPerSec;
|
xue@0
|
996 AStream->Write(&s32,4);
|
xue@0
|
997 s32=FAvgBytesPerSec;
|
xue@0
|
998 AStream->Write(&s32,4);
|
xue@0
|
999 s16=FBlockAlign;
|
xue@0
|
1000 AStream->Write(&s16,2);
|
xue@0
|
1001 s16=FBitsPerSample;
|
xue@0
|
1002 AStream->Write(&s16,2);
|
xue@0
|
1003 s16=0;
|
xue@0
|
1004 AStream->Write(&s16,2);
|
xue@0
|
1005 AStream->Write("data",4);
|
xue@0
|
1006 s32=Stream->Size;
|
xue@0
|
1007 AStream->Write(&s32,4);
|
xue@0
|
1008 }
|
xue@0
|
1009
|
xue@0
|
1010 void __fastcall TWaveAudio::SaveToFile(AnsiString FileName)
|
xue@0
|
1011 {
|
xue@0
|
1012 TFileStream& SaveFile=*new TFileStream(FileName, fmCreate);
|
xue@0
|
1013 SaveHeader(&SaveFile);
|
xue@0
|
1014
|
xue@0
|
1015 if (FUseMemoryStream)
|
xue@0
|
1016 ((TMemoryStream*)Stream)->SaveToStream(&SaveFile);
|
xue@0
|
1017 else
|
xue@0
|
1018 SaveFile.CopyFrom(Stream, 0);
|
xue@0
|
1019 delete &SaveFile;
|
xue@0
|
1020 }
|
xue@0
|
1021
|
xue@0
|
1022 //---------------------------------------------------------------------------
|
xue@0
|
1023 void __fastcall TWaveAudio::Seek(int Offset, WORD Origin)
|
xue@0
|
1024 {
|
xue@0
|
1025 WaveStream->Seek(Offset, Origin);
|
xue@0
|
1026 }
|
xue@0
|
1027
|
xue@0
|
1028 void __fastcall TWaveAudio::SeekSamples(int Offset, WORD Origin)
|
xue@0
|
1029 {
|
xue@0
|
1030 WaveStream->Seek(Offset*FChannels*(BitsPerSample/8), Origin);
|
xue@0
|
1031 }
|
xue@0
|
1032
|
xue@0
|
1033 //---------------------------------------------------------------------------
|
xue@0
|
1034 void __fastcall TWaveAudio::SetBitsPerSample(__int16 ABitsPerSample)
|
xue@0
|
1035 {
|
xue@0
|
1036 if (ABitsPerSample!=8 && ABitsPerSample!=16 && ABitsPerSample!=24) return;
|
xue@0
|
1037 FBitsPerSample=ABitsPerSample;
|
xue@0
|
1038 FAvgBytesPerSec=FSamplesPerSec*FBitsPerSample*FChannels/8;
|
xue@0
|
1039 FBlockAlign=FBitsPerSample*FChannels/8;
|
xue@0
|
1040 }
|
xue@0
|
1041
|
xue@0
|
1042 //---------------------------------------------------------------------------
|
xue@0
|
1043 void __fastcall TWaveAudio::SetBlockSize(int ABlockSize)
|
xue@0
|
1044 {
|
xue@0
|
1045 FBlockSize=ABlockSize;
|
xue@0
|
1046 }
|
xue@0
|
1047
|
xue@0
|
1048 //---------------------------------------------------------------------------
|
xue@0
|
1049 void __fastcall TWaveAudio::SetChannels(__int16 AChannels)
|
xue@0
|
1050 {
|
xue@0
|
1051 if (AChannels!=1 && AChannels!=2) return;
|
xue@0
|
1052 FChannels=AChannels;
|
xue@0
|
1053 FAvgBytesPerSec=FSamplesPerSec*FBitsPerSample*FChannels/8;
|
xue@0
|
1054 FBlockAlign=FBitsPerSample*FChannels/8;
|
xue@0
|
1055 }
|
xue@0
|
1056
|
xue@0
|
1057 //---------------------------------------------------------------------------
|
xue@0
|
1058 void __fastcall TWaveAudio::SetLVolume(unsigned __int16 ALVolume)
|
xue@0
|
1059 {
|
xue@0
|
1060 if (ALVolume!=FLVolume)
|
xue@0
|
1061 {
|
xue@0
|
1062 FLVolume=ALVolume;
|
xue@0
|
1063 if (FPlaying) SetVolume();
|
xue@0
|
1064 }
|
xue@0
|
1065 }
|
xue@0
|
1066
|
xue@0
|
1067 //---------------------------------------------------------------------------
|
xue@0
|
1068 void __fastcall TWaveAudio::SetRVolume(unsigned __int16 ARVolume)
|
xue@0
|
1069 {
|
xue@0
|
1070 if (ARVolume!=FRVolume)
|
xue@0
|
1071 {
|
xue@0
|
1072 FRVolume=ARVolume;
|
xue@0
|
1073 if (FPlaying) SetVolume();
|
xue@0
|
1074 }
|
xue@0
|
1075 }
|
xue@0
|
1076
|
xue@0
|
1077 //---------------------------------------------------------------------------
|
xue@0
|
1078 void __fastcall TWaveAudio::SetSamplesPerSec(__int32 ASamplesPerSec)
|
xue@0
|
1079 {
|
xue@0
|
1080 FSamplesPerSec=ASamplesPerSec;
|
xue@0
|
1081 FAvgBytesPerSec=FSamplesPerSec*FBitsPerSample*FChannels/8;
|
xue@0
|
1082 }
|
xue@0
|
1083
|
xue@0
|
1084 //---------------------------------------------------------------------------
|
xue@0
|
1085 void __fastcall TWaveAudio::SetStreamLimit(int AStreamLimit)
|
xue@0
|
1086 {
|
xue@0
|
1087 if (AStreamLimit>0 && Stream->Size>AStreamLimit)
|
xue@0
|
1088 {
|
xue@0
|
1089 if (OnStreamLimitFailure) OnStreamLimitFailure(this);
|
xue@0
|
1090 return;
|
xue@0
|
1091 }
|
xue@0
|
1092 FStreamLimit=AStreamLimit;
|
xue@0
|
1093 }
|
xue@0
|
1094
|
xue@0
|
1095 void __fastcall TWaveAudio::SetUseMemoryStream(bool AUseMemoryStream)
|
xue@0
|
1096 {
|
xue@0
|
1097 if (FUseMemoryStream!=AUseMemoryStream)
|
xue@0
|
1098 {
|
xue@0
|
1099 FUseMemoryStream=AUseMemoryStream;
|
xue@0
|
1100 }
|
xue@0
|
1101 }
|
xue@0
|
1102
|
xue@0
|
1103 //---------------------------------------------------------------------------
|
xue@0
|
1104 MMRESULT __fastcall TWaveAudio::SetVolume(void)
|
xue@0
|
1105 {
|
xue@0
|
1106 unsigned __int32 Volume=FRVolume;
|
xue@0
|
1107 Volume=Volume<<16;
|
xue@0
|
1108 Volume+=FLVolume;
|
xue@0
|
1109 return waveOutSetVolume(WaveOut, Volume);
|
xue@0
|
1110 }
|
xue@0
|
1111
|
xue@0
|
1112 //---------------------------------------------------------------------------
|
xue@0
|
1113 void __fastcall TWaveAudio::StartPlayback(TObject* Sender)
|
xue@0
|
1114 {
|
xue@0
|
1115 if (FPlaying) return;
|
xue@0
|
1116
|
xue@0
|
1117 WAVEFORMATEX wfx;
|
xue@0
|
1118 wfx.wFormatTag=FFormatTag;
|
xue@0
|
1119 wfx.nChannels=FChannels;
|
xue@0
|
1120 wfx.nSamplesPerSec=FSamplesPerSec;
|
xue@0
|
1121 wfx.nAvgBytesPerSec=FAvgBytesPerSec;
|
xue@0
|
1122 wfx.nBlockAlign=FBlockAlign;
|
xue@0
|
1123 wfx.wBitsPerSample=FBitsPerSample;
|
xue@0
|
1124 wfx.cbSize=FcbSize;
|
xue@0
|
1125
|
xue@0
|
1126 if (waveOutOpen(&WaveOut,WAVE_MAPPER,&wfx,(DWORD)HWndOut, NULL,
|
xue@0
|
1127 CALLBACK_WINDOW)!=MMSYSERR_NOERROR)
|
xue@0
|
1128 {
|
xue@0
|
1129 throw EWriteError("TWaveAudio Err: Failed opening device WaveOut");
|
xue@0
|
1130 }
|
xue@0
|
1131
|
xue@0
|
1132 SetVolume();
|
xue@0
|
1133
|
xue@0
|
1134 Buffer1=new char[FBlockSize];
|
xue@0
|
1135 Buffer2=new char[FBlockSize];
|
xue@0
|
1136 WaveHdr1=new WAVEHDR;
|
xue@0
|
1137 WaveHdr2=new WAVEHDR;
|
xue@0
|
1138
|
xue@0
|
1139 WaveHdr1->lpData=(char*)Buffer1;
|
xue@0
|
1140 WaveHdr1->dwBufferLength=FBlockSize;
|
xue@0
|
1141 WaveHdr1->dwBytesRecorded=0;
|
xue@0
|
1142 WaveHdr1->dwUser=0;
|
xue@0
|
1143 WaveHdr1->dwFlags=0;
|
xue@0
|
1144 WaveHdr1->dwLoops=1;
|
xue@0
|
1145 WaveHdr1->lpNext=NULL;
|
xue@0
|
1146 WaveHdr1->reserved=0;
|
xue@0
|
1147
|
xue@0
|
1148 WaveHdr2->lpData=(char*)Buffer2;
|
xue@0
|
1149 WaveHdr2->dwBufferLength=FBlockSize;
|
xue@0
|
1150 WaveHdr2->dwBytesRecorded=0;
|
xue@0
|
1151 WaveHdr2->dwUser=0;
|
xue@0
|
1152 WaveHdr2->dwFlags=0;
|
xue@0
|
1153 WaveHdr2->dwLoops=1;
|
xue@0
|
1154 WaveHdr2->lpNext=NULL;
|
xue@0
|
1155 WaveHdr2->reserved=0;
|
xue@0
|
1156
|
xue@0
|
1157 int rc;
|
xue@0
|
1158
|
xue@0
|
1159 ResetOut=false;
|
xue@0
|
1160 ResetOutUser=false;
|
xue@0
|
1161
|
xue@0
|
1162 rc=(FillBlock(WaveHdr1->lpData));
|
xue@0
|
1163 if (rc!=FBlockSize)
|
xue@0
|
1164 {
|
xue@0
|
1165 if (BitsPerSample==8) memset(&WaveHdr1->lpData[rc],0x80,FBlockSize-rc);
|
xue@0
|
1166 else memset(&WaveHdr1->lpData[rc],0,FBlockSize-rc);
|
xue@0
|
1167 WaveHdr1->dwBufferLength=rc;
|
xue@0
|
1168 ResetOut=true;
|
xue@0
|
1169 }
|
xue@0
|
1170 waveOutPrepareHeader(WaveOut,WaveHdr1,sizeof(WAVEHDR));
|
xue@0
|
1171 waveOutWrite(WaveOut,WaveHdr1,sizeof(WAVEHDR));
|
xue@0
|
1172
|
xue@0
|
1173 if (FOnPlaybackProgress)
|
xue@0
|
1174 FOnPlaybackProgress(this, 0);
|
xue@0
|
1175 if (FOnPlaybackProg)
|
xue@0
|
1176 FOnPlaybackProg(this, 0);
|
xue@0
|
1177
|
xue@0
|
1178 if (rc==BlockSize)
|
xue@0
|
1179 {
|
xue@0
|
1180 rc=(FillBlock(WaveHdr2->lpData));
|
xue@0
|
1181 if (rc!=FBlockSize)
|
xue@0
|
1182 {
|
xue@0
|
1183 if (BitsPerSample==8) memset(&WaveHdr2->lpData[rc],0x80,FBlockSize-rc);
|
xue@0
|
1184 else memset(&WaveHdr2->lpData[rc],0,FBlockSize-rc);
|
xue@0
|
1185 WaveHdr2->dwBufferLength=rc;
|
xue@0
|
1186 ResetOut=true;
|
xue@0
|
1187 }
|
xue@0
|
1188
|
xue@0
|
1189 waveOutPrepareHeader(WaveOut,WaveHdr2,sizeof(WAVEHDR));
|
xue@0
|
1190 waveOutWrite(WaveOut,WaveHdr2,sizeof(WAVEHDR));
|
xue@0
|
1191
|
xue@0
|
1192 if (FOnPlaybackProgress)
|
xue@0
|
1193 FOnPlaybackProgress(this, (Stream->Position-FBlockSize)*1.0/Stream->Size);
|
xue@0
|
1194 if (FOnPlaybackProg)
|
xue@0
|
1195 FOnPlaybackProg(this, Stream->Position-FBlockSize);
|
xue@0
|
1196
|
xue@0
|
1197 }
|
xue@0
|
1198 FPlaying=true;
|
xue@0
|
1199 if (FOnStartPlayback) FOnStartPlayback(this);
|
xue@0
|
1200 }
|
xue@0
|
1201
|
xue@0
|
1202 //---------------------------------------------------------------------------
|
xue@0
|
1203 void __fastcall TWaveAudio::StartRecording(TObject* Sender)
|
xue@0
|
1204 {
|
xue@0
|
1205 if (FRecording) return;
|
xue@0
|
1206
|
xue@0
|
1207 WAVEFORMATEX wfx;
|
xue@0
|
1208 wfx.wFormatTag=FFormatTag;
|
xue@0
|
1209 wfx.nChannels=FChannels;
|
xue@0
|
1210 wfx.nSamplesPerSec=FSamplesPerSec;
|
xue@0
|
1211 wfx.nAvgBytesPerSec=FAvgBytesPerSec;
|
xue@0
|
1212 wfx.nBlockAlign=FBlockAlign;
|
xue@0
|
1213 wfx.wBitsPerSample=FBitsPerSample;
|
xue@0
|
1214 wfx.cbSize=FcbSize;
|
xue@0
|
1215
|
xue@0
|
1216 MMRESULT tr=waveInOpen(&WaveIn, WAVE_MAPPER, &wfx, (unsigned long)HWndIn, NULL,
|
xue@0
|
1217 CALLBACK_WINDOW);
|
xue@0
|
1218 if (tr!=MMSYSERR_NOERROR && tr!=MMSYSERR_ALLOCATED)
|
xue@0
|
1219 {
|
xue@0
|
1220 throw EReadError("TWaveAudio err: Failed opening device WaveIn");
|
xue@0
|
1221 }
|
xue@0
|
1222
|
xue@0
|
1223 Buffer1=new char[FBlockSize];
|
xue@0
|
1224 Buffer2=new char[FBlockSize];
|
xue@0
|
1225 WaveHdr1=new WAVEHDR;
|
xue@0
|
1226 WaveHdr2=new WAVEHDR;
|
xue@0
|
1227
|
xue@0
|
1228 WaveHdr1->lpData=(char*)Buffer1;
|
xue@0
|
1229 WaveHdr1->dwBufferLength=FBlockSize;
|
xue@0
|
1230 WaveHdr1->dwBytesRecorded=0;
|
xue@0
|
1231 WaveHdr1->dwUser=0;
|
xue@0
|
1232 WaveHdr1->dwFlags=0;
|
xue@0
|
1233 WaveHdr1->dwLoops=1;
|
xue@0
|
1234 WaveHdr1->lpNext=NULL;
|
xue@0
|
1235 WaveHdr1->reserved=0;
|
xue@0
|
1236
|
xue@0
|
1237 waveInPrepareHeader(WaveIn,WaveHdr1,sizeof(WAVEHDR));
|
xue@0
|
1238
|
xue@0
|
1239 WaveHdr2->lpData=(char*)Buffer2;
|
xue@0
|
1240 WaveHdr2->dwBufferLength=FBlockSize;
|
xue@0
|
1241 WaveHdr2->dwBytesRecorded=0;
|
xue@0
|
1242 WaveHdr2->dwUser=0;
|
xue@0
|
1243 WaveHdr2->dwFlags=0;
|
xue@0
|
1244 WaveHdr2->dwLoops=1;
|
xue@0
|
1245 WaveHdr2->lpNext=NULL;
|
xue@0
|
1246 WaveHdr2->reserved=0;
|
xue@0
|
1247
|
xue@0
|
1248 waveInPrepareHeader(WaveIn,WaveHdr2,sizeof(WAVEHDR));
|
xue@0
|
1249
|
xue@0
|
1250 waveInAddBuffer(WaveIn,WaveHdr1,sizeof(WAVEHDR));
|
xue@0
|
1251 waveInAddBuffer(WaveIn,WaveHdr2,sizeof(WAVEHDR));
|
xue@0
|
1252
|
xue@0
|
1253 ResetInStream=false;
|
xue@0
|
1254 ResetInUser=false;
|
xue@0
|
1255 FRecording=true;
|
xue@0
|
1256
|
xue@0
|
1257 waveInStart(WaveIn);
|
xue@0
|
1258
|
xue@0
|
1259 if (FOnStartRecording) FOnStartRecording(this);
|
xue@0
|
1260 }
|
xue@0
|
1261
|
xue@0
|
1262 //---------------------------------------------------------------------------
|
xue@0
|
1263 __fastcall TWaveAudio::TWaveAudio(TComponent* Owner)
|
xue@0
|
1264 : TComponent(Owner)
|
xue@0
|
1265 {
|
xue@0
|
1266 FBlockSize=12288;
|
xue@0
|
1267 FStreamLimit=0;
|
xue@0
|
1268 FUseMemoryStream=true;
|
xue@0
|
1269 FAutoUseMemoryStream=true;
|
xue@0
|
1270 FMemoryStream=new TMemoryStream;
|
xue@0
|
1271 FFileStream=new TAttachFileStream(NULL);
|
xue@0
|
1272
|
xue@0
|
1273 FPlaying=false;
|
xue@0
|
1274 FRecording=false;
|
xue@0
|
1275 FPaused=false;
|
xue@0
|
1276
|
xue@0
|
1277 FOnAudioChange=0;
|
xue@0
|
1278 FOnStartPlayback=0;
|
xue@0
|
1279 FOnStartRecording=0;
|
xue@0
|
1280 FOnPlaybackDone=0;
|
xue@0
|
1281 FOnRecordingDone=0;
|
xue@0
|
1282 FOnStreamLimitFailure=0;
|
xue@0
|
1283 FOnStreamFull=0;
|
xue@0
|
1284 FOnPlaybackProgress=0;
|
xue@0
|
1285 FOnPlaybackProg=0;
|
xue@0
|
1286 FOnInAddBuffer=0;
|
xue@0
|
1287 FOnOutWrite=0;
|
xue@0
|
1288
|
xue@0
|
1289 FSamplesPerSec=44100;
|
xue@0
|
1290 FBitsPerSample=16;
|
xue@0
|
1291 FChannels=1;
|
xue@0
|
1292 FFileName="";
|
xue@0
|
1293
|
xue@0
|
1294 FFormatTag=WAVE_FORMAT_PCM;
|
xue@0
|
1295 FcbSize=0; //ignored for PCM
|
xue@0
|
1296 FAvgBytesPerSec=FSamplesPerSec*FBitsPerSample*FChannels/8;
|
xue@0
|
1297 FBlockAlign=FBitsPerSample*FChannels/8;
|
xue@0
|
1298
|
xue@0
|
1299 HWndOut=AllocateHWnd(WaveOutProc);
|
xue@0
|
1300 HWndIn=AllocateHWnd(WaveInProc);
|
xue@0
|
1301
|
xue@0
|
1302 unsigned long Volume;
|
xue@0
|
1303 waveOutGetVolume((void *)WAVE_MAPPER, &Volume);
|
xue@0
|
1304 FLVolume=Volume&0x0000FFFF;
|
xue@0
|
1305 FRVolume=Volume>>16;
|
xue@0
|
1306 }
|
xue@0
|
1307
|
xue@0
|
1308
|
xue@0
|
1309 //---------------------------------------------------------------------------
|
xue@0
|
1310 void __fastcall TWaveAudio::WaveInProc(TMessage& Message)
|
xue@0
|
1311 {
|
xue@0
|
1312 switch(Message.Msg)
|
xue@0
|
1313 {
|
xue@0
|
1314 case MM_WIM_OPEN: OnWimOpen(Message); break;
|
xue@0
|
1315 case MM_WIM_DATA: OnWimData(Message); break;
|
xue@0
|
1316 case MM_WIM_CLOSE: OnWimClose(Message); break;
|
xue@0
|
1317 }
|
xue@0
|
1318 }
|
xue@0
|
1319
|
xue@0
|
1320 //---------------------------------------------------------------------------
|
xue@0
|
1321 void __fastcall TWaveAudio::WaveOutProc(TMessage& Message)
|
xue@0
|
1322 {
|
xue@0
|
1323 switch(Message.Msg)
|
xue@0
|
1324 {
|
xue@0
|
1325 case MM_WOM_OPEN: OnWomOpen(Message); break;
|
xue@0
|
1326 case MM_WOM_DONE: OnWomDone(Message); break;
|
xue@0
|
1327 case MM_WOM_CLOSE: OnWomClose(Message); break;
|
xue@0
|
1328 }
|
xue@0
|
1329 }
|
xue@0
|
1330
|
xue@0
|
1331 //---------------------------------------------------------------------------
|
xue@0
|
1332 int __fastcall TWaveAudio::Write(void* Buffer, int Count)
|
xue@0
|
1333 {
|
xue@0
|
1334 if (!FUseMemoryStream)
|
xue@0
|
1335 {
|
xue@0
|
1336 int Position=FFileStream->Position;
|
xue@0
|
1337 delete FFileStream->File;
|
xue@0
|
1338 FFileStream->File=new TFileStream(FFileName, fmOpenWrite);
|
xue@0
|
1339 FFileStream->Position=Position;
|
xue@0
|
1340 }
|
xue@0
|
1341 int result=Stream->Write(Buffer, Count);
|
xue@0
|
1342 if (!FUseMemoryStream)
|
xue@0
|
1343 {
|
xue@0
|
1344 int Position=FFileStream->Position;
|
xue@0
|
1345 delete FFileStream->File;
|
xue@0
|
1346 FFileStream->File=new TFileStream(FFileName, fmOpenRead);
|
xue@0
|
1347 FFileStream->Position=Position;
|
xue@0
|
1348 }
|
xue@0
|
1349 if (FOnAudioChange) FOnAudioChange(this);
|
xue@0
|
1350 return result;
|
xue@0
|
1351 }
|
xue@0
|
1352
|
xue@0
|
1353 int __fastcall TWaveAudio::WriteSamples(void* Buffer, int Count)
|
xue@0
|
1354 {
|
xue@0
|
1355 if (!FUseMemoryStream)
|
xue@0
|
1356 {
|
xue@0
|
1357 int Position=FFileStream->Position;
|
xue@0
|
1358 delete FFileStream->File;
|
xue@0
|
1359 FFileStream->File=new TFileStream(FFileName, fmOpenWrite);
|
xue@0
|
1360 FFileStream->Position=Position;
|
xue@0
|
1361 }
|
xue@0
|
1362 int result=Stream->Write(Buffer, Count*FChannels*FBitsPerSample/8);
|
xue@0
|
1363 if (!FUseMemoryStream)
|
xue@0
|
1364 {
|
xue@0
|
1365 int Position=FFileStream->Position;
|
xue@0
|
1366 delete FFileStream->File;
|
xue@0
|
1367 FFileStream->File=new TFileStream(FFileName, fmOpenRead);
|
xue@0
|
1368 FFileStream->Position=Position;
|
xue@0
|
1369 }
|
xue@0
|
1370 if (FOnAudioChange) FOnAudioChange(this);
|
xue@0
|
1371 return result;
|
xue@0
|
1372 }
|
xue@0
|
1373
|
xue@0
|
1374 int __fastcall TWaveAudio::WriteSamples(double* Buffer, int Count)
|
xue@0
|
1375 {
|
xue@0
|
1376 int result=0;
|
xue@0
|
1377 if (!FUseMemoryStream)
|
xue@0
|
1378 {
|
xue@0
|
1379 int Position=FFileStream->Position;
|
xue@0
|
1380 delete FFileStream->File;
|
xue@0
|
1381 FFileStream->File=new TFileStream(FFileName, fmOpenWrite);
|
xue@0
|
1382 FFileStream->Position=Position;
|
xue@0
|
1383 }
|
xue@0
|
1384
|
xue@0
|
1385 int FBytesPerSample=FBitsPerSample/8;
|
xue@0
|
1386 if (FUseMemoryStream)
|
xue@0
|
1387 {
|
xue@0
|
1388 int Position=FMemoryStream->Position;
|
xue@0
|
1389 result=Count*FBytesPerSample;
|
xue@0
|
1390 if (FMemoryStream->Size<Position+result) FMemoryStream->Size=Position+result;
|
xue@0
|
1391 DoubleToInt(&((char*)FMemoryStream->Memory)[Position], FBytesPerSample, Buffer, Count);
|
xue@0
|
1392 FMemoryStream->Position=Position+result;
|
xue@0
|
1393 }
|
xue@0
|
1394 else
|
xue@0
|
1395 {
|
xue@0
|
1396 void *data=new char[FBlockSize];
|
xue@0
|
1397 double *Data=Buffer;
|
xue@0
|
1398 int CountPF=FBlockSize/FBytesPerSample;
|
xue@0
|
1399 int Fr=(Count/CountPF);
|
xue@0
|
1400 for (int i=0; i<Fr; i++)
|
xue@0
|
1401 {
|
xue@0
|
1402 DoubleToInt(data, FBytesPerSample, Data, CountPF);
|
xue@0
|
1403 result+=Stream->Write(data, FBlockSize);
|
xue@0
|
1404 Data=&Data[CountPF];
|
xue@0
|
1405 }
|
xue@0
|
1406 int CountLastF=Count%CountPF;
|
xue@0
|
1407 int lastblocksize=CountLastF*FBytesPerSample;
|
xue@0
|
1408 DoubleToInt(data, FBytesPerSample, Data, CountLastF);
|
xue@0
|
1409 result+=Stream->Write(data, lastblocksize);
|
xue@0
|
1410 delete[] data;
|
xue@0
|
1411 }
|
xue@0
|
1412
|
xue@0
|
1413 if (!FUseMemoryStream)
|
xue@0
|
1414 {
|
xue@0
|
1415 int Position=FFileStream->Position;
|
xue@0
|
1416 delete FFileStream->File;
|
xue@0
|
1417 FFileStream->File=new TFileStream(FFileName, fmOpenRead);
|
xue@0
|
1418 FFileStream->Position=Position;
|
xue@0
|
1419 }
|
xue@0
|
1420 if (FOnAudioChange) FOnAudioChange(this);
|
xue@0
|
1421 return result;
|
xue@0
|
1422 }
|
xue@0
|
1423
|
xue@0
|
1424 int __fastcall TWaveAudio::WriteSamplesInterleave(void* Buffer1, void* Buffer2, int Count)
|
xue@0
|
1425 {
|
xue@0
|
1426 int FBytesPerSample=FBitsPerSample/8;
|
xue@0
|
1427 int SampleSize=FBytesPerSample*2;
|
xue@0
|
1428 if (FUseMemoryStream)
|
xue@0
|
1429 {
|
xue@0
|
1430 int Position=FMemoryStream->Position;
|
xue@0
|
1431 int countavailable=(FMemoryStream->Size-Position)/SampleSize;
|
xue@0
|
1432 if (countavailable<Count) FMemoryStream->Size=Position+SampleSize*Count;
|
xue@0
|
1433 IntToIntInterleave(&((char*)FMemoryStream->Memory)[Position], FBytesPerSample, Buffer1, Buffer2, Count);
|
xue@0
|
1434 FMemoryStream->Position=Position+SampleSize*Count;
|
xue@0
|
1435 }
|
xue@0
|
1436 else
|
xue@0
|
1437 {
|
xue@0
|
1438 int Position=Stream->Position;
|
xue@0
|
1439 delete FFileStream->File;
|
xue@0
|
1440 FFileStream->File=new TFileStream(FFileName, fmOpenWrite);
|
xue@0
|
1441 FFileStream->Position=Position;
|
xue@0
|
1442
|
xue@0
|
1443 int CountPF=FBlockSize/SampleSize, HBlockSize=FBlockSize/2;
|
xue@0
|
1444 int Fr=Count/CountPF;
|
xue@0
|
1445 void *Data1=Buffer1, *Data2=Buffer2, *data=new char[FBlockSize];
|
xue@0
|
1446 for (int i=0; i<Fr; i++)
|
xue@0
|
1447 {
|
xue@0
|
1448 IntToIntInterleave(data, FBytesPerSample, Data1, Data2, CountPF);
|
xue@0
|
1449 Stream->Write(data, FBlockSize);
|
xue@0
|
1450 Data1=&((char*)Data1)[HBlockSize], Data2=&((char*)Data2)[HBlockSize];
|
xue@0
|
1451 }
|
xue@0
|
1452 int CountLastF=Count%CountPF;
|
xue@0
|
1453 int lastblocksize=CountLastF*SampleSize;
|
xue@0
|
1454 IntToIntInterleave(data, FBytesPerSample, Data1, Data2, CountLastF);
|
xue@0
|
1455 Stream->Write(data, lastblocksize);
|
xue@0
|
1456
|
xue@0
|
1457 Position=Stream->Position;
|
xue@0
|
1458 delete FFileStream->File;
|
xue@0
|
1459 FFileStream->File=new TFileStream(FFileName, fmOpenRead);
|
xue@0
|
1460 FFileStream->Position=Position;
|
xue@0
|
1461 }
|
xue@0
|
1462 if (FOnAudioChange) FOnAudioChange(this);
|
xue@0
|
1463 return Count*SampleSize;
|
xue@0
|
1464 }
|
xue@0
|
1465
|
xue@0
|
1466 int __fastcall TWaveAudio::WriteSamplesInterleave(double* Buffer1, double* Buffer2, int Count)
|
xue@0
|
1467 {
|
xue@0
|
1468 int FBytesPerSample=FBitsPerSample/8;
|
xue@0
|
1469 int SampleSize=FBytesPerSample*2;
|
xue@0
|
1470 if (FUseMemoryStream)
|
xue@0
|
1471 {
|
xue@0
|
1472 int Position=FMemoryStream->Position;
|
xue@0
|
1473 int countavailable=(FMemoryStream->Size-Position)/SampleSize;
|
xue@0
|
1474 if (countavailable<Count) FMemoryStream->Size=Position+SampleSize*Count;
|
xue@0
|
1475 DoubleToIntInterleave(&((char*)FMemoryStream->Memory)[Position], FBytesPerSample, Buffer1, Buffer2, Count);
|
xue@0
|
1476 FMemoryStream->Position=Position+SampleSize*Count;
|
xue@0
|
1477 }
|
xue@0
|
1478 else
|
xue@0
|
1479 {
|
xue@0
|
1480 int Position=Stream->Position;
|
xue@0
|
1481 delete FFileStream->File;
|
xue@0
|
1482 FFileStream->File=new TFileStream(FFileName, fmOpenWrite);
|
xue@0
|
1483 FFileStream->Position=Position;
|
xue@0
|
1484
|
xue@0
|
1485 int CountPF=FBlockSize/SampleSize;
|
xue@0
|
1486 int Fr=Count/CountPF;
|
xue@0
|
1487 double *Data1=Buffer1, *Data2=Buffer2;
|
xue@0
|
1488 void *data=new char[FBlockSize];
|
xue@0
|
1489 for (int i=0; i<Fr; i++)
|
xue@0
|
1490 {
|
xue@0
|
1491 DoubleToIntInterleave(data, FBytesPerSample, Data1, Data2, CountPF);
|
xue@0
|
1492 Stream->Write(data, FBlockSize);
|
xue@0
|
1493 Data1=&Data1[CountPF], Data2=&Data2[CountPF];
|
xue@0
|
1494 }
|
xue@0
|
1495 int CountLastF=Count%CountPF;
|
xue@0
|
1496 int lastblocksize=CountLastF*SampleSize;
|
xue@0
|
1497 DoubleToIntInterleave(data, FBytesPerSample, Data1, Data2, CountLastF);
|
xue@0
|
1498 Stream->Write(data, lastblocksize);
|
xue@0
|
1499
|
xue@0
|
1500 Position=Stream->Position;
|
xue@0
|
1501 delete FFileStream->File;
|
xue@0
|
1502 FFileStream->File=new TFileStream(FFileName, fmOpenRead);
|
xue@0
|
1503 FFileStream->Position=Position;
|
xue@0
|
1504 }
|
xue@0
|
1505 if (FOnAudioChange) FOnAudioChange(this);
|
xue@0
|
1506 return Count*SampleSize;
|
xue@0
|
1507 }
|
xue@0
|
1508 //---------------------------------------------------------------------------
|
xue@0
|
1509 __fastcall TDataAudio::TDataAudio(TComponent* Owner)
|
xue@0
|
1510 : TWaveAudio(Owner)
|
xue@0
|
1511 {
|
xue@0
|
1512 FCustomFillBlock=0;
|
xue@0
|
1513 }
|
xue@0
|
1514
|
xue@0
|
1515 int __fastcall TDataAudio::FillBlock(void* Block)
|
xue@0
|
1516 {
|
xue@0
|
1517 if (FCustomFillBlock)
|
xue@0
|
1518 return FCustomFillBlock(Block);
|
xue@0
|
1519 else
|
xue@0
|
1520 return TWaveAudio::FillBlock(Block);
|
xue@0
|
1521 }
|
xue@0
|
1522
|
xue@0
|
1523 //---------------------------------------------------------------------------
|
xue@0
|
1524 namespace Audiopac
|
xue@0
|
1525 {
|
xue@0
|
1526 void __fastcall PACKAGE Register()
|
xue@0
|
1527 {
|
xue@0
|
1528 TComponentClass classes[1] = {__classid(TWaveAudio)};
|
xue@0
|
1529 RegisterComponents("Samples", classes, 0);
|
xue@0
|
1530 }
|
xue@0
|
1531 }
|
xue@0
|
1532 //---------------------------------------------------------------------------
|
xue@0
|
1533
|
xue@0
|
1534
|