15 const char *
gSndFileExts[] = {
"mp3",
"wav",
"aiff",
"aif",
"mp4",
"m4p",
"m4b",
"m4a",
"aac",
"flac", 0 };
20 const char * dot = strrchr(path,
'.');
36 const char * lastDot = strrchr(path,
'.');
42 if (strcasestr(lastDot,
"wav"))
44 if (strcasestr(lastDot,
"mp3"))
45 return kSoundFileFormatMP3;
46 if (strcasestr(lastDot,
"aif"))
48 if (strcasestr(lastDot,
"aiff"))
50 if (strcasestr(lastDot,
"m4a"))
51 return kSoundFileFormatMP4;
52 if (strcasestr(lastDot,
"mp4"))
53 return kSoundFileFormatMP4;
54 if (strcasestr(lastDot,
"m4b"))
55 return kSoundFileFormatMP4;
56 if (strcasestr(lastDot,
"aac"))
57 return kSoundFileFormatAAC;
58 if (strcasestr(lastDot,
"flac"))
59 return kSoundFileFormatFLAC;
60 if (strcasestr(lastDot,
"caf"))
61 return kSoundFileFormatCAF;
62 if (strcasestr(lastDot,
"ogg"))
63 return kSoundFileFormatOGG;
64 if (strcasestr(lastDot,
"shn"))
65 return kSoundFileFormatSHN;
66 if (strcasestr(lastDot,
"snd"))
77 case kSoundFileFormatMP3:
return "audio/mpeg";
78 case kSoundFileFormatMP4:
return "audio/mp4a-latm";
80 default:
return "audio/basic";
87 const char * fname = tpath.c_str();
89 if (strcasestr(fname,
".mp3")) {
90 return new MP3File(tpath, tstart, tstop);
94 if ((strcasestr(fname,
".mp4")) || (strcasestr(fname,
".m4a"))
95 || (strcasestr(fname,
".m4p")) || (strcasestr(fname,
".aac"))) {
96 return new MP4File(tpath, tstart, tstop);
99 return new LSoundFile(tpath, tstart, tstop, doRead);
103 const char * fname = tpath.c_str();
105 if (strcasestr(fname,
".mp3")) {
106 return new MP3File(maxDurInSecs, tpath);
110 if ((strcasestr(fname,
".mp4")) || (strcasestr(fname,
".m4a"))
111 || (strcasestr(fname,
".m4p")) || (strcasestr(fname,
".aac"))) {
112 return new MP4File(maxDurInSecs, tpath);
123 mSFInfo(new SF_INFO),
125 mMaxDurInSecs (maxDurInSecs) {
128 #ifdef CSL_USE_SRConv
146 mSFInfo(new SF_INFO),
148 mMaxDurInSecs (maxDurInSecs) {
151 #ifdef CSL_USE_SRConv
165 mSFInfo(otherSndFile.sfInfo()),
166 mSndfile(otherSndFile.sndFile()) {
170 #ifdef CSL_USE_SRConv
182 #ifdef CSL_USE_SRConv
184 src_delete (mSRateConv);
204 switch (
mSFInfo->format & 0x0f) {
217 #ifdef CSL_USE_SRConv
219 mSRateConv = src_new (CSL_SRC_MODE,
mNumChannels, & mSRCReturn);
220 if (mSRateConv == NULL)
221 logMsg (
kLogError,
"SampleRateConvertor creation error : %s\n", src_strerror (mSRCReturn));
259 logMsg(
"Error: Couldn't get the file format.");
270 mSndfile = sf_open(mPath.c_str(), SFM_READ, mSFInfo);
271 if (mSndfile != NULL) {
272 this->initFromSndfile();
276 this->readBufferFromFile(mNumFrames);
289 unsigned rate,
unsigned bitDepth)
throw (
CException) {
293 mSFInfo->samplerate = rate;
294 mSFInfo->channels = tchannels;
297 mSFInfo->format = SF_FORMAT_WAV;
break;
299 mSFInfo->format = SF_FORMAT_AIFF;
break;
301 mSFInfo->format = SF_FORMAT_AU;
break;
304 mSFInfo->format = SF_FORMAT_RAW;
break;
307 mSFInfo->format = mSFInfo->format | SF_FORMAT_PCM_16;
308 else if (bitDepth == 32)
309 mSFInfo->format = mSFInfo->format | SF_FORMAT_FLOAT;
311 logMsg(
"Invalid bitDepth for sound file %s. Use either 16 or 32 bits.", mPath.c_str());
313 if ( ! sf_format_check(mSFInfo)) {
318 mSndfile = sf_open(mPath.c_str(), SFM_WRITE, mSFInfo);
338 if (this->isCached())
339 return mCurrentFrame;
345 whenceInt = SEEK_CUR;
346 logMsg(
"Error: Invalid position seek flag. Used kPositionCurrent.");
349 mCurrentFrame = sf_seek(mSndfile, position, whenceInt);
350 mBase = mCurrentFrame;
351 return mCurrentFrame;
357 unsigned numFrames = outputBuffer.mNumFrames;
358 unsigned currentFrame = mCurrentFrame;
362 if (currentFrame >= (
unsigned) mStop) {
363 outputBuffer.zeroBuffers();
366 if (currentFrame + numFrames >= (
unsigned) mStop) {
367 numFrames = mStop - currentFrame;
368 outputBuffer.zeroBuffers();
371 if ( ! this->isCached(numFrames)) {
373 this->readBufferFromFile(numFrames);
378 unsigned numBytes = numFrames *
sizeof(
sample);
379 for (
unsigned i = 0; i < outputBuffer.mNumChannels; i++) {
380 SampleBuffer dataOutPtr = mWavetable.monoBuffer(
csl_min(i, (mNumChannels - 1))) + currentFrame;
381 memcpy(outputBuffer.monoBuffer(i), dataOutPtr, numBytes);
385 for (
unsigned i = 0; i < outputBuffer.mNumChannels; i++) {
389 for (
unsigned i = 0; i < numFrames; i++) {
390 samp = (*dPtr++ * scaleValue) + offsetValue;
394 scalePort->resetPtr();
395 offsetPort->resetPtr();
398 currentFrame += numFrames;
401 #ifndef CSL_USE_SRConv // normal case: use wavetable interpolation
402 for (
unsigned i = 0; i < mNumChannels; i++)
404 currentFrame += numFrames;
406 #else // else use Sample rate convertor
408 if (this->isCached())
409 mSRateData.data_in = mWavetable.monoBuffer(0) + (currentFrame * mNumChannels);
411 mSRateData.data_in = mWavetable.monoBuffer(0);
412 mSRateData.data_out = mSRateData.data_in;
413 mSRateData.input_frames = numFrames;
414 mSRateData.output_frames = numFrames;
415 mSRateData.data_out = mSRConvBuffer.monoBuffer(0);
416 mSRateData.end_of_input = 0;
417 mSRateData.src_ratio = mRate;
418 if (answer = src_set_ratio (mSRateConv, mRate))
420 src_strerror (answer));
422 if (answer = src_process (mSRateConv, & mSRateData))
424 src_strerror (answer));
426 mSRateData.data_out = mSRConvBuffer.monoBuffer(0);
427 currentFrame += mSRateData.input_frames_used;
428 numFrames = mSRateData.output_frames_gen;
431 if ((currentFrame >= (
unsigned) mStop) && mIsLooping)
433 mCurrentFrame = currentFrame;
440 unsigned numFrames = inputBuffer.mNumFrames;
441 if (mSFInfo->channels > 1) {
442 mWavetable.setSize(1, mNumChannels * numFrames);
443 mWavetable.allocateBuffers();
445 mInterleaver.interleave(inputBuffer, mWavetable.monoBuffer(0),
446 numFrames, mSFInfo->channels);
447 sf_writef_float(mSndfile, mWavetable.monoBuffer(0), numFrames);
449 sf_writef_float(mSndfile, inputBuffer.monoBuffer(0), numFrames);
451 mCurrentFrame += numFrames;
458 sf_count_t numFramesRead;
460 unsigned myChannels =
mSFInfo->channels;
464 if ((myChannels > 1)) {
471 memset(sampleBufferPtr, 0, numFrames * myChannels *
sizeof(
sample));
476 numFramesRead = sf_readf_float(
mSndfile, sampleBufferPtr, numFrames);
477 if ((
unsigned) numFramesRead != numFrames)
478 logMsg(
kLogError,
"LSoundFile::readBufferFromFile sf_readf_float requested %d got %d",
479 numFrames, numFramesRead);
483 if ((
mBase + numFrames) > (
unsigned) mStop) {
484 unsigned numFramesRemaining = numFrames - numFramesRead;
485 SampleBuffer tempBufferPtr = sampleBufferPtr + (numFramesRead * myChannels);
487 while ((
unsigned) numFramesRead < numFrames) {
488 currentFrame = sf_seek(
mSndfile, 0, SEEK_SET);
489 numFramesRead += sf_readf_float(
mSndfile, tempBufferPtr, numFramesRemaining);
490 currentFrame += numFramesRead;
493 unsigned bytesToClear = numFramesRemaining * myChannels *
sizeof(
sample);
494 memset(tempBufferPtr, 0, bytesToClear);
497 if (myChannels > 1) {
504 #ifdef CSL_USE_SRConv // sample-rate conversion
506 #define BUFFER_LEN 4096
510 static sf_count_t sample_rate_convert (SNDFILE *infile, SNDFILE *outfile,
511 int converter,
double src_ratio,
int channels,
double * gain);
513 static double apply_gain (
float *
data,
long frames,
int channels,
double max,
double gain);