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 #ifndef AudioPacH
|
xue@0
|
15 #define AudioPacH
|
xue@0
|
16 //---------------------------------------------------------------------------
|
xue@0
|
17 /*
|
xue@0
|
18
|
xue@0
|
19 AudioPac.cpp implements a VCL component for linear PCM waveform audio operations on
|
xue@0
|
20 Windows using Win32 WAVEMAPPER device.
|
xue@0
|
21
|
xue@0
|
22 Component class TWaveAudio
|
xue@0
|
23 TWaveAudio is a VCL component that incapsulates the basic waveform audio i/o functions.
|
xue@0
|
24
|
xue@0
|
25 Properties
|
xue@0
|
26
|
xue@0
|
27 readwrite AutoUseMemoryStream
|
xue@0
|
28 readonly AvgBytesPerSec
|
xue@0
|
29 readwrite BitsPerSample
|
xue@0
|
30 readonly BlockAlign
|
xue@0
|
31 readwrite BlockSize
|
xue@0
|
32 readonly BytesPerSample
|
xue@0
|
33 readonly cbSize
|
xue@0
|
34 readwrite Channels
|
xue@0
|
35 readonly FileName
|
xue@0
|
36 readonly FormatTag
|
xue@0
|
37 readonly Length
|
xue@0
|
38 readwrite LVolume
|
xue@0
|
39 readonly Paused
|
xue@0
|
40 readonly Playing
|
xue@0
|
41 readonly Recording
|
xue@0
|
42 readwrite RVolume
|
xue@0
|
43 readwrite SamplesPerSec
|
xue@0
|
44 readwrite StreamLimit
|
xue@0
|
45 readwrite UseMemoryStream
|
xue@0
|
46 readonly WaveStream
|
xue@0
|
47
|
xue@0
|
48
|
xue@0
|
49 AutoUseMemoryStream
|
xue@0
|
50 If set, the component automatically set UseMemoryStream to false when calling
|
xue@0
|
51 LoadFromFile(...).
|
xue@0
|
52
|
xue@0
|
53 AvgBytesPerSec
|
xue@0
|
54 Standard waveform format property.
|
xue@0
|
55
|
xue@0
|
56 BitsPerSample
|
xue@0
|
57 Standard waveform format property. Usually 8, 16 or 24.
|
xue@0
|
58
|
xue@0
|
59 BlockAlign
|
xue@0
|
60 Standard waveform property. Gives the size of a multi-channels sample.
|
xue@0
|
61
|
xue@0
|
62 BlockSize
|
xue@0
|
63 Standard waveform format property. Specifies the size, in bytes, of the data
|
xue@0
|
64 block used for audio recording and playback. In AudioPac42.cpp a total of
|
xue@0
|
65 two data blocks are used.
|
xue@0
|
66
|
xue@0
|
67 BytesPerSample
|
xue@0
|
68 Equals BitsPerSample/8.
|
xue@0
|
69
|
xue@0
|
70 cbSize
|
xue@0
|
71 Standard waveform format property. Reserved.
|
xue@0
|
72
|
xue@0
|
73 Channels
|
xue@0
|
74 Standard waveform format property. Specifies the number of channels.
|
xue@0
|
75
|
xue@0
|
76 FileName
|
xue@0
|
77 The name of the file last loaded or inserted into this waveform.
|
xue@0
|
78
|
xue@0
|
79 FormatTag
|
xue@0
|
80 Standard waveform format property. Must be WAVE_FORMAT_PCM.
|
xue@0
|
81
|
xue@0
|
82 Length
|
xue@0
|
83 The length of waveform data held, in multi-channel samples.
|
xue@0
|
84
|
xue@0
|
85 LVolume
|
xue@0
|
86 Specifies the playback volume of left channel.
|
xue@0
|
87
|
xue@0
|
88 Paused
|
xue@0
|
89 Gives whether the playback is being suspended in pause mode.
|
xue@0
|
90
|
xue@0
|
91 Playing
|
xue@0
|
92 Gives whether the playback is in progress, whether or not suspended in pause
|
xue@0
|
93 mode.
|
xue@0
|
94
|
xue@0
|
95 Recording
|
xue@0
|
96 Gives whether the recording is in progress.
|
xue@0
|
97
|
xue@0
|
98 RVolume
|
xue@0
|
99 Specifies the playback volume of right channel.
|
xue@0
|
100
|
xue@0
|
101 SamplesPerSec
|
xue@0
|
102 Standard waveform format property. As is.
|
xue@0
|
103
|
xue@0
|
104 StreamLimit
|
xue@0
|
105 This property provides a way to control the size of wave stream. If StreamLimit>0,
|
xue@0
|
106 TWaveAudio will generate an StreamFull event when the size of wave stream
|
xue@0
|
107 goes above StreamLimit. StreamLimit is set to zero by default.
|
xue@0
|
108
|
xue@0
|
109 UseMemoryStream
|
xue@0
|
110 Specifies whether the component loads the data samples into a memory stream.
|
xue@0
|
111 If UseMemoryStream is set, a MemoryStream object is used to store the data
|
xue@0
|
112 samples in the memroy. If UseMemoryStream is set to false, the WaveAudio must
|
xue@0
|
113 be working on a wave file, where data samples are read from. Recording is
|
xue@0
|
114 not allowed when UseMemoryStream is false.
|
xue@0
|
115
|
xue@0
|
116 WaveStream
|
xue@0
|
117 The pointer to the Stream object that holds the data samples. If UseMemoryStream
|
xue@0
|
118 is true, the stream is a MemoryStream. If false, the stream is an AttachFileStream,
|
xue@0
|
119 which is based on a FileStream. The data samples are stored right from the
|
xue@0
|
120 beginning of WaveStream.
|
xue@0
|
121
|
xue@0
|
122
|
xue@0
|
123 Methods:
|
xue@0
|
124
|
xue@0
|
125 TWaveAudio & ~TWaveAudio
|
xue@0
|
126 Default constructor and destructor.
|
xue@0
|
127
|
xue@0
|
128 void Clear();
|
xue@0
|
129 void CloseFile(bool Close);
|
xue@0
|
130 void CopyFrom(TStream* AStream, int Count);
|
xue@0
|
131 void CopyFrom(TWaveAudio* AWaveAudio, int Count);
|
xue@0
|
132 void CopySamplesFrom(TStream* AStream, int Count);
|
xue@0
|
133 void CopySamplesFrom(TWaveAudio* AWaveAudio, int Count);
|
xue@0
|
134 void CreateFile(AnsiString FileName);
|
xue@0
|
135 void GetWaveProperties(TWaveAudio* WaveAudio1);
|
xue@0
|
136 void InsertFromFile(AnsiString FileName);
|
xue@0
|
137 bool IsValidWave(AnsiString FileName);
|
xue@0
|
138 void LoadFromFile(AnsiString FileName);
|
xue@0
|
139 void Pause();
|
xue@0
|
140 void PausePlayback();
|
xue@0
|
141 void PauseRecording();
|
xue@0
|
142 void Play();
|
xue@0
|
143 void Play(TNotifyEvent AnOnPlaybackDone);
|
xue@0
|
144 int Read(void* Buffer, int Count);
|
xue@0
|
145 bool ReadHeader(TStream* AStream, __int32& length, bool allowunfinisheddata);
|
xue@0
|
146 int ReadSamples(void* Buffer, int Count);
|
xue@0
|
147 int ReadSamples(double* Buffer, int Count);
|
xue@0
|
148 int ReadSamplesMultiChannel(int C, void** Buffer, int Count);
|
xue@0
|
149 int ReadSamplesMultiSingle(void* Buffer, int Channel, int Count);
|
xue@0
|
150 int ReadSamplesInterleave(void* Buffer1, void* Buffer2, int Count);
|
xue@0
|
151 void Restart();
|
xue@0
|
152 void Rewind();
|
xue@0
|
153 void SaveHeader(TStream* AStream);
|
xue@0
|
154 void SaveToFile(AnsiString FileName);
|
xue@0
|
155 void Seek(int Offset, WORD Origin);
|
xue@0
|
156 void SeekSamples(int Offset, WORD Origin);
|
xue@0
|
157 void StartPlayback();
|
xue@0
|
158 void StartRecording();
|
xue@0
|
159 int Write(void* Buffer, int Count);
|
xue@0
|
160 int WriteSamples(void* Buffer, int Count);
|
xue@0
|
161 int WriteSamples(double* Buffer, int Count);
|
xue@0
|
162 int WriteSamplesInterleave(void* Buffer1, void* Buffer2, int Count);
|
xue@0
|
163 int WriteSamplesInterleave(double* Buffer1, double* Buffer2, int Count);
|
xue@0
|
164
|
xue@0
|
165 Clear()
|
xue@0
|
166 Clear the stored sound in the stream. Be cautious using Clear() when UseMemoryStream
|
xue@0
|
167 is true.
|
xue@0
|
168
|
xue@0
|
169 CloseFile(bool Close)
|
xue@0
|
170 Effective only if UseMemoryStream is false. A call to this method flushes the
|
xue@0
|
171 audio content to the current working FileStream, closes the file handle of,
|
xue@0
|
172 and reopens the audio file as a new FileStream if Close is false.
|
xue@0
|
173
|
xue@0
|
174 CopyFrom(TStream* AStream, int Count)
|
xue@0
|
175 The same as WaveStream->CopyFrom(AStream, Count)
|
xue@0
|
176
|
xue@0
|
177 CopyFrom(TWaveAudio* AWaveAudio, int Count)
|
xue@0
|
178 The same as WaveStream->CopyFrom(AWaveAudio->WaveStream, Count)
|
xue@0
|
179
|
xue@0
|
180 CopySamplesFrom(TStream* AStream, int Count)
|
xue@0
|
181 Similar to CopyFrom(AStream, Count), yet Count indicates the number of multi-channel
|
xue@0
|
182 samples to be copied, not bytes.
|
xue@0
|
183
|
xue@0
|
184 CopySamplesFrom(TWaveAudio* AWaveAudio, int Count)
|
xue@0
|
185 Similar to CopyFrom(AWaveAudio, Count), yet Count indicates the numbet of
|
xue@0
|
186 multi-channel samples to be copied, not bytes.
|
xue@0
|
187
|
xue@0
|
188 CreateFile(AnsiString FileName)
|
xue@0
|
189 Creates a new empty audio file as the current working audio stream.
|
xue@0
|
190
|
xue@0
|
191 GetWaveProperties(TWaveAudio* WaveAudio1)
|
xue@0
|
192 Fill the standard waveform audio properties with those of WaveAudio1.
|
xue@0
|
193
|
xue@0
|
194 InsertFromFile(AnsiString FileName)
|
xue@0
|
195 Loads in a wave file while giving up the previous content. It also sets the
|
xue@0
|
196 FileName property.
|
xue@0
|
197
|
xue@0
|
198 IsValidWave(AnsiString FileName)
|
xue@0
|
199 Judge if a file specified with FileName is an valid waveform audio file.
|
xue@0
|
200
|
xue@0
|
201 LoadFromFile(AnsiString FileName)
|
xue@0
|
202 Almost the same as InsertFromFile(...) but triggers the OnBeforeLoad and OnLoad events
|
xue@0
|
203 as well.
|
xue@0
|
204
|
xue@0
|
205 Pause()
|
xue@0
|
206 Suspends on-going playback in pause mode. It sets Paused property.
|
xue@0
|
207
|
xue@0
|
208 PausePlayback()
|
xue@0
|
209 Terminate playback. It also resets the Playing property and triggers an OnPlaybackDone
|
xue@0
|
210 event.
|
xue@0
|
211
|
xue@0
|
212 PauseRecording()
|
xue@0
|
213 Terminate recording. It also resets the Recording property.
|
xue@0
|
214
|
xue@0
|
215 Play()
|
xue@0
|
216 Rewind() then StartPlayback().
|
xue@0
|
217
|
xue@0
|
218 Play(TNotifyEvent AnOnPlaybackDone)
|
xue@0
|
219 Rewind() then StartPlayback() with AnOnPlaybackDone assigned to OnPlaybackDone
|
xue@0
|
220 event. It is recommended that OnPlaybackDone be assigned at designtime rather
|
xue@0
|
221 than at runtime.
|
xue@0
|
222
|
xue@0
|
223 Read(void* Buffer, int Count)
|
xue@0
|
224 The same as WaveStream->Read(Buffer, Count).
|
xue@0
|
225
|
xue@0
|
226 ReadHeader(TStream* AStream, __int32& length, bool allowunfinisheddata)
|
xue@0
|
227 Reads RIFF waveform header from AStream.
|
xue@0
|
228
|
xue@0
|
229 ReadSamples(void* Buffer, int Count)
|
xue@0
|
230 ReadSamples(double* Buffer, int Count);
|
xue@0
|
231 Similar to Read(...), but Count is given in multi-channel samples, not in bytes.
|
xue@0
|
232
|
xue@0
|
233 ReadSamplesInterleave(void* Buffer1, void* Buffer2, int Count)
|
xue@0
|
234 ReadSamplesInterleave(double* Buffer1, double* Buffer2, int Count)
|
xue@0
|
235 Reads interleaved stereo data into two data buffers.
|
xue@0
|
236
|
xue@0
|
237 ReadSamplesMultiChannel(int C, void** Buffer, int Count)
|
xue@0
|
238 Reads multi-channel audio stream into multiple buffers, one for each channel.
|
xue@0
|
239
|
xue@0
|
240 ReadSamplesMultiSingle(void* Buffer, int Channel, int Count)
|
xue@0
|
241 Reads the data of one channel from a multi-channel WaveAudio into a data buffer.
|
xue@0
|
242
|
xue@0
|
243 Restart()
|
xue@0
|
244 Resumes playback suspended in pause mode. It resets Paused property as well.
|
xue@0
|
245
|
xue@0
|
246 Rewind()
|
xue@0
|
247 Set the position of Stream to the beginning.
|
xue@0
|
248
|
xue@0
|
249 SaveHeader(TStream* AStream)
|
xue@0
|
250 Saves RIFF waveform header to AStream.
|
xue@0
|
251
|
xue@0
|
252 SaveToFile(AnsiString FileName)
|
xue@0
|
253 Saves current waveform stream to disk as a wave file.
|
xue@0
|
254
|
xue@0
|
255 Seek(int Offset, WORD Origin)
|
xue@0
|
256 The same as WaveStream->Seek(Offset, Origin).
|
xue@0
|
257
|
xue@0
|
258 SeekSamples(int Offset, WORD Origin)
|
xue@0
|
259 Similar to Seek(Offset, Origin), yet Offset is of the number of multi-channel samples,
|
xue@0
|
260 not bytes.
|
xue@0
|
261
|
xue@0
|
262 StartPlayback()
|
xue@0
|
263 Start playback, starting from the current position of wave stream. It sets
|
xue@0
|
264 Playing property. When playback is done, a PlaybackDone event is triggered
|
xue@0
|
265 Playing is reset.
|
xue@0
|
266
|
xue@0
|
267 StartRecording()
|
xue@0
|
268 Start recording. New data will be written to stream from the current position.
|
xue@0
|
269 Old data, if any, are overwritten. It sets the property Recording. Be cautious
|
xue@0
|
270 using StartRecording() when UseMemoryStream is true.
|
xue@0
|
271
|
xue@0
|
272 Write(void* Buffer, int Count)
|
xue@0
|
273 The same as WaveStream->Write(Buffer, Count). Be cautious using Write(...)
|
xue@0
|
274 when UseMemoryStream is false as in this case the audio file is overwritten.
|
xue@0
|
275
|
xue@0
|
276 WriteSamples(void* Buffer, int Count)
|
xue@0
|
277 WriteSamples(double* Buffer, int Count)
|
xue@0
|
278 Similar to Write(...), but Count is given in multi-channel samples, not in
|
xue@0
|
279 bytes. By cautious using WriteSamples when UseMemoryStream is false as in
|
xue@0
|
280 this case the audio file is overwritten.
|
xue@0
|
281
|
xue@0
|
282 WriteSamplesInterleave(void* Buffer1, void* Buffer2, int Count)
|
xue@0
|
283 WriteSamplesInterleave(double* Buffer1, double* Buffer2, int Count)
|
xue@0
|
284 Writes stereo data in two data buffers into the interleaved format of WaveAudio.
|
xue@0
|
285 Be cautious using WriteSamplesInterleave when UseMemoryStream is false as
|
xue@0
|
286 in this case the audio file is overwritten.
|
xue@0
|
287
|
xue@0
|
288
|
xue@0
|
289 Events:
|
xue@0
|
290
|
xue@0
|
291 OnAudioChange
|
xue@0
|
292 OnBeforeLoad
|
xue@0
|
293 OnInAddBuffer
|
xue@0
|
294 OnLoad
|
xue@0
|
295 OnOutWrite
|
xue@0
|
296 OnPlaybackDone
|
xue@0
|
297 OnPlaybackProg
|
xue@0
|
298 OnPlaybackProgress
|
xue@0
|
299 OnRecordingDone
|
xue@0
|
300 OnStartPlayback
|
xue@0
|
301 OnStartRecording
|
xue@0
|
302 OnStreamFull
|
xue@0
|
303 OnStreamLimitFailure
|
xue@0
|
304
|
xue@0
|
305
|
xue@0
|
306 OnAudioChange
|
xue@0
|
307 Triggered when the contents of the audio changes. This happens in the following cases:
|
xue@0
|
308 1. InsertFromFile method is called.
|
xue@0
|
309 2. A recording is finished.
|
xue@0
|
310 3. CopyFrom or CopySamplesFrom method is called.
|
xue@0
|
311 4. Clear method is called.
|
xue@0
|
312 The change of audio content by calling methods of WaveAudio is not informed by this event.
|
xue@0
|
313
|
xue@0
|
314 OnBeforeLoad
|
xue@0
|
315 Triggered when a wave file is to be loaded.
|
xue@0
|
316
|
xue@0
|
317 OnInAddBuffer
|
xue@0
|
318 Triggered after a block received from the WaveIn device is released into local
|
xue@0
|
319 data memory and the data block is returned to the WaveIn device. Handle this
|
xue@0
|
320 event to access the latest received data in real time.
|
xue@0
|
321
|
xue@0
|
322 OnLoad
|
xue@0
|
323 Triggered when a wave file is loaded.
|
xue@0
|
324
|
xue@0
|
325 OnOutWrite
|
xue@0
|
326 Triggered when a data block has been sent to the WaveOut device.
|
xue@0
|
327
|
xue@0
|
328 OnPlaybackDone
|
xue@0
|
329 Triggered when playback is finished, whetherever PausePlayback method is called.
|
xue@0
|
330
|
xue@0
|
331 OnPlaybackProg
|
xue@0
|
332 OnPlaybackProgress
|
xue@0
|
333 Triggered after each output data block is sent, and when playback is finished.
|
xue@0
|
334 The two eveent differs in a progress parameter. While OnPlaybackProg uses an
|
xue@0
|
335 integer parameter indicating the progress position in bytes, OnPlaybackProgress
|
xue@0
|
336 uses a floating-point parameter indicating the progress position in percentage.
|
xue@0
|
337
|
xue@0
|
338 OnRecordingDone
|
xue@0
|
339 Triggered when recording is terminated and the WaveIn device is to be closed.
|
xue@0
|
340
|
xue@0
|
341 OnStartPlayback
|
xue@0
|
342 Triggered when playback is started.
|
xue@0
|
343
|
xue@0
|
344 OnStartRecording
|
xue@0
|
345 Triggered when recording is started.
|
xue@0
|
346
|
xue@0
|
347 OnStreamFull
|
xue@0
|
348 Triggered when the size of wave stream exceeds StreamLimit. No other operations
|
xue@0
|
349 are done by TWaveForm. Application must handle this event to perform actual
|
xue@0
|
350 size limit.
|
xue@0
|
351
|
xue@0
|
352 OnStreamLimitFailure
|
xue@0
|
353 Triggered when trying to set StreamLimit to a value smaller than the current
|
xue@0
|
354 size of wave stream. TWaveAudio refuses this operation and generates the event.
|
xue@0
|
355
|
xue@0
|
356
|
xue@0
|
357 Exceptions:
|
xue@0
|
358
|
xue@0
|
359 "Failed opening device WaveIn"
|
xue@0
|
360 Form: StartRecording
|
xue@0
|
361 Thrown on failure of opening waveform audio input device.
|
xue@0
|
362
|
xue@0
|
363 "Failed opening devece WaveOut"
|
xue@0
|
364 From: StartPlayback
|
xue@0
|
365 Thrown on failure of opening waveform audio output device.
|
xue@0
|
366
|
xue@0
|
367
|
xue@0
|
368 Component class TDataAudio
|
xue@0
|
369 TDataAudio is a decendent class of TWaveAudio, providing an CustomFillBlock event
|
xue@0
|
370 to enable on-the-fly data calculation for playback.
|
xue@0
|
371
|
xue@0
|
372 Events:
|
xue@0
|
373
|
xue@0
|
374 CustomFillBlock
|
xue@0
|
375 Triggered when a data block is to be filled by the application before sent to
|
xue@0
|
376 WaveOut device.
|
xue@0
|
377
|
xue@0
|
378 Current version Wen Xue 2009/7
|
xue@0
|
379 First version Wen Xue 2003/3
|
xue@0
|
380 */
|
xue@0
|
381
|
xue@0
|
382 //---------------------------------------------------------------------------
|
xue@0
|
383 //#include <SysUtils.hpp>
|
xue@0
|
384 //#include <Controls.hpp>
|
xue@0
|
385 //#include <Classes.hpp>
|
xue@0
|
386 //#include <Forms.hpp>
|
xue@0
|
387 //#include <Messages.hpp>
|
xue@0
|
388
|
xue@0
|
389 #include <mmsystem.h>
|
xue@0
|
390
|
xue@0
|
391 //---------------------------------------------------------------------------
|
xue@0
|
392 #ifndef INT24
|
xue@0
|
393 #define INT24
|
xue@0
|
394 struct __int24;
|
xue@0
|
395 struct __pint24
|
xue@0
|
396 {
|
xue@0
|
397 char* p;
|
xue@0
|
398 __pint24(){}
|
xue@0
|
399 __pint24(const void* ap){p=(char*)ap;}
|
xue@0
|
400 __pint24& operator=(const void* ap){p=(char*)ap; return *this;}
|
xue@0
|
401 __int24& operator*(){return *(__int24*)p;}
|
xue@0
|
402 __int24& operator[](int index){return *(__int24*)&p[3*index];}
|
xue@0
|
403 __pint24 operator++(int){__pint24 result=*this; p+=3; return result;}
|
xue@0
|
404 __pint24& operator++(){p+=3; return *this;}
|
xue@0
|
405 __pint24 operator--(int){__pint24 result=*this; p-=3; return result;}
|
xue@0
|
406 __pint24& operator--(){p-=3; return *this;}
|
xue@0
|
407 __pint24& operator+=(int a){p+=3*a; return *this;}
|
xue@0
|
408 __pint24& operator-=(int a){p-=3*a; return *this;}
|
xue@0
|
409 operator void*() const{return p;}
|
xue@0
|
410 };
|
xue@0
|
411 struct __int24
|
xue@0
|
412 {
|
xue@0
|
413 __int16 loword;
|
xue@0
|
414 __int8 hibyte;
|
xue@0
|
415 __int24(){}
|
xue@0
|
416 __int24(const __int32 a){loword=*(__int16*)&a; hibyte=((__int16*)&a)[1];}
|
xue@0
|
417 __int24(const double f){__int32 a=f; loword=*(__int16*)&a; hibyte=((__int16*)&a)[1];}
|
xue@0
|
418 __int24& operator=(const __int32 a){loword=*(__int16*)&a; hibyte=((__int16*)&a)[1]; return *this;}
|
xue@0
|
419 __int24& operator=(const double f){__int32 a=f; loword=*(__int16*)&a; hibyte=((__int16*)&a)[1]; return *this;}
|
xue@0
|
420 __int24& operator+=(const __int32 a){__int32 b=*this; b+=a; loword=*(__int16*)&b; hibyte=((__int16*)&b)[1]; return *this;}
|
xue@0
|
421 __int24& operator-=(const __int32 a){__int32 b=*this; b-=a; loword=*(__int16*)&b; hibyte=((__int16*)&b)[1]; return *this;}
|
xue@0
|
422 __int24& operator*=(const __int32 a){__int32 b=*this; b*=a; loword=*(__int16*)&b; hibyte=((__int16*)&b)[1]; return *this;}
|
xue@0
|
423 operator __int32() const{__int32 result; *(__int16*)&result=loword; ((__int16*)&result)[1]=hibyte; return result;}
|
xue@0
|
424 __pint24 operator &(){return (__pint24)this;}
|
xue@0
|
425 void* operator new[](size_t count){void* result=malloc(3*count); return result;}
|
xue@0
|
426 void operator delete[](void* p){free(p);}
|
xue@0
|
427 };
|
xue@0
|
428 #endif
|
xue@0
|
429
|
xue@0
|
430
|
xue@0
|
431 //---------------------------------------------------------------------------
|
xue@0
|
432 void DoubleToIntInterleave(void* _out, int BytesPerSample, double* in1, double* in2, int Count);
|
xue@0
|
433 void IntToDoubleInterleave(double* out1, double* out2, void* _in, int BytesPerSample, int Count);
|
xue@0
|
434 int IntToIntInterleave(void* dest, int bytesperunit, void* block1, void* block2, int Count);
|
xue@0
|
435 int IntToIntInterleave(void* dest1, void* dest2, int bytesperunit, void* block, int Count);
|
xue@0
|
436 int IntToIntMultiSingle(void* dest, int bytesperunit, int channels, int channel, void* block, int Count);
|
xue@0
|
437
|
xue@0
|
438 typedef void __fastcall (__closure *TWaveAudioPlaybackProgressEvent)(System::TObject* Sender, double PlaybackPosition);
|
xue@0
|
439
|
xue@0
|
440 class TAttachFileStream : public TStream
|
xue@0
|
441 {
|
xue@0
|
442 public:
|
xue@0
|
443 TFileStream* File;
|
xue@0
|
444 int StartOffset;
|
xue@0
|
445 int EndOffset;
|
xue@0
|
446 protected:
|
xue@0
|
447 virtual int __fastcall Seek(int AnOffset, Word Origin);
|
xue@0
|
448 virtual __int64 __fastcall Seek(const __int64 AnOffset, TSeekOrigin Origin);
|
xue@0
|
449 virtual int __fastcall Read(void *Buffer, int Count);
|
xue@0
|
450 virtual int __fastcall Write(const void *Buffer, int Count);
|
xue@0
|
451 public:
|
xue@0
|
452 __fastcall TAttachFileStream(TFileStream* AFileStream);
|
xue@0
|
453 __fastcall ~TAttachFileStream();
|
xue@0
|
454 };
|
xue@0
|
455
|
xue@0
|
456 class TWaveView;
|
xue@0
|
457 class PACKAGE TWaveAudio : public TComponent
|
xue@0
|
458 {
|
xue@0
|
459 friend TWaveView;
|
xue@0
|
460
|
xue@0
|
461 protected:
|
xue@0
|
462
|
xue@0
|
463 bool FUseMemoryStream;
|
xue@0
|
464 TMemoryStream* FMemoryStream;
|
xue@0
|
465 TAttachFileStream* FFileStream;
|
xue@0
|
466
|
xue@0
|
467 AnsiString FFileName;
|
xue@0
|
468 __int32 FSamplesPerSec;
|
xue@0
|
469 __int16 FBitsPerSample;
|
xue@0
|
470 __int16 FChannels;
|
xue@0
|
471 __int32 FAvgBytesPerSec;
|
xue@0
|
472 __int16 FBlockAlign;
|
xue@0
|
473 __int16 FFormatTag;
|
xue@0
|
474 __int16 FcbSize;
|
xue@0
|
475 unsigned __int16 FLVolume;
|
xue@0
|
476 unsigned __int16 FRVolume;
|
xue@0
|
477 int FStreamLimit;
|
xue@0
|
478 int FBlockSize;
|
xue@0
|
479
|
xue@0
|
480 TNotifyEvent FOnBeforeLoad;
|
xue@0
|
481 TNotifyEvent FOnAudioChange;
|
xue@0
|
482 TNotifyEvent FOnInAddBuffer;
|
xue@0
|
483 TNotifyEvent FOnLoad;
|
xue@0
|
484 TNotifyEvent FOnOutWrite;
|
xue@0
|
485 TNotifyEvent FOnPlaybackDone;
|
xue@0
|
486 TNotifyEvent FOnRecordingDone;
|
xue@0
|
487 TNotifyEvent FOnStartPlayback;
|
xue@0
|
488 TNotifyEvent FOnStartRecording;
|
xue@0
|
489 TNotifyEvent FOnStreamFull;
|
xue@0
|
490 TNotifyEvent FOnStreamLimitFailure;
|
xue@0
|
491
|
xue@0
|
492 TWaveAudioPlaybackProgressEvent FOnPlaybackProgress;
|
xue@0
|
493 TWaveAudioPlaybackProgressEvent FOnPlaybackProg;
|
xue@0
|
494
|
xue@0
|
495 bool FAutoUseMemoryStream;
|
xue@0
|
496 bool FRecording;
|
xue@0
|
497 bool FPlaying;
|
xue@0
|
498 bool FPaused;
|
xue@0
|
499
|
xue@0
|
500 __property TStream* Stream={read=GetStream};
|
xue@0
|
501
|
xue@0
|
502 public:
|
xue@0
|
503 HWAVEIN WaveIn;
|
xue@0
|
504 HWAVEOUT WaveOut;
|
xue@0
|
505
|
xue@0
|
506 protected:
|
xue@0
|
507 HWND HWndOut;
|
xue@0
|
508 HWND HWndIn;
|
xue@0
|
509
|
xue@0
|
510 WAVEHDR* WaveHdr1;
|
xue@0
|
511 WAVEHDR* WaveHdr2;
|
xue@0
|
512 void* Buffer1;
|
xue@0
|
513 void* Buffer2;
|
xue@0
|
514 bool ResetInStream;
|
xue@0
|
515 bool ResetInUser;
|
xue@0
|
516 bool ResetOut;
|
xue@0
|
517 bool ResetOutUser;
|
xue@0
|
518
|
xue@0
|
519 protected:
|
xue@0
|
520 virtual void __fastcall SetSamplesPerSec(__int32 ASamplesPerSec);
|
xue@0
|
521 virtual void __fastcall SetBitsPerSample(__int16 ABitsPerSample);
|
xue@0
|
522 virtual void __fastcall SetChannels(__int16 AChannels);
|
xue@0
|
523 virtual void __fastcall SetBlockSize(int ABlockSize);
|
xue@0
|
524 virtual void __fastcall SetStreamLimit(int AStreamLimit);
|
xue@0
|
525 virtual void __fastcall SetLVolume(unsigned __int16 ALVolume);
|
xue@0
|
526 virtual void __fastcall SetRVolume(unsigned __int16 ARVolume);
|
xue@0
|
527 virtual void __fastcall SetUseMemoryStream(bool AUseMemoryStream);
|
xue@0
|
528 virtual int __fastcall FillBlock(void* Block);
|
xue@0
|
529 virtual int __fastcall GetBytesPerSample();
|
xue@0
|
530 virtual __int32 __fastcall GetLength();
|
xue@0
|
531 virtual TStream* __fastcall GetStream();
|
xue@0
|
532 MMRESULT __fastcall SetVolume(void);
|
xue@0
|
533 virtual void __fastcall ReleaseBlock(void* Block, int BytesRecorded);
|
xue@0
|
534
|
xue@0
|
535 virtual void __fastcall OnWomOpen(TMessage& Message);
|
xue@0
|
536 virtual void __fastcall OnWomDone(TMessage& Message);
|
xue@0
|
537 virtual void __fastcall OnWomClose(TMessage& Message);
|
xue@0
|
538 virtual void __fastcall OnWimOpen(TMessage& Message);
|
xue@0
|
539 virtual void __fastcall OnWimData(TMessage& Message);
|
xue@0
|
540 virtual void __fastcall OnWimClose(TMessage& Message);
|
xue@0
|
541 void __fastcall WaveOutProc(TMessage& Message);
|
xue@0
|
542 void __fastcall WaveInProc(TMessage& Message);
|
xue@0
|
543
|
xue@0
|
544 public:
|
xue@0
|
545 __property AnsiString FileName={read=FFileName};
|
xue@0
|
546 __property __int32 AvgBytesPerSec={read=FAvgBytesPerSec};
|
xue@0
|
547 __property __int16 BlockAlign={read=FBlockAlign};
|
xue@0
|
548 __property int BytesPerSample={read=GetBytesPerSample};
|
xue@0
|
549 __property __int16 FormatTag={read=FFormatTag};
|
xue@0
|
550 __property __int16 cbSize={read=FcbSize};
|
xue@0
|
551 __property __int32 Length={read=GetLength};
|
xue@0
|
552
|
xue@0
|
553 __property TStream* WaveStream={read=GetStream};
|
xue@0
|
554 __property bool Recording={read=FRecording};
|
xue@0
|
555 __property bool Playing={read=FPlaying};
|
xue@0
|
556 __property bool Paused={read=FPaused};
|
xue@0
|
557
|
xue@0
|
558 virtual __fastcall TWaveAudio(TComponent* Owner);
|
xue@0
|
559 virtual __fastcall ~TWaveAudio();
|
xue@0
|
560
|
xue@0
|
561 void __fastcall Clear(TObject* Sender);
|
xue@0
|
562 void __fastcall CloseFile(bool Close=true);
|
xue@0
|
563 void CopyFrom(TStream* AStream, int Count);
|
xue@0
|
564 void CopyFrom(TWaveAudio* AWaveAudio, int Count);
|
xue@0
|
565 void CopySamplesFrom(TStream* AStream, int Count);
|
xue@0
|
566 void CopySamplesFrom(TWaveAudio* AWaveAudio, int Count);
|
xue@0
|
567 void CreateFile(AnsiString FileName);
|
xue@0
|
568 void GetWaveProperties(TWaveAudio* WaveAudio1);
|
xue@0
|
569 void InsertFromFile(AnsiString FileName);
|
xue@0
|
570 bool IsValidWave(AnsiString FileName);
|
xue@0
|
571 void LoadFromFile(AnsiString FileName);
|
xue@0
|
572 void __fastcall OpenFile(AnsiString AFileName);
|
xue@0
|
573 void __fastcall Pause(TObject* Sender);
|
xue@0
|
574 void __fastcall PausePlayback(TObject* Sender);
|
xue@0
|
575 void __fastcall PauseRecording(TObject* Sender);
|
xue@0
|
576 void __fastcall Play(TObject* Sender);
|
xue@0
|
577 void __fastcall Play(TNotifyEvent AnOnPlaybackDone);
|
xue@0
|
578 int __fastcall Read(void* Buffer, int Count);
|
xue@0
|
579 bool __fastcall ReadHeader(TStream* AStream, __int32& length, bool allowunfinisheddata=false);
|
xue@0
|
580 int __fastcall ReadSamples(void* Buffer, int Count);
|
xue@0
|
581 int __fastcall ReadSamples(double* Buffer, int Count);
|
xue@0
|
582 int __fastcall ReadSamplesInterleave(void* Buffer1, void* Buffer2, int Count);
|
xue@0
|
583 int __fastcall ReadSamplesInterleave(double* Buffer1, double* Buffer2, int Count);
|
xue@0
|
584 int __fastcall ReadSamplesMultiChannel(int C, void** Buffer, int Count);
|
xue@0
|
585 int __fastcall ReadSamplesMultiSingle(void* Buffer, int Channel, int Count);
|
xue@0
|
586 void __fastcall Restart(TObject* Sender);
|
xue@0
|
587 void __fastcall Rewind(TObject* Sender);
|
xue@0
|
588 void __fastcall SaveHeader(TStream* AStream);
|
xue@0
|
589 void __fastcall SaveToFile(AnsiString FileName);
|
xue@0
|
590 void __fastcall Seek(int Offset, WORD Origin);
|
xue@0
|
591 void __fastcall SeekSamples(int Offset, WORD Origin);
|
xue@0
|
592 void __fastcall StartPlayback(TObject* Sender);
|
xue@0
|
593 void __fastcall StartRecording(TObject* Sender);
|
xue@0
|
594 int __fastcall Write(void* Buffer, int Count);
|
xue@0
|
595 int __fastcall WriteSamples(void* Buffer, int Count);
|
xue@0
|
596 int __fastcall WriteSamples(double* Buffer, int Count);
|
xue@0
|
597 int __fastcall WriteSamplesInterleave(void* Buffer1, void* Buffer2, int Count);
|
xue@0
|
598 int __fastcall WriteSamplesInterleave(double* Buffer1, double* Buffer2, int Count);
|
xue@0
|
599
|
xue@0
|
600 __published:
|
xue@0
|
601 __property bool AutoUseMemoryStream={read=FAutoUseMemoryStream, write=FAutoUseMemoryStream};
|
xue@0
|
602 __property __int16 BitsPerSample={read=FBitsPerSample,write=SetBitsPerSample,default=8};
|
xue@0
|
603 __property int BlockSize={read=FBlockSize,write=SetBlockSize,default=4096};
|
xue@0
|
604 __property __int16 Channels={read=FChannels,write=SetChannels,default=1};
|
xue@0
|
605 __property unsigned __int16 LVolume={read=FLVolume, write=SetLVolume, default=0xFFFF};
|
xue@0
|
606 __property unsigned __int16 RVolume={read=FRVolume, write=SetRVolume, default=0xFFFF};
|
xue@0
|
607 __property __int32 SamplesPerSec={read=FSamplesPerSec,write=SetSamplesPerSec,default=11025};
|
xue@0
|
608 __property int StreamLimit={read=FStreamLimit,write=SetStreamLimit,default=0};
|
xue@0
|
609 __property bool UseMemoryStream={read=FUseMemoryStream, write=SetUseMemoryStream};
|
xue@0
|
610
|
xue@0
|
611 __property TNotifyEvent OnAudioChange={read=FOnAudioChange,write=FOnAudioChange};
|
xue@0
|
612 __property TNotifyEvent OnBeforeLoad={read=FOnBeforeLoad, write=FOnBeforeLoad};
|
xue@0
|
613 __property TNotifyEvent OnInAddBuffer={read=FOnInAddBuffer, write=FOnInAddBuffer};
|
xue@0
|
614 __property TNotifyEvent OnLoad={read=FOnLoad, write=FOnLoad};
|
xue@0
|
615 __property TNotifyEvent OnOutWrite={read=FOnOutWrite, write=FOnOutWrite};
|
xue@0
|
616 __property TNotifyEvent OnPlaybackDone={read=FOnPlaybackDone,write=FOnPlaybackDone};
|
xue@0
|
617 __property TNotifyEvent OnRecordingDone={read=FOnRecordingDone,write=FOnRecordingDone};
|
xue@0
|
618 __property TNotifyEvent OnStartPlayback={read=FOnStartPlayback, write=FOnStartPlayback};
|
xue@0
|
619 __property TNotifyEvent OnStartRecording={read=FOnStartRecording, write=FOnStartRecording};
|
xue@0
|
620 __property TNotifyEvent OnStreamFull={read=FOnStreamFull,write=FOnStreamFull};
|
xue@0
|
621 __property TNotifyEvent OnStreamLimitFailure={read=FOnStreamLimitFailure,write=FOnStreamLimitFailure};
|
xue@0
|
622 __property TWaveAudioPlaybackProgressEvent OnPlaybackProgress={read=FOnPlaybackProgress, write=FOnPlaybackProgress};
|
xue@0
|
623 __property TWaveAudioPlaybackProgressEvent OnPlaybackProg={read=FOnPlaybackProg, write=FOnPlaybackProg};
|
xue@0
|
624 };
|
xue@0
|
625
|
xue@0
|
626 typedef int __fastcall (__closure *TDataAudioFillBlockEvent)(void* ABlock);
|
xue@0
|
627
|
xue@0
|
628 class TDataAudio : public TWaveAudio
|
xue@0
|
629 {
|
xue@0
|
630 private:
|
xue@0
|
631 TDataAudioFillBlockEvent FCustomFillBlock;
|
xue@0
|
632 protected:
|
xue@0
|
633 virtual int __fastcall FillBlock(void*);
|
xue@0
|
634 public:
|
xue@0
|
635 virtual __fastcall TDataAudio(TComponent* Owner);
|
xue@0
|
636 __published:
|
xue@0
|
637 __property TDataAudioFillBlockEvent CustomFillBlock={read=FCustomFillBlock, write=FCustomFillBlock};
|
xue@0
|
638 };
|
xue@0
|
639
|
xue@0
|
640 //---------------------------------------------------------------------------
|
xue@0
|
641 #endif
|
xue@0
|
642
|