00001 #include "AudioUtil.h"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 AudioUtil::AudioUtil()
00016 {
00017 this->sfinfo = new SF_INFO;
00018 this->fileHandlingMode = DISK_MODE;
00019 sndFileNotEmpty = false;
00020 }
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 AudioUtil::AudioUtil(string filePath)
00031 {
00032 this->sfinfo = new SF_INFO;
00033 this->fileHandlingMode = DISK_MODE;
00034 sndFileNotEmpty = false;
00035 this->setFile(filePath);
00036 }
00037
00038
00039
00040
00041
00042 AudioUtil::~AudioUtil()
00043 {
00044 if(sndFileNotEmpty == true)
00045 {
00046 sf_close(this->sndFile);
00047 }
00048 delete sfinfo;
00049 }
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 void AudioUtil::setFileHandlingMode(FileHandlingMode mode)
00069 {
00070 this->fileHandlingMode = mode;
00071 if(mode == FULL_CACHE)
00072 {
00073 this->fileCache.clear();
00074 this->populateCache();
00075 }
00076 }
00077
00078
00079
00080
00081
00082 AudioUtil::FileHandlingMode AudioUtil::getFileHandlingMode()
00083 {
00084 return this->fileHandlingMode;
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 bool AudioUtil::setFile(string filePath)
00099 {
00100
00101 if(sndFileNotEmpty == true)
00102 {
00103 sf_close(this->sndFile);
00104 }
00105 this->sfinfo->format=0;
00106 if (! (this->sndFile = sf_open (filePath.c_str(), SFM_READ, this->sfinfo)))
00107 {
00108
00109 fprintf (stderr, "failed to open input file \"%s\".\n", filePath.c_str()) ;
00110
00111 sf_perror (NULL) ;
00112 return false;
00113 };
00114
00115
00116 sf_command (this->sndFile, SFC_SET_NORM_DOUBLE, NULL, SF_TRUE) ;
00117
00118
00119 if (this->sfinfo->channels > MAX_CHANNELS)
00120 {
00121 fprintf (stderr, "Error. Input has too many channels. Maximum channels: %d channels\n", MAX_CHANNELS) ;
00122 return false;
00123 };
00124
00125 if(this->fileHandlingMode == FULL_CACHE)
00126 {
00127 this->fileCache.clear();
00128 this->fileCache = this->getAllFrames();
00129 }
00130
00131 this->sndFileNotEmpty = true;
00132 return true;
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142 vector<double> AudioUtil::calculateNormalizedPeaks()
00143 {
00144 this->peaks.clear();
00145
00146 double *peaksPtr = (double *) malloc(2*sizeof(double));
00147
00148 sf_command (sndFile, SFC_CALC_NORM_MAX_ALL_CHANNELS, peaksPtr, sizeof(double)*this->getNumChannels()) ;
00149
00150 if(this->getNumChannels() == 2)
00151 {
00152 this->peaks.push_back(peaksPtr[0]);
00153 this->peaks.push_back((peaksPtr[1]));
00154 }
00155 else if (this->getNumChannels() == 1)
00156 {
00157 this->peaks.push_back(peaksPtr[0]);
00158 } else
00159 {
00160 perror("Error in AudioUtil::calculateNormalizedPeaks()\n");
00161 }
00162
00163 free(peaksPtr);
00164
00165 return peaks;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174 int AudioUtil::getNumChannels()
00175 {
00176 if (sfinfo != NULL)
00177 {
00178 return this->sfinfo->channels;
00179 }
00180 else
00181 {
00182 return NULL;
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191 int AudioUtil::getSampleRate()
00192 {
00193 return this->sfinfo->samplerate;
00194 }
00195
00196
00197
00198
00199
00200
00201 int AudioUtil::getTotalFrames()
00202 {
00203 if (sfinfo != NULL)
00204 {
00205 return this->sfinfo->frames;
00206 }
00207 else
00208 {
00209 return NULL;
00210 }
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 vector<double> AudioUtil::grabFrame(int frameIndex)
00228 {
00229 vector<double> frameData;
00230
00231 if(this->fileHandlingMode == FULL_CACHE)
00232 {
00233 if(this->getNumChannels() == 1)
00234 {
00235 if(frameIndex >= (int) this->fileCache.size())
00236 {
00237 perror("err in AudioUtil::grabFrame -- caller attempting to access out-of-range frame\n");
00238 return frameData;
00239 }
00240
00241 else
00242 {
00243 frameData.push_back(this->fileCache.at(frameIndex));
00244 }
00245 }
00246
00247 if(this->getNumChannels() == 2)
00248 {
00249 if(2*frameIndex+1 >= (int) this->fileCache.size())
00250 {
00251 perror("err in AudioUtil::grabFrame -- caller attempting to access out-of-range frame\n");
00252 return frameData;
00253 }
00254 else
00255 {
00256 frameData.push_back(this->fileCache.at(2*frameIndex));
00257 frameData.push_back(this->fileCache.at(2*frameIndex+1));
00258 }
00259
00260 }
00261
00262 }
00263
00264 if(this->fileHandlingMode == DISK_MODE)
00265 {
00266 if (sf_seek(sndFile, frameIndex, SEEK_SET) == -1)
00267 {
00268 perror("seek error in AudioUtil::grabFrame\n");
00269 return frameData;
00270 }
00271 else
00272 {
00273 if(sf_readf_double(sndFile, data, 1) == 0)
00274 {
00275 perror("file read error in AudioUtil::grabFrame\n");
00276 return frameData;
00277
00278 }
00279 else
00280 {
00281 if(this->getNumChannels() == 2)
00282 {
00283 frameData.push_back(data[0]);
00284 frameData.push_back(data[1]);
00285 return frameData;
00286 }
00287 if(this->getNumChannels() == 1)
00288 {
00289 frameData.push_back(data[0]);
00290 return frameData;
00291 }
00292 }
00293 }
00294 }
00295
00296 perror("invalid mode selected for AudioUtil instance\n");
00297 return frameData;
00298
00299
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 vector<double> AudioUtil::peakForRegion(int region_start_frame, int region_end_frame)
00318 {
00319
00320 int numChannels = this->getNumChannels();
00321
00322 if(this->fileHandlingMode == FULL_CACHE)
00323 {
00324 if(numChannels == 2)
00325 {
00326 this->regionPeak.clear();
00327
00328 double max0 = 0.0;
00329 double max1 = 0.0;
00330
00331 for (int i = 2*region_start_frame; i < 2*region_end_frame; i+=2)
00332 {
00333 if(fabs(fileCache[i]) > fabs(max0))
00334 {
00335 max0 = fileCache[i];
00336 }
00337 if(fabs(fileCache[i+1]) > fabs(max1))
00338 {
00339 max1 = fileCache[i+1];
00340 }
00341
00342 }
00343
00344 this->regionPeak.push_back(max0);
00345 this->regionPeak.push_back(max1);
00346
00347 return regionPeak;
00348 }
00349
00350 if(numChannels == 1)
00351 {
00352 this->regionPeak.clear();
00353
00354 double max0 = 0.0;
00355
00356 for (int i = region_start_frame; i < region_end_frame; i++)
00357 {
00358 if(fabs(fileCache[i]) > fabs(max0))
00359 {
00360 max0 = fileCache[i];
00361 }
00362 }
00363
00364 this->regionPeak.push_back(max0);
00365
00366 return this->regionPeak;
00367 }
00368
00369 }
00370 if(this->fileHandlingMode == DISK_MODE)
00371 {
00372 if(numChannels == 2)
00373 {
00374 this->regionPeak.clear();
00375 double *chunk = new double[ 2*(region_end_frame - region_start_frame)];
00376
00377 if (sf_seek(sndFile, region_start_frame, SEEK_SET) == -1)
00378 {
00379 perror("seek error in AudioUtil::peakForRegion function\n");
00380 return this->regionPeak;
00381 }
00382
00383 if(sf_readf_double(sndFile, chunk, (region_end_frame - region_start_frame) ) == 0)
00384 {
00385 perror("read error in AudioUtil::peakForRegion function\n");
00386 return this->regionPeak;
00387 }
00388
00389 double max0 = 0.0;
00390 double max1 = 0.0;
00391
00392 for (int i = 0; i < 2*(region_end_frame - region_start_frame); i+=2)
00393 {
00394 if(fabs(chunk[i]) > fabs(max0))
00395 {
00396 max0 = chunk[i];
00397 }
00398 if(fabs(chunk[i+1]) > fabs(max1))
00399 {
00400 max1 = (chunk[i+1]);
00401 }
00402
00403 }
00404
00405 this->regionPeak.push_back(max0);
00406 this->regionPeak.push_back(max1);
00407
00408 delete[] chunk;
00409
00410 return regionPeak;
00411 }
00412
00413
00414 if(numChannels == 1)
00415 {
00416 this->regionPeak.clear();
00417 double *chunk = new double[ region_end_frame - region_start_frame];
00418
00419 if (sf_seek(sndFile, region_start_frame, SEEK_SET) == -1)
00420 {
00421 perror("seek error in AudioUtil::peakForRegion function\n");
00422 return this->regionPeak;
00423 }
00424
00425 if(sf_readf_double(sndFile, chunk, (region_end_frame - region_start_frame) ) == 0)
00426 {
00427 perror("read error in AudioUtil::peakForRegion function\n");
00428 return this->regionPeak;
00429 }
00430
00431 double max0 = 0.0;
00432
00433 for (int i = 0; i < region_end_frame - region_start_frame; i++)
00434 {
00435 if(fabs(chunk[i]) > max0)
00436 {
00437 max0 = fabs(chunk[i]);
00438 }
00439 }
00440
00441 this->regionPeak.push_back(max0);
00442
00443 delete[] chunk;
00444
00445 return this->regionPeak;
00446 }
00447 }
00448 perror("err in AudioUtil::peakForRegion function. Max channels: 2\n");
00449 return this->regionPeak;
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 vector<double> AudioUtil::getAllFrames()
00463 {
00464
00465 if(this->fileHandlingMode == FULL_CACHE)
00466 {
00467 return this->fileCache;
00468 }
00469 else
00470 {
00471 this->dataVector.clear();
00472 int readSize = 1024;
00473
00474
00475 if (sf_seek(sndFile, 0, SEEK_SET) == -1)
00476 {
00477 fprintf(stderr, "seek failed in AudioUtil::getAllFrames() function\n");
00478 }
00479 double *chunk = new double[readSize];
00480 int itemsRead = sf_read_double(this->sndFile, chunk, readSize);
00481
00482 while(itemsRead == readSize)
00483 {
00484
00485 for(int i = 0; i < readSize; i++)
00486 {
00487 this->dataVector.push_back(chunk[i]);
00488 }
00489
00490 itemsRead = sf_read_double(this->sndFile, chunk, readSize);
00491 }
00492
00493
00494 for(int i = 0; i < itemsRead; i++)
00495 {
00496 this->dataVector.push_back(chunk[i]);
00497 }
00498
00499 delete[] chunk;
00500
00501 return this->dataVector;
00502 }
00503 }
00504
00505
00506
00507
00508
00509
00510 void AudioUtil::populateCache()
00511 {
00512 this->fileCache.clear();
00513 int readSize = 1024;
00514
00515
00516 if (sf_seek(sndFile, 0, SEEK_SET) == -1)
00517 {
00518 fprintf(stderr, "seek failed in AudioUtil::getAllFrames() function\n");
00519 }
00520
00521 double *chunk = new double[readSize];
00522 int itemsRead = sf_read_double(this->sndFile, chunk, readSize);
00523
00524 while(itemsRead == readSize)
00525 {
00526
00527 for(int i = 0; i < readSize; i++)
00528 {
00529 this->fileCache.push_back(chunk[i]);
00530 }
00531
00532 itemsRead = sf_read_double(this->sndFile, chunk, readSize);
00533 }
00534
00535
00536 for(int i = 0; i < itemsRead; i++)
00537 {
00538 this->fileCache.push_back(chunk[i]);
00539 }
00540
00541 delete[] chunk;
00542
00543 }