CSL  6.0
SoundFileL.cpp
Go to the documentation of this file.
1 //
2 // SoundFileL.cpp -- sound file class using libsndfile
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5 
6 #include "SoundFileL.h"
7 #include "math.h"
8 #include "SoundFileMP3.h"
9 
10 using namespace csl;
11 
12 #ifdef CSL_WINDOWS
13 #define strcasestr strstr
14 #endif
15 
16 // Factory method
17 
18 LSoundFile * LSoundFile::openSndfile(string tpath, int tstart, int tstop, bool doRead) {
19  const char * fname = tpath.c_str();
20 #ifdef USE_libMAD
21  if (strcasestr(fname, ".mp3")) { // if an MP3
22  return new MP3File(tpath, tstart, tstop);
23  } // if an MP4/AAC
24 #endif
25 #ifdef USE_libFAAD
26  if ((strcasestr(fname, ".mp4")) || (strcasestr(fname, ".m4a"))
27  || (strcasestr(fname, ".m4p")) || (strcasestr(fname, ".aac"))) {
28  return new MP4File(tpath, tstart, tstop);
29  }
30 #endif
31  return new LSoundFile(tpath, tstart, tstop, doRead); // else try LibSndfile
32 }
33 
34 LSoundFile * LSoundFile::openSndfile(float maxDurInSecs, string tpath) {
35  const char * fname = tpath.c_str();
36 #ifdef USE_libMAD
37  if (strcasestr(fname, ".mp3")) { // if an MP3
38  return new MP3File(maxDurInSecs, tpath);
39  } // if an MP4/AAC
40 #endif
41 #ifdef USE_libFAAD
42  if ((strcasestr(fname, ".mp4")) || (strcasestr(fname, ".m4a"))
43  || (strcasestr(fname, ".m4p")) || (strcasestr(fname, ".aac"))) {
44  return new MP4File(maxDurInSecs, tpath);
45  }
46 #endif
47  return new LSoundFile(maxDurInSecs, tpath); // else try LibSndfile
48 }
49 
50 
51 // LSoundFile Constructors
52 
53 LSoundFile::LSoundFile(string tpath, int tstart, int tstop, bool doRead, float maxDurInSecs)
54  : Abst_SoundFile(tpath, tstart, tstop),
55  mSFInfo(new SF_INFO),
56  mSndfile(NULL),
57  mMaxDurInSecs (maxDurInSecs) {
58  mSFInfo->format = 0;
59  mNumFrames = 0;
60 #ifdef CSL_USE_SRConv
61  mSRateConv = NULL;
62 #endif
63  if ( ! doRead)
64  return;
65  try {
66  openForRead(); // read and cache whole file
67  setToEnd();
68  } catch (CException & e) {
69 // logMsg(kLogError, "File open exception caught: %s", e.mMessage.c_str());
70  return;
71  }
72 }
73 
74 // this version sets maxSize and always reads
75 
76 LSoundFile::LSoundFile(float maxDurInSecs, string tpath)
77  : Abst_SoundFile(tpath, -1, -1),
78  mSFInfo(new SF_INFO),
79  mSndfile(NULL),
80  mMaxDurInSecs (maxDurInSecs) {
81  mSFInfo->format = 0;
82  mNumFrames = 0;
83 #ifdef CSL_USE_SRConv
84  mSRateConv = NULL;
85 #endif
86  try {
87  openForRead(); // read and cache whole file
88  setToEnd();
89  } catch (CException & e) {
90  }
91 }
92 
93 // Copy constructor -- shares sample buffer
94 
96  : Abst_SoundFile(otherSndFile),
97  mSFInfo(otherSndFile.sfInfo()),
98  mSndfile(otherSndFile.sndFile()) {
99  if ( ! otherSndFile.isCached())
100  logMsg(kLogError, "Cannot copy uncached sound file \"%s\"", mPath.c_str());
101 // logMsg("Open sound file \"%s\"", mPath.c_str());
102 #ifdef CSL_USE_SRConv
103  mSRateConv = NULL;
104 #endif
105 }
106 
107 // Clean up data allocated
108 
110  if (mSndfile)
111  sf_close(mSndfile);
112  freeBuffer();
113  delete mSFInfo;
114 #ifdef CSL_USE_SRConv
115  if (mSRateConv)
116  src_delete (mSRateConv);
117 #endif
118 }
119 
120 //
121 // set up the receiver's variables based on the file
122 //
123 
125  mIsValid = (mSndfile != NULL);
126  if ( ! mIsValid) {
127 // logMsg(kLogError, "Cannot open sound file \"%s\"", mPath.c_str());
128  return;
129  }
130  mFrameRate = (unsigned) mSFInfo->samplerate;
131  mNumChannels = (unsigned) mSFInfo->channels;
132  mNumFrames = (unsigned) mSFInfo->frames;
133  if (mMaxDurInSecs > 0.0 && (mNumFrames > (unsigned) (mMaxDurInSecs * mFrameRate))) // truncate if too long
135  mBase = 0;
136  switch (mSFInfo->format & 0x0f) {
137  case 1: mBytesPerSample = 1; break; // Signed 8 bit
138  case 2: mBytesPerSample = 2; break; // Signed 16 bit
139  case 3: mBytesPerSample = 3; break; // Signed 24 bit
140  case 4: mBytesPerSample = 4; break; // Signed 32 bit
141  case 5: mBytesPerSample = 1; break; // unsigned 8 bit
142  case 6: mBytesPerSample = 4; break; // 32 bit float
143  case 7: mBytesPerSample = 8; break; // 64 bit float
144  }
145  if (mStart > 0) seekTo(mStart);
146  else mStart = 0;
147  if (mStop < 0) mStop = mNumFrames;
148 
149 #ifdef CSL_USE_SRConv
150  if (mMode == kSoundFileRead) { // sample rate convertor (SRC) state struct
151  mSRateConv = src_new (CSL_SRC_MODE, mNumChannels, & mSRCReturn);
152  if (mSRateConv == NULL)
153  logMsg (kLogError, "SampleRateConvertor creation error : %s\n", src_strerror (mSRCReturn));
154  }
155 #endif
156 }
157 
158 //void LSoundFile::checkBuffer(unsigned numFrames) {
159 // Abst_SoundFile::checkBuffer(numFrames);
160 //#ifdef CSL_USE_SRConv
161 // if ( ! mSRConvBuffer.mAreBuffersAllocated) { // if no SRC buffer allocated
162 // mSRConvBuffer.setSize(1, CGestalt::maxBufferFrames() * mNumChannels);
163 // mSRConvBuffer.allocateBuffers();
164 // }
165 //#endif
166 //}
167 
168 ///< answer if file has all of its samples in RAM
169 
171  return (mWavetable.mNumFrames == mNumFrames);
172 }
173 
174 ///< answer if file has X samples in RAM
175 
176 bool LSoundFile::isCached(unsigned samps) {
177  return (mWavetable.mNumFrames > (mCurrentFrame + samps));
178 }
179 
181  switch (mSFInfo->format) {
182  case SF_FORMAT_WAV:
183  return kSoundFileFormatWAV; break;
184  case SF_FORMAT_AIFF:
185  return kSoundFileFormatAIFF; break;
186  case SF_FORMAT_AU:
187  return kSoundFileFormatSND; break;
188  case SF_FORMAT_RAW:
189  return kSoundFileFormatRaw; break;
190  default:
191  logMsg("Error: Couldn't get the file format.");
192  }
193  return kSoundFileFormatRaw;
194 }
195 
196 // ~~~~ Open functions ~~~~
197 
198 void LSoundFile::openForRead(bool load) throw (CException) {
199  if (mMode == kSoundFileRead)
200  return;
201  mMode = kSoundFileRead;
202  mSndfile = sf_open(mPath.c_str(), SFM_READ, mSFInfo); // libsndfile open call
203  if (mSndfile != NULL) { // check result
204  this->initFromSndfile();
205  if (load && (mNumFrames <= CGestalt::maxSndFileFrames())) { // read file if size < global max
206 // logMsg("Open/read sound file \"%s\" %d frames %g sec %d channels",
207 // mPath.c_str(), duration(), durationInSecs(), channels());
208  this->readBufferFromFile(mNumFrames); // read entire file, de-interleave
209  }
210 // mCurrentFrame = mStart;
211 // this->setWaveform(mSampleBuffer); // set up oscillator pointers
212 // mWavetable.mDidIAllocateBuffers = true;
213 // if (this->isCached())
214 // logMsg("\t\tSound file cached");
215  }
216  if (mIsValid)
217  this->readTags();
218 }
219 
220 void LSoundFile::openForWrite(SoundFileFormat tformat, unsigned tchannels,
221  unsigned rate, unsigned bitDepth) throw (CException) {
222  if (mMode == kSoundFileWrite)
223  return;
224  mMode = kSoundFileWrite;
225  mSFInfo->samplerate = rate;
226  mSFInfo->channels = tchannels;
227  switch (tformat) {
228  case kSoundFileFormatWAV:
229  mSFInfo->format = SF_FORMAT_WAV; break;
231  mSFInfo->format = SF_FORMAT_AIFF; break;
232  case kSoundFileFormatSND:
233  mSFInfo->format = SF_FORMAT_AU; break;
234  case kSoundFileFormatRaw:
235  default:
236  mSFInfo->format = SF_FORMAT_RAW; break;
237  }
238  if (bitDepth == 16)
239  mSFInfo->format = mSFInfo->format | SF_FORMAT_PCM_16;
240  else if (bitDepth == 32)
241  mSFInfo->format = mSFInfo->format | SF_FORMAT_FLOAT;
242  else
243  logMsg("Invalid bitDepth for sound file %s. Use either 16 or 32 bits.", mPath.c_str());
244 
245  if ( ! sf_format_check(mSFInfo)) {
246  logMsg(kLogError, "Invalid format for sound file %s", mPath.c_str());
247  mIsValid = false;
248  return;
249  }
250  mSndfile = sf_open(mPath.c_str(), SFM_WRITE, mSFInfo);
251  initFromSndfile();
252 }
253 
256  mSndfile = sf_open(mPath.c_str(), SFM_RDWR, mSFInfo);
257  initFromSndfile();
258 }
259 
261  sf_close(mSndfile);
262  mSndfile = NULL;
263  freeBuffer();
264 }
265 
266 // file seek via sf_seek call
267 
268 unsigned LSoundFile::seekTo(int position, SeekPosition whence) throw(CException) {
269  int whenceInt;
270  if (this->isCached())
271  return mCurrentFrame;
272  switch (whence) {
273  case kPositionStart: whenceInt = SEEK_SET; break;
274  case kPositionCurrent: whenceInt = SEEK_CUR; break;
275  case kPositionEnd: whenceInt = SEEK_END; break;
276  default:
277  whenceInt = SEEK_CUR;
278  logMsg("Error: Invalid position seek flag. Used kPositionCurrent.");
279  break;
280  } // sf_seek call
281  mCurrentFrame = sf_seek(mSndfile, position, whenceInt);
282  mBase = mCurrentFrame;
283  return mCurrentFrame;
284 }
285 
286 ///////////////// next_buffer -- the work is done here //////////
287 
288 void LSoundFile::nextBuffer(Buffer &outputBuffer) throw(CException) {
289  unsigned numFrames = outputBuffer.mNumFrames;
290  unsigned currentFrame = mCurrentFrame;
291  DECLARE_SCALABLE_CONTROLS; // declare the scale/offset buffers and values
292  bool atEnd = false;
293 
294  if (currentFrame >= (unsigned) mStop) { // if done
295  outputBuffer.zeroBuffers();
296  return;
297  }
298  if (currentFrame + numFrames >= (unsigned) mStop) { // if final window
299  numFrames = mStop - currentFrame;
300  outputBuffer.zeroBuffers();
301  atEnd = true;
302  }
303  if ( ! this->isCached(numFrames)) { // if not playing from cache buffer
304  if (! atEnd)
305  this->readBufferFromFile(numFrames); // read from file
306  }
307  LOAD_SCALABLE_CONTROLS; // load the scaleC and offsetC from the constant or dynamic value
308  if (mRate == 1.0) { // if playing at normal rate
309  if (IS_UNSCALED) { // and there's no scale/offset
310  unsigned numBytes = numFrames * sizeof(sample); // buffer copy loop
311  for (unsigned i = 0; i < outputBuffer.mNumChannels; i++) {
312  SampleBuffer dataOutPtr = mWavetable.buffer(csl_min(i, (mNumChannels - 1))) + currentFrame;
313  memcpy(outputBuffer.buffer(i), dataOutPtr, numBytes);
314  }
315  } else { // do full scaled/offset copy
316  sample samp;
317  for (unsigned i = 0; i < outputBuffer.mNumChannels; i++) {
318  SampleBuffer buffer = outputBuffer.buffer(i); // get pointer to the selected output channel
319  SampleBuffer dPtr = mWavetable.buffer(csl_min(i, (mNumChannels - 1))) + currentFrame;
320 
321  for (unsigned i = 0; i < numFrames; i++) { // sample loop
322  samp = (*dPtr++ * scaleValue) + offsetValue; // get and scale the file sample
323  *buffer++ = samp;
324  UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
325  }
326  scalePort->resetPtr();
327  offsetPort->resetPtr();
328  }
329  }
330  currentFrame += numFrames; // incrememnt buf ptr
331  } else { // if mRate != 1.0,
332 
333 #ifndef CSL_USE_SRConv // normal case: use wavetable interpolation
334  for (unsigned i = 0; i < mNumChannels; i++)
335  WavetableOscillator::nextBuffer(outputBuffer, i);
336  currentFrame += numFrames; // incrememnt buf ptr
337 
338 #else // else use Sample rate convertor
339  int answer; // if we're doing SRC transposition
340  if (this->isCached()) // if playing from cache buffer
341  mSRateData.data_in = mWavetable.buffer(0) + (currentFrame * mNumChannels);
342  else
343  mSRateData.data_in = mWavetable.buffer(0);
344  mSRateData.data_out = mSRateData.data_in; // store for later
345  mSRateData.input_frames = numFrames;
346  mSRateData.output_frames = numFrames;
347  mSRateData.data_out = mSRConvBuffer.buffer(0);
348  mSRateData.end_of_input = 0;
349  mSRateData.src_ratio = mRate;
350  if (answer = src_set_ratio (mSRateConv, mRate)) // set the transposition ratio
351  logMsg (kLogError, "SampleRateConvertor configuration error : %s\n",
352  src_strerror (answer));
353 
354  if (answer = src_process (mSRateConv, & mSRateData)) // run SampleRateConvertor
355  logMsg (kLogError, "SampleRateConvertor runtime error : %s\n",
356  src_strerror (answer));
357 
358  mSRateData.data_out = mSRConvBuffer.buffer(0); // reset out ptr
359  currentFrame += mSRateData.input_frames_used; // input frames actually read
360  numFrames = mSRateData.output_frames_gen; // output frames actually written
361 #endif
362  }
363  if ((currentFrame >= (unsigned) mStop) && mIsLooping) // if we are past the end of the file...
364  currentFrame = 0; // this will click, have to call nextBuffer() recursively here
365  mCurrentFrame = currentFrame; // store back to member
366  return;
367 }
368 
369 // write a CSL buffer to the interleaved output file
370 
371 void LSoundFile::writeBuffer(Buffer &inputBuffer) throw(CException) {
372  unsigned numFrames = inputBuffer.mNumFrames;
373  if (mSFInfo->channels > 1) { // interleave stereo-to-mono
374  mWavetable.setSize(1, mNumChannels * numFrames);
375  mWavetable.allocateBuffers();
376  // call interleaver
377  mInterleaver.interleave(inputBuffer, mWavetable.buffer(0),
378  numFrames, mSFInfo->channels);
379  sf_writef_float(mSndfile, mWavetable.buffer(0), numFrames); // libsndfile write
380  } else { // mono file write
381  sf_writef_float(mSndfile, inputBuffer.buffer(0), numFrames); // libsndfile write
382  }
383  mCurrentFrame += numFrames;
384  return;
385 }
386 
387 void LSoundFile::writeBuffer(Buffer &inputBuffer, unsigned fromFrame, unsigned toFrame) throw (CException) {
388  unsigned maxFrames = inputBuffer.mNumFrames;
389  if (maxFrames > toFrame)
390  maxFrames = toFrame;
391  unsigned numFrames = maxFrames - fromFrame;
392  if (mSFInfo->channels > 1) { // interleave stereo-to-mono
393  mWavetable.setSize(1, mNumChannels * numFrames);
394  mWavetable.allocateBuffers();
395  // call interleaver
396  mInterleaver.interleave(inputBuffer, mWavetable.buffer(0) + fromFrame,
397  numFrames, mSFInfo->channels);
398  sf_writef_float(mSndfile, mWavetable.buffer(0), numFrames); // libsndfile write
399  } else { // mono file write
400  sf_writef_float(mSndfile, inputBuffer.buffer(0) + fromFrame, numFrames); // libsndfile write
401  }
402  mCurrentFrame += numFrames;
403  return;
404 }
405 
406 // readBufferFromFile - read some samples from the file into the temp buffer
407 
408 void LSoundFile::readBufferFromFile(unsigned numFrames) {
409  sf_count_t numFramesRead;
410  unsigned currentFrame = mCurrentFrame;
411  unsigned myChannels = mSFInfo->channels;
412 
413  this->checkBuffer(numFrames); // check my buffer, allocate if necessary
414  SampleBuffer sampleBufferPtr;
415  if ((myChannels > 1)) { // read into temp buffer to multichannel files, then de-interleave
416  SAFE_MALLOC(sampleBufferPtr, sample, (myChannels * numFrames));
417  } else {
418  sampleBufferPtr = mWavetable.buffer(0);
419  }
420  // if we are at the end of the file and not looping
421  if ((currentFrame >= (unsigned) mStop) && !mIsLooping) {
422  memset(sampleBufferPtr, 0, numFrames * myChannels * sizeof(sample));
423  return;
424  }
425  mBase = sf_seek(mSndfile, 0, SEEK_CUR); // get position
426  // libsndfile read function
427  numFramesRead = sf_readf_float(mSndfile, sampleBufferPtr, numFrames);
428  if ((unsigned) numFramesRead != numFrames)
429  logMsg(kLogError, "LSoundFile::readBufferFromFile sf_readf_float requested %d got %d",
430  numFrames, numFramesRead);
431 // mWavetable.mNumFrames = numFrames;
432  mCurrentFrame = 0;
433  // if we are past the end of the file...
434  if ((mBase + numFrames) > (unsigned) mStop) {
435  unsigned numFramesRemaining = numFrames - numFramesRead;
436  SampleBuffer tempBufferPtr = sampleBufferPtr + (numFramesRead * myChannels);
437  if (mIsLooping) { // loop back to start of file
438  while ((unsigned) numFramesRead < numFrames) {
439  currentFrame = sf_seek(mSndfile, 0, SEEK_SET); // libsndfile seek/read function
440  numFramesRead += sf_readf_float(mSndfile, tempBufferPtr, numFramesRemaining);
441  currentFrame += numFramesRead;
442  }
443  } else {
444  unsigned bytesToClear = numFramesRemaining * myChannels * sizeof(sample);
445  memset(tempBufferPtr, 0, bytesToClear);
446  }
447  }
448  if (myChannels > 1) { // auto-de-interleave if multichannel
449  mInterleaver.deinterleave(mWavetable, sampleBufferPtr, numFrames, mNumChannels);
450  SAFE_FREE(sampleBufferPtr);
451  }
453 }
454 
455 #ifdef CSL_USE_SRConv // sample-rate conversion
456 
457 #define BUFFER_LEN 4096 /*-(1<<16)-*/
458 
459 // fcn prototypes below
460 
461 static sf_count_t sample_rate_convert (SNDFILE *infile, SNDFILE *outfile,
462  int converter, double src_ratio, int channels, double * gain);
463 
464 static double apply_gain (float * data, long frames, int channels, double max, double gain);
465 
466 #endif // SR_Conv
467 
468 //-------------------------------------------------------------------------------
469 
470 // SF_Virtual structure
471 /*
472 typedef sf_count_t (*sf_vio_get_filelen) (void *user_data) ;
473 typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data) ;
474 typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data) ;
475 typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data) ;
476 typedef sf_count_t (*sf_vio_tell) (void *user_data) ;
477 
478 struct SF_VIRTUAL_IO
479 { sf_vio_get_filelen get_filelen ;
480  sf_vio_seek seek ;
481  sf_vio_read read ;
482  sf_vio_write write ;
483  sf_vio_tell tell ;
484 } ;
485 */
486 
487 // Call-back functions for SF_VIRTUAL_IO struct
488 
489 //sf_vio_get_filelen lsf_getFileLen(void * vBuffer) {
490 // Buffer * buf = (Buffer *) vfile
491 //}
492 //
493 //sf_vio_seek lsf_seek(sf_count_t offset, int whence, void * vBuffer) {
494 //
495 //}
496 //
497 //sf_vio_tell lsf_tell(void * vBuffer) {
498 //
499 //}
500 //
501 //
502 //sf_vio_read lsf_read(void *ptr, sf_count_t count, void * vBuffer) {
503 //
504 //}
505 //
506 //
507 //sf_vio_write lsf_write(const void *ptr, sf_count_t count, void * vBuffer) {
508 //
509 //}
510 
511 
512 
513 // OLD WAY
514 
515 //void LSoundFile::convertRate(char * mTempPath, int fromRate, int toRate) {
516 // SNDFILE *infile, *outfile;
517 // SF_INFO sfinfo;
518 // sf_count_t count;
519 // char tempName[CSL_NAME_LEN];
520 //
521 // double src_ratio = -1.0, gain = 1.0;
522 // int converter;
523 // converter = SRC_SINC_BEST_QUALITY;
524 // logMsg("Convert-rate of \"%s\" from %d to %d", mTempPath, fromRate, toRate);
525 // // create temp name and rename file
526 // sprintf(tempName, "%s.TEMP", mTempPath);
527 // if (rename(mTempPath, tempName) != 0) {
528 // logMsg(kLogError, "Convert-rate cannot rename \"%s\" to \"%s\"", mTempPath, tempName);
529 // perror("SoundFile::convertRate");
530 // return;
531 // }
532 // infile = sf_open(tempName, SFM_READ, &sfinfo);
533 // src_ratio = (double) toRate / (double) fromRate;
534 // sfinfo.samplerate = toRate;
535 // if (src_is_valid_ratio (src_ratio) == 0) {
536 // logMsg (kLogError, "Error: Sample rate change out of valid range.");
537 // sf_close (infile);
538 // return;
539 // }
540 // outfile = sf_open (mTempPath, SFM_WRITE, &sfinfo);
541 // if (outfile == NULL) {
542 // logMsg (kLogError, "Error: Cannot open output file.");
543 // sf_close (infile);
544 // return;
545 // }
546 // sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE);
547 // sf_command (outfile, SFC_SET_CLIPPING, NULL, SF_TRUE);
548 // do {
549 // count = sample_rate_convert(infile, outfile, converter, src_ratio, sfinfo.channels, &gain);
550 // } while (count < 0);
551 //
552 // logMsg("Convert-rate: output frames %ld", (long) count);
553 // sf_close(infile);
554 // sf_close(outfile);
555 // if (remove(tempName) != 0)
556 // logMsg(kLogError, "Convert-rate cannot remove temp file \"%s\"\n", tempName);
557 //}
558 
559 /////////////////////////
560 // These 2 functions are taken from libSampleRate
561 //
562 
563 //static sf_count_t sample_rate_convert (SNDFILE *infile, SNDFILE *outfile, int converter,
564 // double src_ratio, int channels, double * gain) {
565 // static float input [BUFFER_LEN];
566 // static float output [BUFFER_LEN];
567 // SRC_STATE * src_state;
568 // SRC_DATA src_data;
569 // int error;
570 // double max = 0.0;
571 // sf_count_t output_count = 0;
572 // sf_seek (infile, 0, SEEK_SET);
573 // sf_seek (outfile, 0, SEEK_SET);
574 //
575 // /* Initialize the sample rate converter. */
576 // if ((src_state = src_new (converter, channels, &error)) == NULL) {
577 // logMsg ("Error : src_new() failed : %s.", src_strerror (error));
578 // exit (1);
579 // };
580 //
581 // src_data.end_of_input = 0; /* Set this later. */
582 //
583 // /* Start with zero to force load in while loop. */
584 // src_data.input_frames = 0;
585 // src_data.data_in = input;
586 // src_data.src_ratio = src_ratio;
587 // src_data.data_out = output;
588 // src_data.output_frames = BUFFER_LEN /channels;
589 //
590 // while (1) {
591 // /* If the input buffer is empty, refill it. */
592 // if (src_data.input_frames == 0) {
593 // src_data.input_frames = sf_readf_float (infile, input, BUFFER_LEN / channels);
594 // src_data.data_in = input;
595 //
596 // /* The last read will not be a full buffer, so snd_of_input. */
597 // if (src_data.input_frames < BUFFER_LEN / channels)
598 // src_data.end_of_input = SF_TRUE;
599 // }
600 //
601 // if ((error = src_process (src_state, &src_data))) {
602 // logMsg ("SRC Error : %s", src_strerror (error));
603 // return (0);
604 // }
605 //
606 // /* Terminate if done. */
607 // if (src_data.end_of_input && src_data.output_frames_gen == 0)
608 // break;
609 //
610 // max = apply_gain (src_data.data_out, src_data.output_frames_gen, channels, max, *gain);
611 //
612 // /* Write output. */
613 // sf_writef_float (outfile, output, src_data.output_frames_gen);
614 // output_count += src_data.output_frames_gen;
615 //
616 // src_data.data_in += src_data.input_frames_used * channels;
617 // src_data.input_frames -= src_data.input_frames_used;
618 // }
619 //
620 // src_state = src_delete (src_state);
621 //
622 // if (max > 1.0) { *gain = 1.0 / max;
623 // logMsg ("Output has clipped. Restarting conversion to prevent clipping.");
624 // output_count = 0;
625 // sf_command (outfile, SFC_FILE_TRUNCATE, &output_count, sizeof (output_count));
626 // return -1;
627 // }
628 //
629 // return output_count;
630 //} /* sample_rate_convert */
631 //
632 //static double apply_gain (float * data, long frames, int channels, double max, double gain) {
633 // for (long k = 0; k < frames * channels; k++) {
634 // double val = (double) data [k];
635 // val *= gain;
636 // data[k] = val;
637 // val = fabs (val);
638 // if (val > max)
639 // max = val;
640 // }
641 // return max;
642 //} /* apply_gain */
sample * SampleBuffer
1-channel buffer data type, vector of (sample)
Definition: CSL_Types.h:194
#define UPDATE_SCALABLE_CONTROLS
Definition: CSL_Core.h:444
#define max(a, b)
Definition: matrix.h:156
void logMsg(const char *format,...)
These are the public logging messages.
Definition: CGestalt.cpp:292
SeekPosition
Enumeration for seek flags.
Definition: CSL_Core.h:560
#define kSoundFileFormatAIFF
Definition: SoundFile.h:60
unsigned mNumFrames
num frames used in each buffer
Definition: CSL_Core.h:113
unsigned mNumFrames
sample frames
Definition: SoundFile.h:189
#define csl_min(a, b)
SF_INFO * mSFInfo
libsndfile sf-info struct
Definition: SoundFileL.h:104
float mMaxDurInSecs
max size to read from file. In seconds so it can deal with varying sample rates.
Definition: SoundFileL.h:107
void readBufferFromFile(unsigned numFrames)
read a buffer from the file (possibly all of it)
Definition: SoundFileL.cpp:408
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
Definition: Accessor.h:17
SoundFileMode mMode
r/w mode
Definition: SoundFile.h:183
static unsigned maxSndFileFrames()
the max num frames that can be cached
Definition: CGestalt.cpp:56
bool isCached()
answer if file has all of its samples in RAM
Definition: SoundFileL.cpp:170
#define kSoundFileRead
Sound file constants.
Definition: SoundFile.h:54
unsigned mFrameRate
trigger ignored here
Definition: CSL_Core.h:288
unsigned mBase
starting frame in file of buffer
Definition: SoundFile.h:191
int SoundFileFormat
Definition: SoundFile.h:65
#define kSoundFileReadWrite
Definition: SoundFile.h:56
virtual void setToEnd()
set to end position
Definition: SoundFile.cpp:334
void nextBuffer(Buffer &outB)
UGen operations.
Definition: SoundFileL.cpp:288
virtual SampleBuffer buffer(unsigned bufNum)
convenience accessors for sample buffers
Definition: CSL_Core.cpp:66
SoundFileFormat format()
get format
Definition: SoundFileL.cpp:180
virtual void nextBuffer(Buffer &outputBuffer, unsigned outBufNum)
really compute the next buffer given an offset base channel; this is called by nextBuffer, possibly multiple times
Definition: Oscillator.cpp:132
void openForWrite(SoundFileFormat format=kSoundFileFormatAIFF, unsigned channels=1, unsigned rate=44100, unsigned bitDepth=16)
Open a file for writing. Default values are some common format.
Definition: SoundFileL.cpp:220
virtual void openForRead(bool load=true)
open file and get stats Open a file for write. Default values are some common format.
Definition: SoundFileL.cpp:198
void close()
close file seek to some position
Definition: SoundFileL.cpp:260
#define kSoundFileFormatRaw
Definition: SoundFile.h:63
void deinterleave(Buffer &output, SampleBuffer samples, unsigned numFrames, unsigned numChannels)
De-interleave = copy from interleaved SampleBuffer to CSL Buffer object.
Definition: CSL_Core.cpp:1337
void writeBuffer(Buffer &inputBuffer)
write a buffer of data into the file
Definition: SoundFileL.cpp:371
bool mIsValid
is my file valid?
Definition: SoundFile.h:185
static LSoundFile * openSndfile(string path, int start=-1, int stop=-1, bool doRead=true)
Factory methods.
Definition: SoundFileL.cpp:18
#define kSoundFileFormatSND
Definition: SoundFile.h:61
Interleaver mInterleaver
File IO interleaver/deinterleaver.
Definition: SoundFileL.h:106
unsigned mBytesPerSample
the # of bytes per sample
Definition: SoundFile.h:190
unsigned mCurrentFrame
where I currently am in the buffer
Definition: CSL_Core.h:580
float sample
(could be changed to int, or double)
Definition: CSL_Types.h:191
unsigned mNumChannels
my "expected" number of output channels
Definition: CSL_Core.h:292
#define kSoundFileWrite
Definition: SoundFile.h:55
#define kSoundFileFormatWAV
Definition: SoundFile.h:59
virtual void freeBuffer()
free the file cache
Definition: SoundFile.cpp:165
void openForReadWrite()
open r/w
Definition: SoundFileL.cpp:254
#define SAFE_FREE(ptr)
Definition: CGestalt.h:137
bool mIsLooping
am i looping start-stop?
Definition: SoundFile.h:186
void initFromSndfile()
read SF header
Definition: SoundFileL.cpp:124
int mStop
starting/ending frames (or -1 if not used)
Definition: SoundFile.h:187
Buffer mWavetable
the stored wave form
Definition: Oscillator.h:84
string mPath
file name
Definition: SoundFile.h:182
#define LOAD_SCALABLE_CONTROLS
Load the scale/offset-related values at the start.
Definition: CSL_Core.h:436
#define IS_UNSCALED
Definition: CSL_Core.h:454
Buffer – the multi-channel sample buffer class (passed around between generators and IO guys)...
Definition: CSL_Core.h:106
LSoundFile(std::string path, int start=-1, int stop=-1, bool doRead=true, float maxDurInSecs=0.0)
Constructor with defaults.
void checkBuffer(unsigned numFrames)
allocate buffer lazily
Definition: SoundFile.cpp:172
unsigned seekTo(int position, SeekPosition whence=kPositionStart)
seek to some position relative to "whence"
Definition: SoundFileL.cpp:268
Here's the abstract sound file reader/writer class, a sample player UGen. The concrete subclasses rep...
Definition: SoundFile.h:101
Here's the sound file reader/writer class; it assumes libSndFile and interleaved sample buffers...
Definition: SoundFileL.h:66
SNDFILE * mSndfile
libsndfile handle
Definition: SoundFileL.h:105
#define SAFE_MALLOC(ptr, type, len)
Useful Macros.
Definition: CGestalt.h:103
Base class of CSL exceptions (written upper-case). Has a string message.
#define DECLARE_SCALABLE_CONTROLS
Macros for all the Scalable UnitGenerators (note that these don't end with ";")
Definition: CSL_Core.h:429