- Main Page
- Namespaces
- Classes
- Files
- Directories
- Related Pages

- File List
- File Members

# TAudioBuffer.hpp

Go to the documentation of this file.

    00001 #ifndef __TAudioBuffer__
    00002 #define __TAudioBuffer__
    00003
    00004 //  ===========================================================================
    00005
    00006 #include <Basics/CCountedObject.hpp>
    00007 #include <MathTools/CMathTools.hpp>
    00008 #include <Collections/TAutomaticPointer.hpp>
    00009 using Exponent::MathTools::CMathTools;
    00010 using Exponent::Basics::CCountedObject;
    00011 using Exponent::Collections::TAutomaticPointer;
    00012
    00013 //  ===========================================================================
    00014
    00015 namespace Exponent
    00016 {
    00017     namespace Audio
    00018     {
    00036         template<typename TypeName> class TAudioBuffer : public CCountedObject
    00037         {
    00039             EXPONENT_CLASS_DECLARATION;
    00042 //  ===========================================================================
    00043
    00044         public:
    00045
    00046 //  ===========================================================================
    00047
    00052             typedef TAutomaticPointer< TAutomaticPointer<TypeName> > TAudioBufferPointer;
    00053
    00054 //  ===========================================================================
    00055
    00059             TAudioBuffer() : m_buffer(NULL), m_numberOfSamples(0), m_numberOfChannels(0), m_bufferSize(0)
    00060             {
    00061                 NULL_POINTER(m_buffer);
    00062                 m_numberOfSamples  = 0;
    00063                 m_numberOfChannels = 0;
    00064                 m_bufferSize       = 0;
    00065             }
    00066
    00070             virtual ~TAudioBuffer()
    00071             {
    00072                 this->uninitialise();
    00073             }
    00074
    00075 //  ===========================================================================
    00076
    00077
    00084             bool initialise(const unsigned long numberOfSamples, const unsigned long numberOfChannels)
    00085             {
    00086                 // Delete the old buffer
    00087                 if (m_buffer)
    00088                 {
    00089                     this->uninitialise();
    00090                 }
    00091
    00092                 // Total size of the buffer
    00093                 m_numberOfSamples  = numberOfSamples;
    00094                 m_numberOfChannels = numberOfChannels;
    00095                 m_bufferSize       = m_numberOfSamples * m_numberOfChannels;
    00096
    00097                 // Create the buffer
    00098                 m_buffer = new TypeName[m_bufferSize];
    00099
    00100                 // Clear the audio buffers out
    00101                 this->clearBuffer();
    00102
    00103                 // We are done :)
    00104                 return true;
    00105             }
    00106
    00110             void uninitialise()
    00111             {
    00112                 // Check we've got a buffer
    00113                 if (m_buffer)
    00114                 {
    00115                     // Delete the main buffer
    00116                     FREE_ARRAY_POINTER(m_buffer);
    00117
    00118                     // Default values
    00119                     m_numberOfChannels = 0;
    00120                     m_numberOfSamples  = 0;
    00121                     m_bufferSize       = 0;
    00122                 }
    00123             }
    00124
    00128             void clearBuffer()
    00129             {
    00130                 // Check we've got a buffer
    00131                 if (m_buffer)
    00132                 {
    00133                     memset(m_buffer, 0, m_bufferSize * sizeof(TypeName));
    00134                 }
    00135             }
    00136
    00137 //  ===========================================================================
    00138
    00145             const TypeName *operator[](const long index) const
    00146             {
    00147                 return this->getChannel(index);
    00148             }
    00149
    00150 //  ===========================================================================
    00151
    00161             const TypeName *getChannel(const unsigned long index) const
    00162             {
    00163                 if (m_buffer && index < m_numberOfChannels)
    00164                 {
    00165                     return &m_buffer[index];
    00166                 }
    00167                 return NULL;
    00168             }
    00169
    00179             TypeName *getMutableChannel(const unsigned long index)
    00180             {
    00181                 if (m_buffer && index < m_numberOfChannels)
    00182                 {
    00183                     return &m_buffer[index];
    00184                 }
    00185                 return NULL;
    00186             }
    00187
    00192             const TypeName *getData() const
    00193             {
    00194                 if (m_buffer)
    00195                 {
    00196                     return m_buffer;
    00197                 }
    00198                 return NULL;
    00199             }
    00200
    00205             TypeName *getMutableData()
    00206             {
    00207                 if (m_buffer)
    00208                 {
    00209                     return m_buffer;
    00210                 }
    00211                 return NULL;
    00212             }
    00213
    00214 //  ===========================================================================
    00215
    00220             FORCEINLINE unsigned long getNumberOfChannels() const { return m_numberOfChannels; }
    00221
    00226             FORCEINLINE unsigned long getNumberOfSamples() const { return m_numberOfSamples; }
    00227
    00232             FORCEINLINE unsigned long getBufferSize() const { return m_bufferSize; }
    00233
    00240             FORCEINLINE unsigned long getSampleFrameSize() const { return m_numberOfChannels; }
    00241
    00242 //  ===========================================================================
    00243
    00249             TypeName getMaximumSample(const unsigned long channel) const
    00250             {
    00251                 if (channel < m_numberOfChannels && m_buffer)
    00252                 {
    00253                     TypeName *buffer  = &m_buffer[channel];
    00254                     TypeName maxValue = -2.0;   // Well outside of range
    00255                     for (long i = 0; i < m_numberOfSamples; i++)
    00256                     {
    00257                         maxValue = CMathTools::fastMaximum(*buffer, maxValue);
    00258                         buffer  += m_numberOfChannels;
    00259                     }
    00260                     return maxValue;
    00261                 }
    00262                 return (TypeName)0;
    00263             }
    00264
    00270             TypeName getMinimumSample(const unsigned long channel) const
    00271             {
    00272                 if (channel < m_numberOfChannels && m_buffer)
    00273                 {
    00274                     TypeName *buffer  = &m_buffer[channel];
    00275                     TypeName minValue = 2.0;    // Well outside of range
    00276                     for (long i = 0; i < m_numberOfSamples; i++)
    00277                     {
    00278                         minValue = CMathTools::fastMinimum(*buffer, minValue);
    00279                         buffer  += m_numberOfChannels;
    00280                     }
    00281                     return minValue;
    00282                 }
    00283                 return (TypeName)0;
    00284             }
    00285
    00293             FORCEINLINE TypeName getRMSLevel(const unsigned long channel, const unsigned long numberOfSamples, const unsigned long startSample = 0) const
    00294             {
    00295                 if (channel < m_numberOfChannels && m_buffer && numberOfSamples <= m_numberOfSamples && startSample + numberOfSamples <= m_numberOfSamples)
    00296                 {
    00297                     TypeName mean = 0.0;
    00298                     const TypeName *theChannel = &m_buffer[channel + (this->getSampleFrameSize() * startSample)];
    00299
    00300                     // Compute the squares
    00301                     for (unsigned long i = 0; i < numberOfSamples; i++)
    00302                     {
    00303                         mean += *theChannel * *theChannel;
    00304                         theChannel += this->getSampleFrameSize();
    00305                     }
    00306
    00307                     // Return the RMS
    00308                     return sqrt(mean / (TypeName)numberOfSamples);
    00309                 }
    00310                 return (TypeName)0;
    00311             }
    00312
    00316             void denormal()
    00317             {
    00318                 // Check the buffer is valid
    00319                 if (m_buffer == NULL)
    00320                 {
    00321                     return;
    00322                 }
    00323
    00324                 // Loop and apply the denormalling..
    00325                 for (unsigned long i = 0; i < m_bufferSize; i++)
    00326                 {
    00327                     m_buffer[i] += (TypeName)1e-15;
    00328                 }
    00329             }
    00330
    00335             bool mergeChannelsToMono()
    00336             {
    00337                 // Check we have an audio buffer
    00338                 if (m_buffer == NULL)
    00339                 {
    00340                     return false;
    00341                 }
    00342
    00343                 // Check if we are mono already
    00344                 if (m_numberOfChannels <= 1)
    00345                 {
    00346                     return true;        // We it is a sucess really ;)
    00347                 }
    00348
    00349                 // Compute the level of each channel
    00350                 const TypeName level = 1.0 / (TypeName)m_numberOfChannels;
    00351
    00352                 // Store the internal buffer
    00353                 TypeName *buffer = new TypeName[m_numberOfSamples];             // Note single channel!!
    00354                 memset(buffer, 0, m_numberOfSamples * sizeof(TypeName));
    00355                 TypeName *bufferPointer = &m_buffer[0];
    00356
    00357                 // Merge the samples
    00358                 for (unsigned long i = 0; i < m_numberOfSamples; i++)
    00359                 {
    00360                     for (unsigned long j = 0; j < m_numberOfChannels; j++)
    00361                     {
    00362                         buffer[i] += *bufferPointer++ * level;
    00363                     }
    00364                 }
    00365
    00366                 // Delete the old buffer
    00367                 FREE_POINTER(m_buffer);
    00368
    00369                 // Store the new buffer
    00370                 m_buffer = buffer;
    00371
    00372                 // Set the number of channels
    00373                 m_numberOfChannels = 1;
    00374                 m_bufferSize       = m_numberOfSamples;
    00375
    00376                 // We are complete!
    00377                 return true;
    00378             }
    00379
    00386             bool copySamples(const TypeName *buffer, const unsigned long numberOfSamples)
    00387             {
    00388                 // Check if we have room
    00389                 if (numberOfSamples <= m_numberOfSamples * m_numberOfChannels && m_buffer)
    00390                 {
    00391                     // Copy the buffer
    00392                     memcpy(m_buffer, buffer, numberOfSamples * sizeof(TypeName));
    00393
    00394                     // Complete!
    00395                     return true;
    00396                 }
    00397
    00398                 // Failed
    00399                 return false;
    00400             }
    00401
    00411             bool mergeChannelToBuffer(float *buffer, const unsigned long startSample, const unsigned long numberOfSamples, const unsigned long channel)
    00412             {
    00413                 // Compute the length to process
    00414                 const unsigned long length = startSample + numberOfSamples;
    00415
    00416                 // Check for the validity
    00417                 if (length <= m_numberOfSamples && channel < m_numberOfChannels && buffer != NULL)
    00418                 {
    00419                     //&m_buffer[index];
    00420
    00421                     // Get the audio data
    00422                     const TypeName *audioData = &m_buffer[channel][startSample * m_numberOfChannels];
    00423
    00424                     // Check we got proper audio data
    00425                     if (audioData == NULL)
    00426                     {
    00427                         return false;
    00428                     }
    00429
    00430                     // Now loop through and process
    00431                     for (unsigned long i = 0; i < numberOfSamples; i++)
    00432                     {
    00433                         buffer[i] += (float)*audioData;
    00434                         audioData += m_numberOfChannels;
    00435                     }
    00436
    00437                     // Sucess
    00438                     return true;
    00439                 }
    00440
    00441                 // Failed
    00442                 return false;
    00443             }
    00444
    00454             bool mergeChannelToBuffer(double *buffer, const unsigned long startSample, const unsigned long numberOfSamples, const unsigned long channel)
    00455             {
    00456                 // Compute the length to process
    00457                 const unsigned long length = startSample + numberOfSamples;
    00458
    00459                 // Check for the validity
    00460                 if (length <= m_numberOfSamples && channel < m_numberOfChannels && buffer != NULL)
    00461                 {
    00462                     //&m_buffer[index];
    00463
    00464                     // Get the audio data
    00465                     const TypeName *audioData = &m_buffer[startSample * m_numberOfChannels];
    00466
    00467                     // Now loop through and process
    00468                     for (unsigned long i = 0; i < numberOfSamples; i++)
    00469                     {
    00470                         buffer[i] += (double)*audioData;
    00471                         audioData += m_numberOfChannels;
    00472                     }
    00473
    00474                     // Sucess
    00475                     return true;
    00476                 }
    00477
    00478                 // Failed
    00479                 return false;
    00480             }
    00481
    00482 //  ===========================================================================
    00483
    00484         protected:
    00485
    00486 //  ===========================================================================
    00487
    00488             TypeName *m_buffer;
    00489             unsigned long m_numberOfSamples;
    00490             unsigned long m_numberOfChannels;
    00491             unsigned long m_bufferSize;
    00493 //  ===========================================================================
    00494
    00495         };
    00496
    00501         typedef TAudioBuffer<double> TDoublePrecisionAudioBuffer;
    00502
    00507         typedef TAudioBuffer<float> TSinglePrecisionAudioBuffer;
    00508
    00510          EXPONENT_TEMPLATE_CLASS_IMPLEMENTATION(TAudioBuffer<TypeName>, TypeName, CCountedObject);
    00512     }
    00513 }
    00514 #endif  // End of TAudioBuffer.hpp