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