// -------------------------------------------------------------------------- // ========================================================================== // File: TDx_SoundBuffer.CPP // Authors: BCB_Code_Generator v1.62, // Darren Dwyer (source code, documentation, demos, website), // Hugh Edwards (documentation, icons), // // Description: This file contains the code for the TDx_SoundBuffer // Component // // "TDx_Sound_Library v1.62" // (c) 2002 BCB-Tools.com Pty. Ltd., Sydney, Australia. // All Rights Reserved. // // Refer to the 'Licence.Txt' file for licencing & copyright information. // ========================================================================== // -------------------------------------------------------------------------- // #includes ... // -------------------------------------------------------------------------- #include #pragma hdrstop // -------------------------------------------------------------------------- #include "TDx_SoundBuffer.H" // -------------------------------------------------------------------------- // external classes used by the TDx_SoundBuffer component. #include "TDx_Sound.H" // -------------------------------------------------------------------------- // external classes used by TDx_SoundBuffer methods. #include "TDSBufferDesc.H" #include "TDSBCaps.H" // -------------------------------------------------------------------------- #pragma link "TDx_Library_Defns" #pragma link "TDx_Library_Functions" #pragma link "TDx_Sound_Library_Defns" #pragma link "TDx_Sound_Library_Functions" // -------------------------------------------------------------------------- // Object Registration... // -------------------------------------------------------------------------- #if (__BORLANDC__ >= 0x0530) // BCB Version 3+ #pragma package(smart_init) #endif // -------------------------------------------------------------------------- static inline void ValidCtrCheck(TDx_SoundBuffer*) { new TDx_SoundBuffer(NULL); } // -------------------------------------------------------------------------- namespace Tdx_soundbuffer { #if (__BORLANDC__ >= 0x0530) // BCB Version 3+ void __fastcall PACKAGE Register() #else void __fastcall Register() #endif { TComponentClass classes[1] = {__classid(TDx_SoundBuffer)}; RegisterComponents("TDx_Sound", classes, 0); } } // -------------------------------------------------------------------------- // Constructor: TDx_SoundBuffer::TDx_SoundBuffer() // Description: The default constructor for the TDx_SoundBuffer object. // -------------------------------------------------------------------------- __fastcall TDx_SoundBuffer::TDx_SoundBuffer(TComponent* Owner) : TComponent(Owner) { fCreated = false; fErrorValue = DS_OK; fStreamFormat = NULL; fStreamHandle = -1; fStreamIsOpen = false; fStreamSize = 0; } // -------------------------------------------------------------------------- // Destructor: TDx_SoundBuffer::~TDx_SoundBuffer() // Description: The destructor for the TDx_SoundBuffer object. // -------------------------------------------------------------------------- __fastcall TDx_SoundBuffer::~TDx_SoundBuffer() { // destroy internals if (Created) Destroy(); if (fStreamFormat!=NULL) GlobalFree( fStreamFormat ); if (fStreamHandle!=-1) close( fStreamHandle ); } // -------------------------------------------------------------------------- // Property: Created // Description: The Created property is true if the internal // LPDIRECTSOUNDBUFFER used in this component has been // successfully created, otherwise Created is false. // // To create the internal LPDIRECTSOUNDBUFFER, call the // TDx_SoundBuffer::Create() method. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::FGetCreated() { return fCreated; } // -------------------------------------------------------------------------- void __fastcall TDx_SoundBuffer::FSetCreated( bool pCreated ) { fCreated = (pCreated && (fLPDIRECTSOUNDBUFFER==NULL)); } // -------------------------------------------------------------------------- // Property: ErrorValue // Description: The ErrorValue property contains the last error value // returned from a call to a TDx_SoundBuffer method or // fget/fset. eg. DS_OK or DDERR_SURFACELOST or TDX_ERROR // -------------------------------------------------------------------------- HRESULT __fastcall TDx_SoundBuffer::FGetErrorValue() { return fErrorValue; } // -------------------------------------------------------------------------- void __fastcall TDx_SoundBuffer::FSetErrorValue( HRESULT pErrorValue ) { fErrorValue = pErrorValue; } // -------------------------------------------------------------------------- // Property: Frequency // Description: The Frequency property can be used as an alternative to // calling the TDx_SoundBuffer::GetFrequency() and // TDx_SoundBuffer::SetFrequency() methods. // Retrieving this property calls the GetFrequency() method and // returns the result. // Setting this property calls the SetFrequency() method and // passes the supplied property value as the method parameter. // -------------------------------------------------------------------------- dword __fastcall TDx_SoundBuffer::FGetFrequency() { dword temp_Frequency; GetFrequency(&temp_Frequency); return temp_Frequency; } // -------------------------------------------------------------------------- void __fastcall TDx_SoundBuffer::FSetFrequency( dword pFrequency ) { SetFrequency(pFrequency); } // -------------------------------------------------------------------------- // Property: Pan // Description: The Pan property can be used as an alternative to calling the // TDx_SoundBuffer::GetPan() and TDx_SoundBuffer::SetPan() // methods. // Retrieving this property calls the GetPan() method and // returns the result. // Setting this property calls the SetPan() method and passes // the supplied property value as the method parameter. // -------------------------------------------------------------------------- long __fastcall TDx_SoundBuffer::FGetPan() { long temp_Pan; GetPan(&temp_Pan); return temp_Pan; } // -------------------------------------------------------------------------- void __fastcall TDx_SoundBuffer::FSetPan( long pPan ) { SetPan(pPan); } // -------------------------------------------------------------------------- // Property: Playing // Description: The Playing property can be used to determine whether or not // a buffer is currently playing. If true, the sound buffer is // currently playing. If false, the sound buffer is not // currently playing. // // This is equivalent to calling TDx_SoundBuffer::GetStatus() // and checking for DSBSTATUS_PLAYING. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::FGetPlaying() { dword status; if (GetStatus( &status )) if ((status & DSBSTATUS_PLAYING)==DSBSTATUS_PLAYING) return true; return false; } // -------------------------------------------------------------------------- // Property: StreamFormat // Description: The StreamFormat property references an internal WAVEFORMATEX // structure defining the format of the current stream. // This internal structure is setup when you call the // TDx_SoundBuffer::OpenStream(), // TDx_SoundBuffer::CreateFromFile(), // TDx_SoundBuffer::CreateStream() or // TDx_SoundBuffer::SaveToFile() methods. // -------------------------------------------------------------------------- WAVEFORMATEX* __fastcall TDx_SoundBuffer::FGetStreamFormat() { return fStreamFormat; } // -------------------------------------------------------------------------- // Property: StreamHandle // Description: The StreamHandle property is used internally by the // TDx_SoundBuffer component to implement sound streaming. // -------------------------------------------------------------------------- int __fastcall TDx_SoundBuffer::FGetStreamHandle() { return fStreamHandle; } // -------------------------------------------------------------------------- // Property: StreamIsOpen // Description: The StreamIsOpen property will be true if a stream is // currently open and false otherwise. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::FGetStreamIsOpen() { return fStreamIsOpen; } // -------------------------------------------------------------------------- // Property: StreamSize // Description: The StreamSize property holds the total number of bytes in // the current stream. // Set this property to the total size of the stream to be // saved, in bytes, before calling // TDx_SoundBuffer::SaveToFile(). // // After calling TDx_SoundBuffer::CreateFromStream(), this // property will contain the total number of bytes of data read // from the stream. // After calling TDx_SoundBuffer::CreateStream() or // TDx_SoundBuffer::OpenStream() this property will be 0. // After calling TDx_SoundBuffer::CloseStream() this property // will contain the total number of bytes read from or written // to the stream using TDx_SoundBuffer::ReadFromStream() or // TDx_SoundBuffer::WriteToStream() since the last call to // TDx_SoundBuffer::CreateStream() // After calling TDx_SoundBuffer::CreateStream() this property // will contain the total number of bytes read from or written // to the stream. // // -------------------------------------------------------------------------- dword __fastcall TDx_SoundBuffer::FGetStreamSize() { return fStreamSize; } // -------------------------------------------------------------------------- void __fastcall TDx_SoundBuffer::FSetStreamSize( dword pStreamSize ) { fStreamSize = pStreamSize; } // -------------------------------------------------------------------------- // Property: Volume // Description: The Volume property can be used as an alternative to calling // the TDx_SoundBuffer::GetVolume() and // TDx_SoundBuffer::SetVolume() methods. // Retrieving this property calls the GetVolume() method and // returns the result. // Setting this property calls the SetVolume() method and passes // the supplied property value as the method parameter. // -------------------------------------------------------------------------- long __fastcall TDx_SoundBuffer::FGetVolume() { long temp_Volume; GetVolume(&temp_Volume); return temp_Volume; } // -------------------------------------------------------------------------- void __fastcall TDx_SoundBuffer::FSetVolume( long pVolume ) { SetVolume(pVolume); } // -------------------------------------------------------------------------- // Property: WaveFileFormat // Description: The WaveFileFormat property is used internally to setup the // .WAV file header for streaming. // -------------------------------------------------------------------------- TDX_WAVE_FILE_FORMAT __fastcall TDx_SoundBuffer::FGetWaveFileFormat() { return fWaveFileFormat; } // -------------------------------------------------------------------------- void __fastcall TDx_SoundBuffer::FSetWaveFileFormat( TDX_WAVE_FILE_FORMAT pWaveFileFormat ) { fWaveFileFormat = pWaveFileFormat; } // -------------------------------------------------------------------------- // Method: CloseStream() // Description: The CloseStream method will close the current .wav file. // // If the method call fails, the OnError event will be triggered // with one of the following values: // TDX_ERROR // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::CloseStream() { if (fStreamFormat==NULL) { fErrorValue = TDX_ERROR; if (FOnError) FOnError(this, Name+"::CloseStream()", "TDX_ERROR", "StreamFormat is NULL when it should not be NULL." ); return false; } if (!fStreamIsOpen) { fErrorValue = TDX_ERROR; if (FOnError) FOnError(this, Name+"::CloseStream()", "TDX_ERROR", "Cannot close the stream because it is not open." ); return false; } // update the wave file header fWaveFileFormat.data_chunk.size = fStreamSize; fWaveFileFormat.riff_chunk.size = sizeof( TDX_WAVE_FILE_FORMAT ) + fStreamSize - 8; // write it to the file int error = lseek( fStreamHandle, 0, SEEK_SET ); if (error==-1) { close( fStreamHandle ); fStreamHandle = NULL; fErrorValue = TDX_ERROR; if (FOnError) FOnError(this, Name+"::CloseStream()", "TDX_ERROR", "Cannot create the stream because could not seek to update the file header." ); return false; } error = write( fStreamHandle, (void*) &fWaveFileFormat, sizeof(fWaveFileFormat) ); if (error==-1) { close( fStreamHandle ); fStreamHandle = NULL; fErrorValue = TDX_ERROR; if (FOnError) FOnError(this, Name+"::CloseStream()", "TDX_ERROR", "Cannot create the stream because the wave file header could not be created." ); return false; } // close the file close( fStreamHandle ); delete[] fStreamFormat; fStreamFormat = NULL; fStreamHandle = -1; fStreamIsOpen = false; fErrorValue = DS_OK; return true; } // -------------------------------------------------------------------------- // Method: Create() // Description: The Create() method is used to automatically create the // internal LPDIRECTSOUNDBUFFER interface used in the // TDx_SoundBuffer component and must be called before any // methods of the TDx_SoundBuffer component will function. // Params: pBufferDesc - // The BufferDesc parameter references a TDSBufferDesc defining // the properties of the sound buffer being created. // pSound - // The Sound parameter references the existing TDx_Sound // component for which the sound buffer is to be created. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::Create( TDSBufferDesc* pBufferDesc, TDx_Sound* pSound ) { // if the component internals have already been created, exit if (fCreated) { fErrorValue = TDX_ALREADYCREATED; if (FOnError) FOnError( this, Name+"::Create()", "TDX_ALREADYCREATED", "The "+Name+"::Create() method was called when the component has already been created successfully." ); return false; } // check params for accuracy if (pBufferDesc==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::Create()", "TDX_BADPARAMS", "The 'pBufferDesc' parameter must point to an existing TDSBufferDesc component and cannot be NULL." ); return false; } if (pSound==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::Create()", "TDX_BADPARAMS", "The 'pSound' parameter must point to an existing TDx_Sound component and cannot be NULL." ); return false; } // code that creates the internal IDirectSoundBuffer interface pSound->CreateSoundBuffer( pBufferDesc, this ); fErrorValue = pSound->ErrorValue; if (fErrorValue!=DS_OK) { if (FOnError) FOnError( this, Name+"::Create()", "TDX_ERROR", "The "+Name+"::Create() method failed because DirectSoundCreate() failed with error: "+TDx_Sound_Library_ErrorString(fErrorValue)+", "+TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // successfully created fCreated = true; if (FOnCreate) FOnCreate(this); return true; } // -------------------------------------------------------------------------- // Method: CreateFromFile() // Description: The CreateFromFile method will create a sound buffer of the // same format as a specified .wav file. // If there is an existing buffer for this component, it will be // destroyed before the new one is created. // The size of the new buffer will equal that of the file's // sound data, which is automatically loaded into the buffer. // // The internal WAVEFORMATEX structure referenced by the // TDx_SoundBuffer::StreamFormat property will automatically be // filled with the format data of the specified .wav file. // // Note: // This method does not support the loading of .wav files where // the format of the .wav file being loaded is not the raw, // uncompressed, WAVE_FORMAT_PCM .wav file standard that // DirectSound supports. It currently supports only // WAVE_FORMAT_PCM files, and may have undetermined results if // used with non-WAVE_FORMAT_PCM files. // // If the method call fails, the OnError event will be triggered // with one of the following values: // TDX_BADPARAMS // TDX_ERROR // Params: pFileName - // The FileName parameter defines the path and filename of the // .wav file which will be used to create the sound buffer. // pBufferDesc - // The BufferDesc parameter references a TDSBufferDesc component // for holding the properties of the new buffer. // // The TDSBufferDesc component will mostly be filled // automatically from data contained in the .wav file. // // If control options in addition to the // DSBCAPS_GETCURRENTPOSITION2 are required, it is neccessary to // set the desired flags in the TDSBufferDesc component manually // before calling this method. // pSound - // The Sound parameter references the existing TDx_Sound // component for which the sound buffer is to be created. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::CreateFromFile( AnsiString pFileName, TDSBufferDesc* pBufferDesc, TDx_Sound* pSound ) { // check params if (pFileName=="") { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError(this, Name+"::CreateFromFile()", "TDX_BADPARMS", "The 'FileName' parameter cannot be a NULL string." ); return false; } // check params for accuracy if (pBufferDesc==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::CreateFromFile()", "TDX_BADPARAMS", "The 'pBufferDesc' parameter must point to an existing TDSBufferDesc component and cannot be NULL." ); return false; } if (pSound==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::CreateFromFile()", "TDX_BADPARAMS", "The 'pSound' parameter must point to an existing TDx_Sound component and cannot be NULL." ); return false; } // if we've already created our buffer, destroy it. if (Created) Destroy(); // open the wave file and set it up ready for reading data if (!OpenStream( pFileName )) { fErrorValue = TDX_ERROR; if (FOnError) FOnError( this, Name+"::CreateFromFile()", "TDX_ERROR", "The CreateFromFile() method failed because TDx_SoundBuffer::OpenStream() failed." ); return false; } // setup the buffer desc with retrieved info pBufferDesc->Format = StreamFormat; pBufferDesc->BufferBytes = StreamSize; pBufferDesc->Flags = pBufferDesc->Flags | DSBCAPS_GETCURRENTPOSITION2; // create the required sound buffer bool success = pSound->CreateSoundBuffer( pBufferDesc, this ); if (!success) { CloseStream(); fErrorValue = TDX_ERROR; if (FOnError) FOnError( this, Name+"::CreateFromFile()", "TDX_ERROR", "The CreateFromFile() method failed because TDx_Sound::CreateSoundBuffer() failed." ); return false; } // read the entire datablock void* first_block = NULL; void* second_block = NULL; dword first_block_length; dword second_block_length; dword dummy_bytes_read; success = Lock( 0, StreamSize, &first_block, &first_block_length, &second_block, &second_block_length, 0 ); if (!success) { CloseStream(); fErrorValue = TDX_ERROR; if (FOnError) FOnError( this, Name+"::CreateFromFile()", "TDX_ERROR", "The CreateFromFile() method failed because TDx_SoundBuffer::Lock() failed." ); return false; } success = ReadFromStream( StreamSize, (byte*) first_block, &dummy_bytes_read ); if (!success) { Unlock( first_block, StreamSize, NULL, 0 ); CloseStream(); fErrorValue = TDX_ERROR; if (FOnError) FOnError( this, Name+"::CreateFromFile()", "TDX_ERROR", "The CreateFromFile() method failed because TDx_SoundBuffer::ReadFromStream() failed." ); return false; } Unlock( first_block, StreamSize, NULL, 0 ); CloseStream(); // success fErrorValue = DS_OK; if (FOnCreate) FOnCreate(this); return true; } // -------------------------------------------------------------------------- // Method: CreateStream() // Description: The CreateStream method will create and open a new .wav file. // Once created, sound data may be written to the file with // TDx_SoundBuffer::WriteToStream(). // Once all data has been written to the stream, close the // stream using TDx_SoundBuffer::CloseStream() // When the stream is open, the TDx_SoundBuffer::StreamIsOpen // property will be true. // // If the method call fails, the OnError event will be triggered // with one of the following values: // // TDX_BADPARAMS // TDX_ERROR // Params: pFileName - // The FileName parameter defines the path and filename of the // .wav file to be created. // pFormat - // The Format method parameter describes the format of the sound // file to be created. This parameter must point to a // user-supplied WAVEFORMATEX structure that has been filled // with appropriate values. // // You can retrieve the WAVEFORMATEX of the current buffer using // the TDx_SoundBuffer::GetFormat() method. // // You can also pass in a non-WAVE_FORMAT_PCM structure typecast // as a WAVEFORMATEX, and supply the byte-size of the // non-WAVE_FORMAT_PCM using the FormatSize parameter. // pFormatSize - // The FormatSize parameter must contain the size of the // WAVEFORMATEX structure passed into this method via the Format // parameter. // Generally this will be sizeof(WAVEFORMATEX) but it may differ // depending on the definition of the WAVEFORMATEX.. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::CreateStream( AnsiString pFileName, WAVEFORMATEX* pFormat, int pFormatSize ) { // check 'filename' parameter if (pFileName=="") { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError(this, Name+"::CreateStream()", "TDX_BADPARAMS", "The 'FileName' parameter cannot be a NULL string." ); return false; } if (pFileName.UpperCase().Pos(".WAV")==0) pFileName = pFileName +".WAV"; // check 'format' parameter if (pFormat==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError(this, Name+"::CreateStream()", "TDX_BADPARAMS", "The 'Format' parameter must reference a valid WAVEFORMATEX structure and cannot be NULL." ); return false; } if (pFormatSize sizeof(WAVEFORMATEX)) { int error = write( fStreamHandle, (void*) &pFormat[ sizeof(WAVEFORMATEX) ], sizeof(WAVEFORMATEX) - pFormatSize ); if (error==-1) { close( fStreamHandle ); fStreamHandle = NULL; fErrorValue = TDX_ERROR; if (FOnError) FOnError(this, Name+"::CreateStream()", "TDX_ERROR", "Cannot create the media file: "+pFileName+" because the Extra PCM Info could not be created." ); return false; } } // successfully created the stream fStreamSize = 0; fStreamIsOpen = true; fErrorValue = DS_OK; return true; } // -------------------------------------------------------------------------- // Method: Destroy() // Description: The Destroy() method is used to automatically destroy the // internal LPDIRECTSOUNDBUFFER interface used in the // TDx_SoundBuffer component and should be called when the // internal interface is no longer required. // // Note: This method is called by the component's destructor. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::Destroy() { // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Destroy()", "TDX_NOTCREATED", "The "+Name+"::Destroy() method was called before being created successfully." ); return false; } // if the stream is still open, close it now. if (fStreamIsOpen) CloseStream(); // code that destroys the internal interface if (FOnDestroy) FOnDestroy(this); if (fLPDIRECTSOUNDBUFFER==NULL) { fErrorValue = TDX_ERROR; if (FOnError) FOnError( this, Name+"::Destroy()", "TDX_ERROR", "The "+Name+" component's internal LPDIRECTSOUNDBUFFER is NULL but the TDx_Sound component is expecting it to be not NULL. Aborting the Destroy()." ); return false; } try { fLPDIRECTSOUNDBUFFER->Release(); } catch (...) { fErrorValue = TDX_ERROR; if (FOnError) FOnError( this, Name+"::Destroy()", "TDX_ERROR", "An exception has occurred within LPDIRECTSOUNDBUFFER->Release(). Check that you are destroying all components in reverse order of creation." ); } // successful destruction fLPDIRECTSOUNDBUFFER = NULL; fCreated = false; return true; } // -------------------------------------------------------------------------- // Method: GetCaps() // Description: The TDx_SoundBuffer::GetCaps method will return the current // capabilities of the buffer. // // If the method call fails, the OnError event may be triggered // with the following value: // TDX_BADPARAMS // DSERR_INVALIDPARAM // Params: pBufferCaps - // The BufferCaps parameter references a TDSBCaps component for // holding the capabilities of the sound buffer if this method // returns successfully. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::GetCaps( TDSBCaps* pBufferCaps ) { // Original Function Definition // HRESULT GetCaps( // LPDSBCAPS lpDSBufferCaps // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetCaps()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pBufferCaps==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::GetCaps()", "TDX_BADPARAMS", "'pBufferCaps' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->GetCaps( pBufferCaps->Internal_DSBCAPS_Ptr ); // Translate Data returned from Function pBufferCaps->Internal_DSBCAPS_Update(); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetCaps()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetCurrentPosition() // Description: The TDx_SoundBuffer::GetCurrentPosition method will return // the current postion of the play and write cursors within the // sound buffer. // // If the method call fails, the OnError event will be triggered // with one of the following values: // DSERR_INVALIDPARAM // DSERR_PRIOLEVELNEEDED // Params: pCurrentPlayCursor - // The CurrentPlayCursor parameter will reference the current // offset, in bytes, of the play cursor within the buffer if // this method returns successfully. // Set this parameter to NULL if only the write position is // desired. // pCurrentWriteCursor - // The CurrentWriteCursor parameter will reference the current // offset, in bytes, of the write cursor within the buffer if // this method returns successfully. // Set this parameter to NULL if only the play position is // desired. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::GetCurrentPosition( dword* pCurrentPlayCursor, dword* pCurrentWriteCursor ) { // Original Function Definition // HRESULT GetCurrentPosition( // LPDWORD lpdwCurrentPlayCursor, // LPDWORD lpdwCurrentWriteCursor // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetCurrentPosition()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->GetCurrentPosition( (LPDWORD) pCurrentPlayCursor, (LPDWORD) pCurrentWriteCursor ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetCurrentPosition()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetFormat() // Description: The TDx_SoundBuffer::GetFormat method will return either the // sound data format of the buffer or amount of space needed to // retrieve that information. // // If the method call fails, the OnError event may be triggered // with the following value: // DSERR_INVALIDPARAM // Params: pFormat - // The Format parameter references a WAVEFORMATEX structure for // holding the sound data format of the buffer. // // Setting this parameter to NULL will cause the required buffer // size to be placed in the SizeWritten parameter of this // method. // pSizeAllocated - // The SizeAllocated parameter defines the size, in bytes, of // the WAVEFORMATEX structure referenced by the Format parameter // of this method. // pSizeWritten - // The SizeWritten parameter will reference the amount, in // bytes, written into the WAVEFORMATEX structure referenced by // the Format parameter of this method. // This parameter may be set to NULL. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::GetFormat( WAVEFORMATEX* pFormat, dword pSizeAllocated, dword* pSizeWritten ) { // Original Function Definition // HRESULT GetFormat( // LPWAVEFORMATEX lpwfxFormat, // DWORD dwSizeAllocated, // LPDWORD lpdwSizeWritten // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetFormat()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->GetFormat( (LPWAVEFORMATEX) pFormat, (DWORD) pSizeAllocated, (LPDWORD) pSizeWritten ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetFormat()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetFrequency() // Description: The TDx_SoundBuffer::GetFrequency method will return the // frequency, in samples per second, at which the sound buffer // is playing. // // The minimum and maximum frequencies are defined in the // dsound.h DSBFREQUENCY_MIN and DSBFREQUENCY_MAX members as 100 // and 100,000 respectively. // // If the method call fails, the OnError event will be triggered // with one of the following values: // TDX_BADPARAMS // DSERR_CONTROLUNAVAIL // DSERR_INVALIDPARAM // DSERR_PRIOLEVELNEEDED // Params: pFrequency - // The Frequency parameter will reference the playing frequency // of the buffer if this method returns successfully. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::GetFrequency( dword* pFrequency ) { // Original Function Definition // HRESULT GetFrequency( // LPDWORD lpdwFrequency // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetFrequency()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pFrequency==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::GetFrequency()", "TDX_BADPARAMS", "'pFrequency' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->GetFrequency( (LPDWORD) pFrequency ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetFrequency()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetPan() // Description: The TDx_SoundBuffer::GetPan method will return the relative // volume of the left and right audio channels. // // The left, right and center pan values are defined in the // dsound.h DSBPAN_LEFT, DSBPAN_RIGHT and DSBPAN_CENTER members // as -10,000, 10,000 and 0 respectively. // // If the method call fails, the OnError event will be triggered // with one of the following values: // TDX_BADPARAMS // DSERR_CONTROLUNAVAIL // DSERR_INVALIDPARAM // DSERR_PRIOLEVELNEEDED // Params: pPan - // The Pan parameter will reference the relative volume of the // left and right audio channels if this method returns // successfully. // // Displacement to the negative represents attenuation, in // 100ths of a decibel, of the right channel and displacement to // the positive represents attentuation of the left channel in a // similar manner. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::GetPan( long* pPan ) { // Original Function Definition // HRESULT GetPan( // LPLONG lplPan // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetPan()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pPan==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::GetPan()", "TDX_BADPARAMS", "'pPan' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->GetPan( (LPLONG) pPan ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetPan()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetStatus() // Description: The TDx_SoundBuffer::GetStatus method will return the current // status of the sound buffer. // // If the method call fails, the OnError event may be triggered // with the following value: // TDX_BADPARAMS // DSERR_INVALIDPARAM // Params: pStatus - // The Status parameter will reference flags indicating the // current status of the sound buffer if this method returns // successfully. // The described effect applies when the flag is set. // Flags: // DSBSTATUS_BUFFERLOST - // The buffer has been lost. // Restoration is required before playing or locking of // the buffer can be performed. // DSBSTATUS_LOCHARDWARE - // The buffer is playing and is located in hardware // memory. // This flag only applies for buffers created with // DSBCAPS_LOCDEFER set. // DSBSTATUS_LOCSOFTWARE - // The buffer is playing and is located in system memory. // This flag only applies for buffers created with // DSBCAPS_LOCDEFER set. // DSBSTATUS_LOOPING - // The buffer is looping. // The buffer returns to the beginning and continues // playing when it reaches the end of the buffer. // When this flag is set, the buffer will also be playing. // DSBSTATUS_PLAYING - // The buffer is playing. // DSBSTATUS_TERMINATED - // The buffer is not playing. // This flag is set when the voice management logic halts // the play of a sound buffer and only applies for buffers // created with DSBCAPS_LOCDEFER set. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::GetStatus( dword* pStatus ) { // Original Function Definition // HRESULT GetStatus( // LPDWORD lpdwStatus // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetStatus()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pStatus==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::GetStatus()", "TDX_BADPARAMS", "'pStatus' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->GetStatus( (LPDWORD) pStatus ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetStatus()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetVolume() // Description: The TDx_SoundBuffer::GetVolume method will return the volume, // in 100ths of a decibel, currently set for the sound buffer. // // The minimum and maximum volumes are defined in the dsound.h // DSBVOLUME_MIN and DSBVOLUME_MAX members as -10,000 and 0 // respectively. // // Minimum volume indicates the sound is attenuated by 100 // decibels while the maximum volume represents the original // unadjusted volume of the sound. // // If the method call fails, the OnError event will be triggered // with one of the following values: // TDX_BADPARAMS // DSERR_CONTROLUNAVAIL // DSERR_INVALIDPARAM // DSERR_PRIOLEVELNEEDED // Params: pVolume - // The Volume parameter will reference the volume, in 100ths of // a decibel, of the buffer if this method returns successfully. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::GetVolume( long* pVolume ) { // Original Function Definition // HRESULT GetVolume( // LPLONG lplVolume // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetVolume()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pVolume==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::GetVolume()", "TDX_BADPARAMS", "'pVolume' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->GetVolume( (LPLONG) pVolume ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetVolume()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: Lock() // Description: The TDx_SoundBuffer::Lock method will return a valid write // pointer to the buffer's audio data. // // This method returns write pointers only, do not attempt to // use them for the purpose of reading. // // The buffer should not be locked for long periods of time as // the play cursor may reach the locked portion of the buffer // and cause configuration dependent audio problems. // // If the method call fails, the OnError event will be triggered // with one of the following values: // TDX_BADPARAMS // DSERR_BUFFERLOST // DSERR_INVALIDCALL // DSERR_INVALIDPARAM // DSERR_PRIOLEVELNEEDED // Params: pWriteCursor - // The WriteCursor parameter defines the offset, in bytes, of // where the lock is to begin in the buffer. // // Setting either of the flags in the flags parameter of this // method causes this parameter to be ignored. // pWriteBytes - // The WriteBytes parameter defines the amount, in bytes, of // buffer to be locked. // // The space that is locked may wrap around to the start of the // buffer, which is conceptually circular, in which case the // AudioPtr2 parameter of this method will reference the start // of the buffer. // pAudioPtr1 - // The AudioPtr1 parameter will reference the first block of // locked sound buffer if this method returns successfully. // pAudioBytes1 - // The AudioBytes1 parameter references the number of bytes // referenced by the AudioPtr1 parameter of this method. // // When this value is less than the value in the WriteBytes // parameter of this method, it means AudioPtr2 will reference a // second block of sound data. // pAudioPtr2 - // The AudioPtr2 parameter will reference the second block of // locked sound buffer if this method returns successfully. // // When this parameter is NULL it means AudioPtr1 references the // entire locked region of the sound buffer and any portion of // the area that wraps around will not be locked. // pAudioBytes2 - // The AudioBytes2 parameter references the number of bytes // referenced by the AudioPtr2 parameter of this method. // // When the AudioPtr2 parameter of this method is set to NULL, // this parameter will be 0. // pFlags - // The Flags parameter defines flags indicating modifications to // the lock event. // The described effect applies when the flag is set. // Flags: // DSBLOCK_ENTIREBUFFER - // Lock the whole sound buffer. // Setting this flag causes the WriteCursor parameter of // this method to be ignored. // DSBLOCK_FROMWRITECURSOR - // Use the current write position as the start of the // sound buffer lock area. // Setting this flag causes the WriteCursor parameter of // this method to be ignored. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::Lock( dword pWriteCursor, dword pWriteBytes, void** pAudioPtr1, dword* pAudioBytes1, void** pAudioPtr2, dword* pAudioBytes2, dword pFlags ) { // Original Function Definition // HRESULT Lock( // DWORD dwWriteCursor, // DWORD dwWriteBytes, // LPVOID* lplpvAudioPtr1, // LPDWORD lpdwAudioBytes1, // LPVOID* lplpvAudioPtr2, // LPDWORD lpdwAudioBytes2, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Lock()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pAudioPtr1==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::Lock()", "TDX_BADPARAMS", "'pAudioPtr1' cannot be 'NULL'"); return false; } if (pAudioBytes1==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::Lock()", "TDX_BADPARAMS", "'pAudioBytes1' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->Lock( (DWORD) pWriteCursor, (DWORD) pWriteBytes, (LPVOID*) pAudioPtr1, (LPDWORD) pAudioBytes1, (LPVOID*) pAudioPtr2, (LPDWORD) pAudioBytes2, (DWORD) pFlags ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::Lock()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); // Translate Errors to Events if ((fErrorValue==DSERR_BUFFERLOST) && (FOnBufferLost)) FOnBufferLost(this); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: OpenStream() // Description: The OpenStream method will open an existing .wav file for // reading or writing. // This method will automatically fill the internal WAVEFORMATEX // structure referenced by the StreamFormat property of this // component with the format data of the .wav file being opened. // // Once opened the file can be read with // TDx_SoundBuffer::ReadFromStream() or written using // TDx_SoundBuffer::WriteToStream(). // Once all data has been read from or written to the stream, // close the stream using TDx_SoundBuffer::CloseStream() // When the stream is open, the TDx_SoundBuffer::StreamIsOpen // property will be true. // // If the method call fails, the OnError event will be triggered // with one of the following values: // TDX_BADPARAMS // TDX_ERROR // Params: pFileName - // The FileName parameter defines the path and filename of the // exisitng .wav file which is to be opened. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::OpenStream( AnsiString pFileName ) { // check 'filename' parameter if (pFileName=="") { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError(this, Name+"::OpenStream()", "TDX_BADPARAMS", "The 'FileName' parameter cannot be a NULL string." ); return false; } if (pFileName.UpperCase().Pos(".WAV")==0) pFileName = pFileName +".WAV"; // cleanup ready to open the stream if (StreamIsOpen) CloseStream(); // open the stream fStreamHandle = open( pFileName.c_str(), O_BINARY | O_RDWR, S_IREAD|S_IWRITE ); if (fStreamHandle==NULL) { fErrorValue = TDX_ERROR; if (FOnError) FOnError(this, Name+"::OpenStream()", "TDX_ERROR", "Cannot open the media file: "+pFileName+"." ); return false; } // read the wave file header from the file int error = read( fStreamHandle, (void*) &fWaveFileFormat, sizeof(TDX_WAVE_FILE_FORMAT) ); if (error==-1) { close( fStreamHandle ); fStreamHandle = NULL; fErrorValue = TDX_ERROR; if (FOnError) FOnError(this, Name+"::OpenStream()", "TDX_ERROR", "Cannot create the media file: "+pFileName+" because the Wave File Format could not be created." ); return false; } // allocate memory for the internal format if (fStreamFormat!=NULL) delete[] fStreamFormat; fStreamFormat = (WAVEFORMATEX*) new WAVEFORMATEX; if (fStreamFormat==NULL) { close( fStreamHandle ); fErrorValue = TDX_ERROR; if (FOnError) FOnError(this, Name+"::OpenStream()", "TDX_ERROR", "Cannot allocate memory for internal storage of the WAVEFORMATEX structure passed in via the 'Format' parameter." ); return false; } // copy the format supplied into internal storage CopyMemory( fStreamFormat, (void*) &fWaveFileFormat.format_chunk.format, sizeof(TDX_WAVE_FORMAT) ); // successfully created the stream fStreamSize = fWaveFileFormat.data_chunk.size; fStreamIsOpen = true; fErrorValue = DS_OK; return true; } // -------------------------------------------------------------------------- // Method: Play() // Description: The TDx_SoundBuffer::Play method will cause the sound buffer // to play from the current position of the play cursor. // // Calling this method will succeed, but no sound will be // produced unless a cooperative level has been set using // TDx_Sound::SetCooperativeLevel(). // // A secondary buffer being played when there is no primary // buffer will cause the primary buffer to be automatically // created and played. // // Calling this method when the buffer is already playing will // succeed, playing will continue using the flag settings // defined in the latest call to this method. // // Calling this method on a primary buffer will cause it to // continue playing between sounds, thus reducing the overhead // of starting and stopping play and potential sound artifacts // such as popping. // // If the method call fails, the OnError event will be triggered // with one of the following values: // DSERR_BUFFERLOST // DSERR_HWUNAVAIL // DSERR_INVALIDCALL // DSERR_INVALIDPARAM // DSERR_PRIOLEVELNEEDED // Params: pPriority - // The Priority parameter defines the priority given to the // sound being played. // // This value may be used to decide which sound buffer is played // using hardware resources when DSBPLAY_TERMINATEBY_PRIORITY is // set in the Flags parameter of this method. // // When DSBCAPS_ LOCDEFER is not set, this parameter must be 0. // Priorities range from 0 to ffffffff, with 0 having the lowest // priory. // pFlags - // The Flags parameter defines a flag indicating how the buffer // is to be played. // The described effect applies when the flag is set. // Flags: // DSBPLAY_LOCHARDWARE - // Play the sound using hardware only. // // The buffer must have DSBCAPS_LOCDEFER set. // DSBPLAY_LOCSOFTWARE cannot be set in conjunction with // this flag. // If no hardware voices are available and no // DSBPLAY_TERMINATEBY_xxx flags set, the method call will // fail. // When neither this flag or DBSPLAY_LOCSOFTWARE are set, // the sound will be played using hardware or software, // depending on resource availablility. // DSBPLAY_LOCSOFTWARE - // Play the sound using software only. // // The buffer must have DSBCAPS_LOCDEFER set. // The DSBPLAY_LOCHARDWARE and DSBPLAY_TERMINATEBY_xxx // flags cannot be set in conjunction with this flag. // When neither this flag or DBSPLAY_LOCHARDWARE are set, // the sound will be played using hardware or software, // depending on resource availablility. // DSBPLAY_LOOPING - // Play restarts from the beginning of the buffer whenever // the end is reached. // Primary sound buffers must have this flag set. // DSBPLAY_TERMINATEBY_DISTANCE - // If there are no hardware resources available, stop // playing a 3D buffer that has // DSBCAPS_MUTE3DATMAXDISTANCE set and is beyond its max // distance and play this buffer instead. // If there are no 3D buffers meeting the requirements, // the play will fail. // Only 3D buffers with DSBCAPS_LOCDEFER set may be // terminated in this way. // DSBPLAY_TERMINATEBY_PRIORITY - // If there are no hardware resources available, stop // playing the buffer with the lowest priority and play // this buffer instead. // A buffers priority is defined by the Priority parameter // of this method and the play will fail if there are no // hardware buffers with a lower priority than this one. // DSBPLAY_TERMINATEBY_DISTANCE cannot be set in // conjunction with this flag. // Only buffers with DSBCAPS_LOCDEFER set may be // terminated in this way. // DSBPLAY_TERMINATEBY_TIME - // If there are no hardware resources available, stop // playing the buffer with the least play time left and // play this buffer instead. // Only buffers with DSBCAPS_LOCDEFER set may be // terminated in this way. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::Play( dword pPriority, dword pFlags ) { // Original Function Definition // HRESULT Play( // DWORD dwReserved1, // DWORD dwPriority, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Play()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->Play( 0, (DWORD) pPriority, (DWORD) pFlags ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::Play()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); // Translate Errors to Events if ((fErrorValue==DSERR_BUFFERLOST) && (FOnBufferLost)) FOnBufferLost(this); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: ReadFromStream() // Description: The ReadFromStream method will read a specified amount of // sound data from the .wav file opened with // TDx_SoundBuffer::OpenStream(). // // If the method call fails, the OnError event will be triggered // with one of the following values: // TDX_BADPARAMS // TDX_ERROR // Params: pBytesToRead - // The BytesToRead parameter defines the amount, in bytes, of // sound data to read from the current .wav file. // pSoundData - // The SoundData parameter references the array of bytes that // will be used for holding the sound data read from the current // .wav file. // // The provided byte array must be large enough to contain the // amount of data specified by the BytesToRead parameter. // // This parameter may be set to one of the pointers returned by // TDx_SoundBuffer::Lock() to read sound data directly into the // sound buffer. // pBytesActuallyRead - // The BytesActuallyRead parameter will reference the amount, in // bytes, that was actually written to the SoundData parameter // if this method returns successfully. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::ReadFromStream( dword pBytesToRead, byte* pSoundData, dword* pBytesActuallyRead ) { if (pBytesToRead==0) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError(this, Name+"::ReadFromStream()", "TDX_BADPARAMS", "Cannot read from the stream because the 'BytesToRead' parameter is 0." ); return false; } if (pSoundData==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError(this, Name+"::ReadFromStream()", "TDX_BADPARAMS", "Cannot read from the stream because the 'SoundData' parameter is NULL." ); return false; } if (pBytesActuallyRead==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError(this, Name+"::ReadFromStream()", "TDX_BADPARAMS", "Cannot read from the stream because the 'BytesActuallyRead' parameter is NULL." ); return false; } if (!StreamIsOpen) { fErrorValue = TDX_ERROR; if (FOnError) FOnError(this, Name+"::ReadFromStream()", "TDX_ERROR", "Cannot read from the stream because it is not open." ); return false; } // read the relevant number of bytes to the file int bytes_actually_read = read( fStreamHandle, (void*) pSoundData, pBytesToRead ); if (bytes_actually_read==-1) { fErrorValue = TDX_ERROR; if (FOnError) FOnError(this, Name+"::ReadFromStream()", "TDX_ERROR", "Cannot read because the read() function reached the end of file before reading enough data." ); return false; } // done *pBytesActuallyRead = bytes_actually_read; fErrorValue = DS_OK; return true; } // -------------------------------------------------------------------------- // Method: Restore() // Description: The TDx_SoundBuffer::Restore method will restore memory // allocated to the sound buffer when it has been lost. // // This method restores the memory, not the contents, of the // sound buffer. // Attempts to restore buffers when the application does not // have the input focus may not succeed. // // If the method call fails, the OnError event will be triggered // with one of the following values: // DSERR_BUFFERLOST // DSERR_INVALIDCALL // DSERR_INVALIDPARAM // DSERR_PRIOLEVELNEEDED // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::Restore() { // Original Function Definition // HRESULT Restore(); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Restore()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->Restore( ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::Restore()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); // Translate Errors to Events if ((fErrorValue==DSERR_BUFFERLOST) && (FOnBufferLost)) FOnBufferLost(this); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SaveToFile() // Description: The SaveToFile method will save the entire sound buffer to a // specified file. // // This method will not append data. If you wish to save sound // data a segment at a time, TDx_SoundBuffer::WriteToStream() // should be used. // // The application should ensure the desired WAVEFORMATEX values // are set in the StreamFormat property of this component prior // to calling this method. // // If the method call fails, the OnError event will be triggered // with one of the following values: // TDX_BADPARAMS // TDX_ERROR // Params: pFileName - // The FileName parameter defines the path and filename of the // new .wav file which is to be created. // pFormat - // The Format method parameter describes the format of the sound // file to be created. This parameter must point to a // user-supplied WAVEFORMATEX structure that has been filled // with appropriate values. // pFormatSize - // The FormatSize parameter must contain the size of the // WAVEFORMATEX structure passed into this method via the Format // parameter. Generally this will be sizeof(WAVEFORMATEX) but it // may differ depending on the definition of the WAVEFORMATEX. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::SaveToFile( AnsiString pFileName, WAVEFORMATEX* pFormat, int pFormatSize ) { // check params if (pFileName=="") { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError(this, Name+"::SaveToFile()", "TDX_BADPARMS", "The 'FileName' parameter cannot be a NULL string." ); return false; } if (pFileName.UpperCase().Pos(".WAV")==0) pFileName = pFileName +".WAV"; // check params if (pFormat==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::SaveToFile()", "TDX_BADPARAMS", "The 'pFormat' parameter cannot be NULL" ); return false; } if (pFormatSizeSetCurrentPosition( (DWORD) pNewPosition ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetCurrentPosition()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetFormat() // Description: The TDx_SoundBuffer::SetFormat method will set the primary // sound buffer format for the application. // // The application must hold at least the DSSCL_PRIORITY // cooperative level for this method to succeed. // // Whenever the application has the input focus, the primary // buffer will be set to the specified format. // // When the DSSCL_WRITEPRIMARY cooperative level is being used, // the buffer must be explicitly stopped and started for the // SetFormat call. The buffer will be automatically stopped and // started for the other cooperative levels. // // Setting an unsupported format will still succeed. The closest // supported format will be used and conversion from the // requested format will be performed during mixing. This may // cause some performance loss. Compare the specified format // with that retrieved using TDx_SoundBuffer::GetFormat() to // determine if this is being done. // // To change the data format for a secondary sound buffer, // recreate the buffer with the new format. // // Compressed audio formats are not currently supported and must // be converted to pulse-code modulation (PCM) before writing to // a sound buffer. // // If the method call fails, the OnError event will be triggered // with one of the following values: // TDX_BADPARAMS // DSERR_BADFORMAT // DSERR_INVALIDCALL // DSERR_INVALIDPARAM // DSERR_OUTOFMEMORY // DSERR_PRIOLEVELNEEDED // DSERR_UNSUPPORTED // Params: pFormat - // The Format parameter references a WAVEFORMATEX structure // which describes the new primary sound buffer format. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::SetFormat( const WAVEFORMATEX* pFormat ) { // Original Function Definition // HRESULT SetFormat( // LPCWAVEFORMATEX lpcfxFormat // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetFormat()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pFormat==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::SetFormat()", "TDX_BADPARAMS", "'pFormat' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->SetFormat( (LPCWAVEFORMATEX) pFormat ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetFormat()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetFrequency() // Description: The TDx_SoundBuffer::SetFrequency method will define the // playing frequency, in Hertz, of audio samples for a secondary // sound buffer. // // The minimum and maximum frequencies are defined in the // dsound.h DSBFREQUENCY_MIN and DSBFREQUENCY_MAX members as 100 // and 100,000 respectively. // // Changing frequency modifies the pitch of audio data, not the // format. // // If the method call fails, the OnError event will be triggered // with one of the following values: // TDX_BADPARAMS // DSERR_CONTROLUNAVAIL // DSERR_GENERIC // DSERR_INVALIDPARAM // DSERR_PRIOLEVELNEEDED // Params: pFrequency - // The Frequency parameter defines the frequency, in hertz, at // which audio samples are to be played by the buffer. // // DSBFREQUENCY_ORIGINAL may be used to restore the original // frequency defined in the format used when creating the // buffer. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::SetFrequency( dword pFrequency ) { // Original Function Definition // HRESULT SetFrequency( // DWORD dwFrequency // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetFrequency()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->SetFrequency( (DWORD) pFrequency ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetFrequency()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetPan() // Description: The TDx_SoundBuffer::SetPan method will set the relative // volume for the left and right audio channels. // // The left, right and center pan values are defined in the // dsound.h DSBPAN_LEFT, DSBPAN_RIGHT and DSBPAN_CENTER members // as -10,000, 10,000 and 0 respectively. // // If the method call fails, the OnError event will be triggered // with one of the following values: // DSERR_CONTROLUNAVAIL // DSERR_GENERIC // DSERR_INVALIDPARAM // DSERR_PRIOLEVELNEEDED // Params: pPan - // The Pan parameter defines the relative volume of the left and // right channels. // Displacement to the negative represents attenuation, in // 100ths of a decibel, of the right channel and displacement to // the positive represents attentuation to the left channel in a // similar manner. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::SetPan( long pPan ) { // Original Function Definition // HRESULT SetPan( // LONG lPan // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetPan()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->SetPan( (LONG) pPan ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetPan()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetVolume() // Description: The TDx_SoundBuffer::SetVolume method will set the volume, in // 100ths of a decibel, for the sound buffer. // // The minimum and maximum volumes are defined in the dsound.h // DSBVOLUME_MIN and DSBVOLUME_MAX members as -10,000 and 0 // respectively. // // Minimum volume indicates the sound is attenuated by 100 // decibels while the maximum volume represents the original // unadjusted volume of the sound. // // If the method call fails, the OnError event will be triggered // with one of the following values: // DSERR_CONTROLUNAVAIL // DSERR_GENERIC // DSERR_INVALIDPARAM // DSERR_PRIOLEVELNEEDED // Params: pVolume - // The Volume parameter defines the volume, in 100ths of a // decibel, to be set for the buffer. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::SetVolume( long pVolume ) { // Original Function Definition // HRESULT SetVolume( // LONG lVolume // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetVolume()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->SetVolume( (LONG) pVolume ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetVolume()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: Stop() // Description: The TDx_SoundBuffer::Stop method will halt the playing of the // sound buffer. // // The play position of a secondary buffer will be set to the // next sample to be played. Play will resume from where the // buffer was stopped. // // When called on a primary buffer utilizing the // DSSCL_WRITEPRIMARY cooperative level, the buffer will be // stopped and the play position reset to 0. This is done // because most sound devices can only play from the beginning // of the primary buffer. // // For other cooperative levels, this method will reverse the // effects of TDx_SoundBuffer::Play() being called on a primary // buffer. // That is, the buffer will stop whenever there are no secondary // buffers playing. The buffer will not actually stop playing // until all the secondary buffers of this or any other // application have stopped. // // If the method call fails, the OnError event will be triggered // with one of the following values: // DSERR_INVALIDPARAM // DSERR_PRIOLEVELNEEDED // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::Stop() { // Original Function Definition // HRESULT Stop(); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Stop()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->Stop( ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::Stop()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: Unlock() // Description: The TDx_SoundBuffer::Unlock method will release the sound // buffer area previously locked by TDx_SoundBuffer::Lock(). // // Both pointers and both byte values returned by // TDx_SoundBuffer::Lock() must be supplied, even if 0 bytes // were written to the second pointer. // // Do not lock the sound buffer for long periods of time as the // play cursor could reach the locked bytes and configuration // dependent audio problems may result. // // If the method call fails, the OnError event will be triggered // with one of the following values: // TDX_BADPARAMS // DSERR_INVALIDCALL // DSERR_INVALIDPARAM // DSERR_PRIOLEVELNEEDED // Params: pAudioPtr1 - // The AudioPtr1parameter should reference the value returned in // the AudioPtr1 parameter of TDx_SoundBuffer::Lock(). // pAudioBytes1 - // The AudioBytes1 parameter defines the number of bytes written // to the area referenced by the AudioPtr1 parameter. // pAudioPtr2 - // The AudioPtr2 parameter should reference the value returned // in the AudioPtr2 parameter of TDx_SoundBuffer::Lock(). // pAudioBytes2 - // The AudioBytes2 parameter defines the number of bytes written // to the area referenced by the AudioPtr2 parameter. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::Unlock( void* pAudioPtr1, dword pAudioBytes1, void* pAudioPtr2, dword pAudioBytes2 ) { // Original Function Definition // HRESULT Unlock( // LPVOID lpvAudioPtr1, // DWORD dwAudioBytes1, // LPVOID lpvAudioPtr2, // DWORD dwAudioBytes2 // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Unlock()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pAudioPtr1==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::Unlock()", "TDX_BADPARAMS", "'pAudioPtr1' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTSOUNDBUFFER->Unlock( (LPVOID) pAudioPtr1, (DWORD) pAudioBytes1, (LPVOID) pAudioPtr2, (DWORD) pAudioBytes2 ); // Handle any Known Results if (fErrorValue!=DS_OK) { // Failure. if (FOnError) FOnError( this, Name+"::Unlock()", TDx_Sound_Library_ErrorString(fErrorValue), TDx_Sound_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: WriteToStream() // Description: The WriteToStream method will write a specified amount of // sound data to the current .wav file. // // If the method call fails, the OnError event will be triggered // with one of the following values: // TDX_BADPARAMS // TDX_ERROR // Params: pBytesToWrite - // The BytesToWrite parameter defines the amount, in bytes, of // sound data to write to the current .wav file. // pSoundData - // The SoundData parameter references the array of bytes that // will be written to the current .wav file. // // This parameter may be set to one of the pointers returned by // TDx_SoundBuffer::Lock() to write sound data directly from the // sound buffer. // pBytesActuallyWritten - // The BytesActuallyWritten parameter will reference the amount, // in bytes, that was actually written to the file if this // method returns successfully. // -------------------------------------------------------------------------- bool __fastcall TDx_SoundBuffer::WriteToStream( dword pBytesToWrite, byte* pSoundData, dword* pBytesActuallyWritten ) { if (pBytesToWrite==0) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError(this, Name+"::WriteToStream()", "TDX_BADPARAMS", "Cannot write from the stream because the 'BytesToWrite' parameter is 0." ); return false; } if (pSoundData==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError(this, Name+"::WriteToStream()", "TDX_BADPARAMS", "Cannot write from the stream because the 'SoundData' parameter is NULL." ); return false; } if (pBytesActuallyWritten==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError(this, Name+"::WriteToStream()", "TDX_BADPARAMS", "Cannot write from the stream because the 'BytesActuallyWrite' parameter is NULL." ); return false; } if (!StreamIsOpen) { fErrorValue = TDX_ERROR; if (FOnError) FOnError(this, Name+"::WriteToStream()", "TDX_ERROR", "Cannot write from the stream because it is not open." ); return false; } // write the relevant number of bytes to the file int bytes_actually_written = write( fStreamHandle, (void*) pSoundData, pBytesToWrite ); if (bytes_actually_written==-1) { fErrorValue = TDX_ERROR; if (FOnError) FOnError(this, Name+"::WriteToStream()", "TDX_ERROR", "Cannot write because the write() function reached the end of file before writing enough data." ); return false; } // done *pBytesActuallyWritten = bytes_actually_written; fStreamSize += bytes_actually_written; fErrorValue = DS_OK; return true; } // -------------------------------------------------------------------------- // Internal Interface Access // -------------------------------------------------------------------------- LPDIRECTSOUNDBUFFER __fastcall TDx_SoundBuffer::FGetInternal_LPDIRECTSOUNDBUFFER() { return fLPDIRECTSOUNDBUFFER; } // -------------------------------------------------------------------------- LPDIRECTSOUNDBUFFER* __fastcall TDx_SoundBuffer::FGetInternal_LPDIRECTSOUNDBUFFER_Ptr() { return &fLPDIRECTSOUNDBUFFER; } // -------------------------------------------------------------------------- void __fastcall TDx_SoundBuffer::FSetInternal_LPDIRECTSOUNDBUFFER( LPDIRECTSOUNDBUFFER pLPDIRECTSOUNDBUFFER ) { if (!fCreated) { fLPDIRECTSOUNDBUFFER = pLPDIRECTSOUNDBUFFER; fCreated = (fLPDIRECTSOUNDBUFFER!=NULL); } } // -------------------------------------------------------------------------- void __fastcall TDx_SoundBuffer::Internal_LPDIRECTSOUNDBUFFER_Update() { fCreated = (fLPDIRECTSOUNDBUFFER!=NULL); } // --------------------------------------------------------------------------