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

Infinity API - TAudioBuffer.hpp Source File generated on 7 Mar 2007