00001 #ifndef __CAudioBuffer__
00002 #define __CAudioBuffer__
00003
00004
00005
00006 #include <Basics/CCountedObject.hpp>
00007 #include <Exceptions/CException.hpp>
00008 #include <MathTools/CMathTools.hpp>
00009
00010
00011
00012 using Exponent::Basics::CCountedObject;
00013 using Exponent::Exceptions::CException;
00014 using Exponent::MathTools::CMathTools;
00015
00016
00017
00018 namespace Exponent
00019 {
00020 namespace Audio
00021 {
00046 class CAudioBuffer : public CCountedObject
00047 {
00049 EXPONENT_CLASS_DECLARATION;
00052
00053
00054 public:
00055
00056
00057
00058 const static double CAUDIO_BUFFER_DENORMAL;
00060
00061
00066 enum EStereoChannels
00067 {
00068 e_left = 0,
00069 e_right,
00071 e_mono = 1,
00072 e_stereo,
00073 };
00074
00075
00076
00081 CAudioBuffer(const long bufferSize);
00082
00086 CAudioBuffer();
00087
00091 virtual ~CAudioBuffer();
00092
00093
00094
00099 double **getMutableAudioData() const { return m_waveData; }
00100
00105 const double **getAudioData() const { return (const double **)&m_waveData[0]; }
00106
00112 FORCEINLINE double *getChannel(const long channel) { return m_waveData[channel]; }
00113
00120 FORCEINLINE double getSample(const long channel, const long index) { return m_waveData[channel][index]; }
00121
00122
00123
00128 void initialise(const long bufferSize);
00129
00133 void uninitialise();
00134
00139 void reInitialise(const long bufferSize);
00140
00141
00142
00146 void FORCEINLINE clearWaveForm()
00147 {
00148 const size_t size = m_bufferSize * sizeof(double);
00149 memset(m_waveData[0], 0, size);
00150 memset(m_waveData[1], 0, size);
00151 }
00152
00153
00154
00158 void FORCEINLINE mergeChannels()
00159 {
00160 for (long i = 0; i < m_bufferSize; i++)
00161 {
00162 m_waveData[0][i] = m_waveData[1][i] = ((m_waveData[0][i] * 0.5) + (m_waveData[1][i] * 0.5));
00163 }
00164 }
00165
00171 void FORCEINLINE mergeWithBuffer(CAudioBuffer *buffer)
00172 {
00173 if (buffer->getBufferSize() != m_bufferSize)
00174 {
00175 throw CException("Buffer sizes do not match", "CAudioBuffer::mergeWithBuffer(CAudioBuffer *)");
00176 }
00177
00178 double *left = m_waveData[0];
00179 double *right = m_waveData[1];
00180 double *leftF = buffer->getChannel(e_left);
00181 double *rightF = buffer->getChannel(e_right);
00182
00183 for (long i = 0; i < m_bufferSize; i++)
00184 {
00185 left[i] += leftF[i];
00186 right[i] += rightF[i];
00187 }
00188 }
00189
00190
00191
00197 void FORCEINLINE accumulateInToFloatData(float **output, const long numberOfSamples)
00198 {
00199 double *left = m_waveData[0];
00200 double *right = m_waveData[1];
00201 float *leftF = output[0];
00202 float *rightF = output[1];
00203
00204 for (long i = 0; i < numberOfSamples; i++)
00205 {
00206 leftF[i] += (float)left[i];
00207 rightF[i] += (float)right[i];
00208 }
00209 }
00210
00217 void FORCEINLINE mergeToBuffer(double *output, const long numberOfSamples)
00218 {
00219 if (output == NULL)
00220 {
00221 throw CException("Output buffer is NULL", "CAudioBuffer::mergeToBuffer(double *, const long)");
00222 }
00223
00224 double *left = m_waveData[0];
00225 double *right = m_waveData[1];
00226
00227 for (long i = 0; i < numberOfSamples; i++)
00228 {
00229 output[i] = (left[i] * 0.5) + (right[i] * 0.5);
00230 }
00231 }
00232
00233
00234
00239 long getBufferSize() const { return m_bufferSize; }
00240
00241
00242
00248 void FORCEINLINE setFromAudioBuffer(CAudioBuffer *buffer)
00249 {
00250 if (buffer->getBufferSize() != m_bufferSize)
00251 {
00252 throw CException("Buffer sizes do not match", "CAudioBuffer::setFromAudioBuffer(CAudioBuffer *)");
00253 }
00254
00255 memcpy(m_waveData[0], buffer->getChannel(e_left), m_bufferSize * sizeof(double));
00256 memcpy(m_waveData[1], buffer->getChannel(e_right), m_bufferSize * sizeof(double));
00257 }
00258
00264 void FORCEINLINE setWaveDataFromFloatData(float **waveData, const long numberOfSamples)
00265 {
00266 double *left = m_waveData[0];
00267 double *right = m_waveData[1];
00268
00269 float *leftF = waveData[0];
00270 float *rightF = waveData[1];
00271
00272 for (long i = 0; i < numberOfSamples; i++)
00273 {
00274 left[i] = (double)leftF[i];
00275 right[i] = (double)rightF[i];
00276 }
00277 }
00278
00284 void FORCEINLINE setWaveDataFromFloatDataAndDenormal(float **waveData, const long numberOfSamples)
00285 {
00286 double *left = m_waveData[0];
00287 double *right = m_waveData[1];
00288
00289 float *leftF = waveData[0];
00290 float *rightF = waveData[1];
00291
00292 for (long i = 0; i < numberOfSamples; i++)
00293 {
00294 left[i] = (double)leftF[i] + CAUDIO_BUFFER_DENORMAL;
00295 right[i] = (double)rightF[i] + CAUDIO_BUFFER_DENORMAL;
00296 }
00297 }
00298
00304 void FORCEINLINE copyToFloatBufferFromWaveData(float **waveData, const long numberOfSamples)
00305 {
00306 double *left = m_waveData[0];
00307 double *right = m_waveData[1];
00308
00309 float *leftF = waveData[0];
00310 float *rightF = waveData[1];
00311
00312 for (long i = 0; i < numberOfSamples; i++)
00313 {
00314 leftF[i] = (float)left[i];
00315 rightF[i] = (float)right[i];
00316 }
00317 }
00318
00319
00320
00325 void FORCEINLINE denormal(const long numberOfSamples)
00326 {
00327 double *left = m_waveData[0];
00328 double *right = m_waveData[1];
00329 for (long i = 0; i < numberOfSamples; i++)
00330 {
00331 left[i] += CAUDIO_BUFFER_DENORMAL;
00332 right[i] += CAUDIO_BUFFER_DENORMAL;
00333 }
00334 }
00335
00340 void FORCEINLINE changeGain(const double volume)
00341 {
00342 double *left = m_waveData[0];
00343 double *right = m_waveData[1];
00344 for (long i = 0; i < m_bufferSize; i++)
00345 {
00346 left[i] *= volume;
00347 right[i] *= volume;
00348 }
00349 }
00350
00356 void getMaxSamples(double &left, double &right);
00357
00362 void FORCEINLINE applyTanhLimiting()
00363 {
00364 double *left = m_waveData[0];
00365 double *right = m_waveData[1];
00366 for (long i = 0; i < m_bufferSize; i++)
00367 {
00368 left[i] = CMathTools::tanhApproximation(left[i]);
00369 right[i] = CMathTools::tanhApproximation(right[i]);
00370 }
00371 }
00372
00379 FORCEINLINE static double computeRMS(const double *buffer, const long numberOfSamplesToProcess)
00380 {
00381
00382 double mean1 = 0.0, mean2 = 0.0, mean3 = 0.0, mean4 = 0.0;
00383 for (long i = 0; i < numberOfSamplesToProcess - 4; i+=4)
00384 {
00385 mean1 += buffer[i] * buffer[i];
00386 mean2 += buffer[i + 1] * buffer[i + 1];
00387 mean3 += buffer[i + 2] * buffer[i + 2];
00388 mean4 += buffer[i + 3] * buffer[i + 3];
00389 }
00390
00391
00392
00393
00394 return sqrt((mean1 + mean2 + mean3 + mean4) / numberOfSamplesToProcess);
00395
00396
00397
00398
00399
00400
00401 }
00402
00409 FORCEINLINE static double computeRMS(const float *buffer, const long numberOfSamplesToProcess)
00410 {
00411
00412 double mean = 0.0;
00413 for (long i = 0; i < numberOfSamplesToProcess; i++)
00414 {
00415 mean += (double)(buffer[i] * buffer[i]);
00416 }
00417
00418
00419 mean /= numberOfSamplesToProcess;
00420
00421
00422 return sqrt(mean);
00423 }
00424
00425
00426
00427 protected:
00428
00429
00430
00431 double **m_waveData;
00432 long m_bufferSize;
00433 };
00434 }
00435 }
00436
00437 #endif // End of CAudioBuffer.hpp