CSL 5.2

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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)
12 mPath = CGestalt::sndFileName();
13 else
14 mPath = path;
15 mFile = new SoundFile(mPath);
16 }
17
18 FileIO::~FileIO() {
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
37 mInBuffer.freeBuffers();
38 mInBuffer.setSize(channels, blockSize);
39 mInBuffer.allocateBuffers();
40 if (mOutBuffer.mAreBuffersAllocated)
41 mOutBuffer.freeBuffers();
42 mOutBuffer.setSize(channels, blockSize);
43 mOutBuffer.allocateBuffers();
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
80 csl::sleepUsec(mDuration);
81 }
82
83 // close, free, and write output file
84
85 void FileIO::close() throw(CException) {
86 if (mOutBuffer.mAreBuffersAllocated)
87 mOutBuffer.freeBuffers();
88 if (mInBuffer.mAreBuffersAllocated)
89 mInBuffer.freeBuffers();
90 mFile->close();
91 }
92
93 // compute and write a buffer
94
95 void FileIO::writeNextBuffer() {
96 if (mGraph != 0)
97 mGraph->nextBuffer(mOutBuffer);
98 else
99 mOutBuffer.zeroBuffers();
100 mFile->writeBuffer(mOutBuffer);
101 mNumFramesPlayed += mOutBuffer.mNumFrames;
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
129 csl::sleepUsec(me->mDuration);
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 }