Mercurial > hg > hv
view AudioPac.h @ 1:f3fd4e19cec0 tip
first binary upload
author | wenx <xue.wen@eecs.qmul.ac.uk> |
---|---|
date | Wed, 10 Aug 2011 14:56:28 +0100 |
parents | a6a46af64546 |
children |
line wrap: on
line source
/* Harmonic Visualiser An audio file viewer and editor. Centre for Digital Music, Queen Mary, University of London. This file copyright 2011 Wen Xue. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ //--------------------------------------------------------------------------- #ifndef AudioPacH #define AudioPacH //--------------------------------------------------------------------------- /* AudioPac.cpp implements a VCL component for linear PCM waveform audio operations on Windows using Win32 WAVEMAPPER device. Component class TWaveAudio TWaveAudio is a VCL component that incapsulates the basic waveform audio i/o functions. Properties readwrite AutoUseMemoryStream readonly AvgBytesPerSec readwrite BitsPerSample readonly BlockAlign readwrite BlockSize readonly BytesPerSample readonly cbSize readwrite Channels readonly FileName readonly FormatTag readonly Length readwrite LVolume readonly Paused readonly Playing readonly Recording readwrite RVolume readwrite SamplesPerSec readwrite StreamLimit readwrite UseMemoryStream readonly WaveStream AutoUseMemoryStream If set, the component automatically set UseMemoryStream to false when calling LoadFromFile(...). AvgBytesPerSec Standard waveform format property. BitsPerSample Standard waveform format property. Usually 8, 16 or 24. BlockAlign Standard waveform property. Gives the size of a multi-channels sample. BlockSize Standard waveform format property. Specifies the size, in bytes, of the data block used for audio recording and playback. In AudioPac42.cpp a total of two data blocks are used. BytesPerSample Equals BitsPerSample/8. cbSize Standard waveform format property. Reserved. Channels Standard waveform format property. Specifies the number of channels. FileName The name of the file last loaded or inserted into this waveform. FormatTag Standard waveform format property. Must be WAVE_FORMAT_PCM. Length The length of waveform data held, in multi-channel samples. LVolume Specifies the playback volume of left channel. Paused Gives whether the playback is being suspended in pause mode. Playing Gives whether the playback is in progress, whether or not suspended in pause mode. Recording Gives whether the recording is in progress. RVolume Specifies the playback volume of right channel. SamplesPerSec Standard waveform format property. As is. StreamLimit This property provides a way to control the size of wave stream. If StreamLimit>0, TWaveAudio will generate an StreamFull event when the size of wave stream goes above StreamLimit. StreamLimit is set to zero by default. UseMemoryStream Specifies whether the component loads the data samples into a memory stream. If UseMemoryStream is set, a MemoryStream object is used to store the data samples in the memroy. If UseMemoryStream is set to false, the WaveAudio must be working on a wave file, where data samples are read from. Recording is not allowed when UseMemoryStream is false. WaveStream The pointer to the Stream object that holds the data samples. If UseMemoryStream is true, the stream is a MemoryStream. If false, the stream is an AttachFileStream, which is based on a FileStream. The data samples are stored right from the beginning of WaveStream. Methods: TWaveAudio & ~TWaveAudio Default constructor and destructor. void Clear(); void CloseFile(bool Close); void CopyFrom(TStream* AStream, int Count); void CopyFrom(TWaveAudio* AWaveAudio, int Count); void CopySamplesFrom(TStream* AStream, int Count); void CopySamplesFrom(TWaveAudio* AWaveAudio, int Count); void CreateFile(AnsiString FileName); void GetWaveProperties(TWaveAudio* WaveAudio1); void InsertFromFile(AnsiString FileName); bool IsValidWave(AnsiString FileName); void LoadFromFile(AnsiString FileName); void Pause(); void PausePlayback(); void PauseRecording(); void Play(); void Play(TNotifyEvent AnOnPlaybackDone); int Read(void* Buffer, int Count); bool ReadHeader(TStream* AStream, __int32& length, bool allowunfinisheddata); int ReadSamples(void* Buffer, int Count); int ReadSamples(double* Buffer, int Count); int ReadSamplesMultiChannel(int C, void** Buffer, int Count); int ReadSamplesMultiSingle(void* Buffer, int Channel, int Count); int ReadSamplesInterleave(void* Buffer1, void* Buffer2, int Count); void Restart(); void Rewind(); void SaveHeader(TStream* AStream); void SaveToFile(AnsiString FileName); void Seek(int Offset, WORD Origin); void SeekSamples(int Offset, WORD Origin); void StartPlayback(); void StartRecording(); int Write(void* Buffer, int Count); int WriteSamples(void* Buffer, int Count); int WriteSamples(double* Buffer, int Count); int WriteSamplesInterleave(void* Buffer1, void* Buffer2, int Count); int WriteSamplesInterleave(double* Buffer1, double* Buffer2, int Count); Clear() Clear the stored sound in the stream. Be cautious using Clear() when UseMemoryStream is true. CloseFile(bool Close) Effective only if UseMemoryStream is false. A call to this method flushes the audio content to the current working FileStream, closes the file handle of, and reopens the audio file as a new FileStream if Close is false. CopyFrom(TStream* AStream, int Count) The same as WaveStream->CopyFrom(AStream, Count) CopyFrom(TWaveAudio* AWaveAudio, int Count) The same as WaveStream->CopyFrom(AWaveAudio->WaveStream, Count) CopySamplesFrom(TStream* AStream, int Count) Similar to CopyFrom(AStream, Count), yet Count indicates the number of multi-channel samples to be copied, not bytes. CopySamplesFrom(TWaveAudio* AWaveAudio, int Count) Similar to CopyFrom(AWaveAudio, Count), yet Count indicates the numbet of multi-channel samples to be copied, not bytes. CreateFile(AnsiString FileName) Creates a new empty audio file as the current working audio stream. GetWaveProperties(TWaveAudio* WaveAudio1) Fill the standard waveform audio properties with those of WaveAudio1. InsertFromFile(AnsiString FileName) Loads in a wave file while giving up the previous content. It also sets the FileName property. IsValidWave(AnsiString FileName) Judge if a file specified with FileName is an valid waveform audio file. LoadFromFile(AnsiString FileName) Almost the same as InsertFromFile(...) but triggers the OnBeforeLoad and OnLoad events as well. Pause() Suspends on-going playback in pause mode. It sets Paused property. PausePlayback() Terminate playback. It also resets the Playing property and triggers an OnPlaybackDone event. PauseRecording() Terminate recording. It also resets the Recording property. Play() Rewind() then StartPlayback(). Play(TNotifyEvent AnOnPlaybackDone) Rewind() then StartPlayback() with AnOnPlaybackDone assigned to OnPlaybackDone event. It is recommended that OnPlaybackDone be assigned at designtime rather than at runtime. Read(void* Buffer, int Count) The same as WaveStream->Read(Buffer, Count). ReadHeader(TStream* AStream, __int32& length, bool allowunfinisheddata) Reads RIFF waveform header from AStream. ReadSamples(void* Buffer, int Count) ReadSamples(double* Buffer, int Count); Similar to Read(...), but Count is given in multi-channel samples, not in bytes. ReadSamplesInterleave(void* Buffer1, void* Buffer2, int Count) ReadSamplesInterleave(double* Buffer1, double* Buffer2, int Count) Reads interleaved stereo data into two data buffers. ReadSamplesMultiChannel(int C, void** Buffer, int Count) Reads multi-channel audio stream into multiple buffers, one for each channel. ReadSamplesMultiSingle(void* Buffer, int Channel, int Count) Reads the data of one channel from a multi-channel WaveAudio into a data buffer. Restart() Resumes playback suspended in pause mode. It resets Paused property as well. Rewind() Set the position of Stream to the beginning. SaveHeader(TStream* AStream) Saves RIFF waveform header to AStream. SaveToFile(AnsiString FileName) Saves current waveform stream to disk as a wave file. Seek(int Offset, WORD Origin) The same as WaveStream->Seek(Offset, Origin). SeekSamples(int Offset, WORD Origin) Similar to Seek(Offset, Origin), yet Offset is of the number of multi-channel samples, not bytes. StartPlayback() Start playback, starting from the current position of wave stream. It sets Playing property. When playback is done, a PlaybackDone event is triggered Playing is reset. StartRecording() Start recording. New data will be written to stream from the current position. Old data, if any, are overwritten. It sets the property Recording. Be cautious using StartRecording() when UseMemoryStream is true. Write(void* Buffer, int Count) The same as WaveStream->Write(Buffer, Count). Be cautious using Write(...) when UseMemoryStream is false as in this case the audio file is overwritten. WriteSamples(void* Buffer, int Count) WriteSamples(double* Buffer, int Count) Similar to Write(...), but Count is given in multi-channel samples, not in bytes. By cautious using WriteSamples when UseMemoryStream is false as in this case the audio file is overwritten. WriteSamplesInterleave(void* Buffer1, void* Buffer2, int Count) WriteSamplesInterleave(double* Buffer1, double* Buffer2, int Count) Writes stereo data in two data buffers into the interleaved format of WaveAudio. Be cautious using WriteSamplesInterleave when UseMemoryStream is false as in this case the audio file is overwritten. Events: OnAudioChange OnBeforeLoad OnInAddBuffer OnLoad OnOutWrite OnPlaybackDone OnPlaybackProg OnPlaybackProgress OnRecordingDone OnStartPlayback OnStartRecording OnStreamFull OnStreamLimitFailure OnAudioChange Triggered when the contents of the audio changes. This happens in the following cases: 1. InsertFromFile method is called. 2. A recording is finished. 3. CopyFrom or CopySamplesFrom method is called. 4. Clear method is called. The change of audio content by calling methods of WaveAudio is not informed by this event. OnBeforeLoad Triggered when a wave file is to be loaded. OnInAddBuffer Triggered after a block received from the WaveIn device is released into local data memory and the data block is returned to the WaveIn device. Handle this event to access the latest received data in real time. OnLoad Triggered when a wave file is loaded. OnOutWrite Triggered when a data block has been sent to the WaveOut device. OnPlaybackDone Triggered when playback is finished, whetherever PausePlayback method is called. OnPlaybackProg OnPlaybackProgress Triggered after each output data block is sent, and when playback is finished. The two eveent differs in a progress parameter. While OnPlaybackProg uses an integer parameter indicating the progress position in bytes, OnPlaybackProgress uses a floating-point parameter indicating the progress position in percentage. OnRecordingDone Triggered when recording is terminated and the WaveIn device is to be closed. OnStartPlayback Triggered when playback is started. OnStartRecording Triggered when recording is started. OnStreamFull Triggered when the size of wave stream exceeds StreamLimit. No other operations are done by TWaveForm. Application must handle this event to perform actual size limit. OnStreamLimitFailure Triggered when trying to set StreamLimit to a value smaller than the current size of wave stream. TWaveAudio refuses this operation and generates the event. Exceptions: "Failed opening device WaveIn" Form: StartRecording Thrown on failure of opening waveform audio input device. "Failed opening devece WaveOut" From: StartPlayback Thrown on failure of opening waveform audio output device. Component class TDataAudio TDataAudio is a decendent class of TWaveAudio, providing an CustomFillBlock event to enable on-the-fly data calculation for playback. Events: CustomFillBlock Triggered when a data block is to be filled by the application before sent to WaveOut device. Current version Wen Xue 2009/7 First version Wen Xue 2003/3 */ //--------------------------------------------------------------------------- //#include <SysUtils.hpp> //#include <Controls.hpp> //#include <Classes.hpp> //#include <Forms.hpp> //#include <Messages.hpp> #include <mmsystem.h> //--------------------------------------------------------------------------- #ifndef INT24 #define INT24 struct __int24; struct __pint24 { char* p; __pint24(){} __pint24(const void* ap){p=(char*)ap;} __pint24& operator=(const void* ap){p=(char*)ap; return *this;} __int24& operator*(){return *(__int24*)p;} __int24& operator[](int index){return *(__int24*)&p[3*index];} __pint24 operator++(int){__pint24 result=*this; p+=3; return result;} __pint24& operator++(){p+=3; return *this;} __pint24 operator--(int){__pint24 result=*this; p-=3; return result;} __pint24& operator--(){p-=3; return *this;} __pint24& operator+=(int a){p+=3*a; return *this;} __pint24& operator-=(int a){p-=3*a; return *this;} operator void*() const{return p;} }; struct __int24 { __int16 loword; __int8 hibyte; __int24(){} __int24(const __int32 a){loword=*(__int16*)&a; hibyte=((__int16*)&a)[1];} __int24(const double f){__int32 a=f; loword=*(__int16*)&a; hibyte=((__int16*)&a)[1];} __int24& operator=(const __int32 a){loword=*(__int16*)&a; hibyte=((__int16*)&a)[1]; return *this;} __int24& operator=(const double f){__int32 a=f; loword=*(__int16*)&a; hibyte=((__int16*)&a)[1]; return *this;} __int24& operator+=(const __int32 a){__int32 b=*this; b+=a; loword=*(__int16*)&b; hibyte=((__int16*)&b)[1]; return *this;} __int24& operator-=(const __int32 a){__int32 b=*this; b-=a; loword=*(__int16*)&b; hibyte=((__int16*)&b)[1]; return *this;} __int24& operator*=(const __int32 a){__int32 b=*this; b*=a; loword=*(__int16*)&b; hibyte=((__int16*)&b)[1]; return *this;} operator __int32() const{__int32 result; *(__int16*)&result=loword; ((__int16*)&result)[1]=hibyte; return result;} __pint24 operator &(){return (__pint24)this;} void* operator new[](size_t count){void* result=malloc(3*count); return result;} void operator delete[](void* p){free(p);} }; #endif //--------------------------------------------------------------------------- void DoubleToIntInterleave(void* _out, int BytesPerSample, double* in1, double* in2, int Count); void IntToDoubleInterleave(double* out1, double* out2, void* _in, int BytesPerSample, int Count); int IntToIntInterleave(void* dest, int bytesperunit, void* block1, void* block2, int Count); int IntToIntInterleave(void* dest1, void* dest2, int bytesperunit, void* block, int Count); int IntToIntMultiSingle(void* dest, int bytesperunit, int channels, int channel, void* block, int Count); typedef void __fastcall (__closure *TWaveAudioPlaybackProgressEvent)(System::TObject* Sender, double PlaybackPosition); class TAttachFileStream : public TStream { public: TFileStream* File; int StartOffset; int EndOffset; protected: virtual int __fastcall Seek(int AnOffset, Word Origin); virtual __int64 __fastcall Seek(const __int64 AnOffset, TSeekOrigin Origin); virtual int __fastcall Read(void *Buffer, int Count); virtual int __fastcall Write(const void *Buffer, int Count); public: __fastcall TAttachFileStream(TFileStream* AFileStream); __fastcall ~TAttachFileStream(); }; class TWaveView; class PACKAGE TWaveAudio : public TComponent { friend TWaveView; protected: bool FUseMemoryStream; TMemoryStream* FMemoryStream; TAttachFileStream* FFileStream; AnsiString FFileName; __int32 FSamplesPerSec; __int16 FBitsPerSample; __int16 FChannels; __int32 FAvgBytesPerSec; __int16 FBlockAlign; __int16 FFormatTag; __int16 FcbSize; unsigned __int16 FLVolume; unsigned __int16 FRVolume; int FStreamLimit; int FBlockSize; TNotifyEvent FOnBeforeLoad; TNotifyEvent FOnAudioChange; TNotifyEvent FOnInAddBuffer; TNotifyEvent FOnLoad; TNotifyEvent FOnOutWrite; TNotifyEvent FOnPlaybackDone; TNotifyEvent FOnRecordingDone; TNotifyEvent FOnStartPlayback; TNotifyEvent FOnStartRecording; TNotifyEvent FOnStreamFull; TNotifyEvent FOnStreamLimitFailure; TWaveAudioPlaybackProgressEvent FOnPlaybackProgress; TWaveAudioPlaybackProgressEvent FOnPlaybackProg; bool FAutoUseMemoryStream; bool FRecording; bool FPlaying; bool FPaused; __property TStream* Stream={read=GetStream}; public: HWAVEIN WaveIn; HWAVEOUT WaveOut; protected: HWND HWndOut; HWND HWndIn; WAVEHDR* WaveHdr1; WAVEHDR* WaveHdr2; void* Buffer1; void* Buffer2; bool ResetInStream; bool ResetInUser; bool ResetOut; bool ResetOutUser; protected: virtual void __fastcall SetSamplesPerSec(__int32 ASamplesPerSec); virtual void __fastcall SetBitsPerSample(__int16 ABitsPerSample); virtual void __fastcall SetChannels(__int16 AChannels); virtual void __fastcall SetBlockSize(int ABlockSize); virtual void __fastcall SetStreamLimit(int AStreamLimit); virtual void __fastcall SetLVolume(unsigned __int16 ALVolume); virtual void __fastcall SetRVolume(unsigned __int16 ARVolume); virtual void __fastcall SetUseMemoryStream(bool AUseMemoryStream); virtual int __fastcall FillBlock(void* Block); virtual int __fastcall GetBytesPerSample(); virtual __int32 __fastcall GetLength(); virtual TStream* __fastcall GetStream(); MMRESULT __fastcall SetVolume(void); virtual void __fastcall ReleaseBlock(void* Block, int BytesRecorded); virtual void __fastcall OnWomOpen(TMessage& Message); virtual void __fastcall OnWomDone(TMessage& Message); virtual void __fastcall OnWomClose(TMessage& Message); virtual void __fastcall OnWimOpen(TMessage& Message); virtual void __fastcall OnWimData(TMessage& Message); virtual void __fastcall OnWimClose(TMessage& Message); void __fastcall WaveOutProc(TMessage& Message); void __fastcall WaveInProc(TMessage& Message); public: __property AnsiString FileName={read=FFileName}; __property __int32 AvgBytesPerSec={read=FAvgBytesPerSec}; __property __int16 BlockAlign={read=FBlockAlign}; __property int BytesPerSample={read=GetBytesPerSample}; __property __int16 FormatTag={read=FFormatTag}; __property __int16 cbSize={read=FcbSize}; __property __int32 Length={read=GetLength}; __property TStream* WaveStream={read=GetStream}; __property bool Recording={read=FRecording}; __property bool Playing={read=FPlaying}; __property bool Paused={read=FPaused}; virtual __fastcall TWaveAudio(TComponent* Owner); virtual __fastcall ~TWaveAudio(); void __fastcall Clear(TObject* Sender); void __fastcall CloseFile(bool Close=true); void CopyFrom(TStream* AStream, int Count); void CopyFrom(TWaveAudio* AWaveAudio, int Count); void CopySamplesFrom(TStream* AStream, int Count); void CopySamplesFrom(TWaveAudio* AWaveAudio, int Count); void CreateFile(AnsiString FileName); void GetWaveProperties(TWaveAudio* WaveAudio1); void InsertFromFile(AnsiString FileName); bool IsValidWave(AnsiString FileName); void LoadFromFile(AnsiString FileName); void __fastcall OpenFile(AnsiString AFileName); void __fastcall Pause(TObject* Sender); void __fastcall PausePlayback(TObject* Sender); void __fastcall PauseRecording(TObject* Sender); void __fastcall Play(TObject* Sender); void __fastcall Play(TNotifyEvent AnOnPlaybackDone); int __fastcall Read(void* Buffer, int Count); bool __fastcall ReadHeader(TStream* AStream, __int32& length, bool allowunfinisheddata=false); int __fastcall ReadSamples(void* Buffer, int Count); int __fastcall ReadSamples(double* Buffer, int Count); int __fastcall ReadSamplesInterleave(void* Buffer1, void* Buffer2, int Count); int __fastcall ReadSamplesInterleave(double* Buffer1, double* Buffer2, int Count); int __fastcall ReadSamplesMultiChannel(int C, void** Buffer, int Count); int __fastcall ReadSamplesMultiSingle(void* Buffer, int Channel, int Count); void __fastcall Restart(TObject* Sender); void __fastcall Rewind(TObject* Sender); void __fastcall SaveHeader(TStream* AStream); void __fastcall SaveToFile(AnsiString FileName); void __fastcall Seek(int Offset, WORD Origin); void __fastcall SeekSamples(int Offset, WORD Origin); void __fastcall StartPlayback(TObject* Sender); void __fastcall StartRecording(TObject* Sender); int __fastcall Write(void* Buffer, int Count); int __fastcall WriteSamples(void* Buffer, int Count); int __fastcall WriteSamples(double* Buffer, int Count); int __fastcall WriteSamplesInterleave(void* Buffer1, void* Buffer2, int Count); int __fastcall WriteSamplesInterleave(double* Buffer1, double* Buffer2, int Count); __published: __property bool AutoUseMemoryStream={read=FAutoUseMemoryStream, write=FAutoUseMemoryStream}; __property __int16 BitsPerSample={read=FBitsPerSample,write=SetBitsPerSample,default=8}; __property int BlockSize={read=FBlockSize,write=SetBlockSize,default=4096}; __property __int16 Channels={read=FChannels,write=SetChannels,default=1}; __property unsigned __int16 LVolume={read=FLVolume, write=SetLVolume, default=0xFFFF}; __property unsigned __int16 RVolume={read=FRVolume, write=SetRVolume, default=0xFFFF}; __property __int32 SamplesPerSec={read=FSamplesPerSec,write=SetSamplesPerSec,default=11025}; __property int StreamLimit={read=FStreamLimit,write=SetStreamLimit,default=0}; __property bool UseMemoryStream={read=FUseMemoryStream, write=SetUseMemoryStream}; __property TNotifyEvent OnAudioChange={read=FOnAudioChange,write=FOnAudioChange}; __property TNotifyEvent OnBeforeLoad={read=FOnBeforeLoad, write=FOnBeforeLoad}; __property TNotifyEvent OnInAddBuffer={read=FOnInAddBuffer, write=FOnInAddBuffer}; __property TNotifyEvent OnLoad={read=FOnLoad, write=FOnLoad}; __property TNotifyEvent OnOutWrite={read=FOnOutWrite, write=FOnOutWrite}; __property TNotifyEvent OnPlaybackDone={read=FOnPlaybackDone,write=FOnPlaybackDone}; __property TNotifyEvent OnRecordingDone={read=FOnRecordingDone,write=FOnRecordingDone}; __property TNotifyEvent OnStartPlayback={read=FOnStartPlayback, write=FOnStartPlayback}; __property TNotifyEvent OnStartRecording={read=FOnStartRecording, write=FOnStartRecording}; __property TNotifyEvent OnStreamFull={read=FOnStreamFull,write=FOnStreamFull}; __property TNotifyEvent OnStreamLimitFailure={read=FOnStreamLimitFailure,write=FOnStreamLimitFailure}; __property TWaveAudioPlaybackProgressEvent OnPlaybackProgress={read=FOnPlaybackProgress, write=FOnPlaybackProgress}; __property TWaveAudioPlaybackProgressEvent OnPlaybackProg={read=FOnPlaybackProg, write=FOnPlaybackProg}; }; typedef int __fastcall (__closure *TDataAudioFillBlockEvent)(void* ABlock); class TDataAudio : public TWaveAudio { private: TDataAudioFillBlockEvent FCustomFillBlock; protected: virtual int __fastcall FillBlock(void*); public: virtual __fastcall TDataAudio(TComponent* Owner); __published: __property TDataAudioFillBlockEvent CustomFillBlock={read=FCustomFillBlock, write=FCustomFillBlock}; }; //--------------------------------------------------------------------------- #endif