CSL  5.2
FileIO.cpp
Go to the documentation of this file.
1 //
2 // FileIO.cpp -- File IO using libsndfile
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5 
6 #include "FileIO.h"
7 
8 using namespace csl;
9 
10 FileIO::FileIO(char * path) : IO(), mFile(0), mIsPlaying(false), mIsThreadRunning(false) {
11  if ( ! path)
13  else
14  mPath = path;
15  mFile = new SoundFile(mPath);
16 }
17 
19  if (mFile)
20  delete mFile;
21  if (mThread)
22  delete mThread;
23 }
24 
25 // Open file output file writer
26 
27 void FileIO::open() throw(CException) {
28  int channels = CGestalt::numOutChannels();
29  int blockSize = CGestalt::blockSize();
30  int rate = CGestalt::frameRate();
31  SoundFileFormat format;
32 
33 #ifdef DO_TIMING
34  mThisSec = mTimeVals = mTimeSum = 0;
35 #endif
36  if (mInBuffer.mAreBuffersAllocated) // allocate I/O buffers
38  mInBuffer.setSize(channels, blockSize);
42  mOutBuffer.setSize(channels, blockSize);
44  const char * sPath = mPath.c_str();
45 
46  char * dot = (char *) strrchr(sPath, '.'); // get the file name extension
47  format = kSoundFileFormatAIFF; // default = AIFF files
48  if (strcmp(dot, ".wav") == 0)
49  format = kSoundFileFormatWAV;
50  else if (strcmp(dot, ".snd") == 0)
51  format = kSoundFileFormatSND;
52 
53  mFile->openForWrite(format, channels, rate); // open output file
54  if ( ! mFile->isValid()) {
55  logMsg(kLogError, "Error opening sound file output");
56  return; // THROW AN EXCEPTION
57  }
58  mThread = CThread::MakeThread(); // create background thread
59  mDuration = (int)((float)blockSize / (float)rate * 1000000.0f); // block rate in usec
60  return;
61 }
62 
63 void FileIO::start(float seconds) throw(CException) {
64  mIsPlaying = true;
65  mIsThreadRunning = false;
66  if (seconds) { // full-speed driver version
67  unsigned numFrames = (unsigned) (seconds * CGestalt::frameRate());
68  logMsg("Starting sound file output loop");
69  while (mNumFramesPlayed < numFrames) // note that this does not return until it's done,
70  writeNextBuffer(); // so you can't start and then trigger envelopes!
71  } else { // Start file IO -- loop in the background
72  logMsg("Starting sound file output thread");
73  mThread->createThread(threadFunction, this);
74  }
75 }
76 
77 void FileIO::stop() throw(CException) {
78  mIsPlaying = false; // signal for writer thread to finish
79  while(mIsThreadRunning) // wait around for the feeder thread to die
81 }
82 
83 // close, free, and write output file
84 
85 void FileIO::close() throw(CException) {
90  mFile->close();
91 }
92 
93 // compute and write a buffer
94 
96  if (mGraph != 0)
98  else
100  mFile->writeBuffer(mOutBuffer);
102 }
103 
104 // Background thread function -- loop to read from the DSP graph and write to the file
105 
106 void * FileIO::threadFunction(void * ptr) {
107  FileIO *me = (FileIO *)ptr;
108 // printf("D: %d\n", me->mDuration);
109 
110 #ifdef DO_TIMING
111  int sleepTime;
112  struct timeval *meThen = &me->mThen;
113  struct timeval *meNow = & me->mNow;
114 #endif
115  while (me->mIsPlaying) { // loop until turned off
116 #ifdef DO_TIMING
117  GET_TIME(meThen);
118 #endif
119  me->writeNextBuffer(); // get and write the next buffer
120 #ifdef DO_TIMING
121  GET_TIME(meNow);
122  me->printTimeStatistics(meNow, meThen, & me->mThisSec, & me->mTimeSum, & me->mTimeVals);
123  GET_TIME(meNow);
124  sleepTime = me->mDuration - (((meNow->tv_sec - meThen->tv_sec) * 1000000) + (meNow->tv_usec - meThen->tv_usec));
125  // printf("S: %d\n", sleepTime);
126  if (sleepTime > 0)
127  csl::sleepUsec(sleepTime);
128 #else
130 #endif
131  }
132  // do this to prevent a race condition
133  me->mIsThreadRunning = false;
134  logMsg("Stopping sound file output thread");
135  return 0;
136 }