CSL 5.2

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

- File List
- File Members

SoundFileJ.cpp
Go to the documentation of this file.
1 //
2 // SoundFile.cpp -- sound file class using JUCE
3 //
4 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
5 //
6
7 #include "SoundFileJ.h"
8
9 using namespace csl;
10
11 //
12 // JSoundFile implementation
13 //
14
15 JSoundFile::JSoundFile(string tpath, int tstart, int tstop)
16 : Abst_SoundFile(tpath, tstart, tstop),
17 mAFReader(0),
18 mAFWriter(0),
19 mIOFile(0),
20 mOutStream(0) {
21 try {
22 openForRead(); // read and cache whole file
23 setToEnd();
24 } catch (CException & e) {
25 logMsg(kLogError, "File open exception caught: %s", e.mMessage.c_str());
26 return;
27 }
28 }
29
30 //JSoundFile::JSoundFile(string folder, string tpath, int tstart, int tstop)
31 // : Abst_SoundFile(folder, tpath, tstart, tstop),
32 // mAFReader(0),
33 // mAFWriter(0),
34 // mIOFile(0),
35 // mOutStream(0) {
36 // try {
37 // openForRead(); // read and cache whole file
38 // setToEnd();
39 // } catch (CException & e) {
40 // logMsg(kLogError, "File open exception caught: %s", e.mMessage.c_str());
41 // return;
42 // }
43 //}
44
45 JSoundFile::JSoundFile(JSoundFile & otherSndFile)
46 : Abst_SoundFile(otherSndFile),
47 mAFReader(otherSndFile.mAFReader),
48 mAFWriter(otherSndFile.mAFWriter),
49 mIOFile(otherSndFile.mIOFile),
50 mOutStream(otherSndFile.mOutStream) { }
51
52 JSoundFile::~JSoundFile() {
53 if (mAFReader)
54 delete mAFReader;
55 if (mAFWriter)
56 delete mAFWriter;
57 }
58
59 // Accessors
60
61 unsigned JSoundFile::duration() const {
62 return mAFReader ? (unsigned) mAFReader->lengthInSamples : 0;
63 }
64
65 SoundFileFormat JSoundFile::format() {
66 String fmt = mAFReader->getFormatName();
67 if (fmt[0] == 'A')
68 return kSoundFileFormatAIFF;
69 else if (fmt[0] == 'W')
70 return kSoundFileFormatWAV;
71 return kSoundFileFormatOther;
72 }
73
74 // set up the receiver's variables based on the file
75
76 void JSoundFile::initFromSndfile() {
77 mIsValid = ((mAFReader != NULL) || (mAFWriter != NULL));
78 if ( ! mIsValid) {
79 // logMsg(kLogError, "Cannot open sound file \"%s\"", mPath.c_str());
80 return;
81 }
82 if (mAFReader) {
83 mFrameRate = (unsigned) mAFReader->sampleRate;
84 mNumChannels = (unsigned) mAFReader->numChannels;
85 mNumFrames = (unsigned) mAFReader->lengthInSamples;
86 mBytesPerSample = (unsigned) mAFReader->bitsPerSample / 8;
87 } else if (mAFWriter) {
88 mFrameRate = (unsigned) mAFWriter->getSampleRate();
89 mNumChannels = (unsigned) mAFWriter->getNumChannels();
90 mNumFrames = 0;
91 mBytesPerSample = (unsigned) mAFWriter->getBitsPerSample() / 8;
92 }
93 if (mStart > 0)
94 seekTo(mStart, kPositionStart);
95 else
96 mStart = 0;
97 if ((mStop < 0) && mAFReader)
98 mStop = mAFReader->lengthInSamples;
99 }
100
101 void JSoundFile::openForRead(bool load) throw (CException) {
102 mMode = kSoundFileRead;
103 String fname(mPath.c_str());
104 mIOFile = new File(fname); // create a JUCE file object
105 if ( ! mIOFile->exists()) {
106 logMsg(kLogError, "Cannot find sound file \"%s\"", mPath.c_str());
107 return;
108 }
109 AudioFormatManager formatManager; // get a format manager
110 formatManager.registerBasicFormats(); // set it up with the basic types (wav and aiff).
111 mAFReader = formatManager.createReaderFor(*mIOFile);
112
113 this->initFromSndfile();
114 if ( ! mIsValid) {
115 logMsg(kLogError, "Cannot open sound file \"%s\"", mPath.c_str());
116 return;
117 }
118 if (mNumFrames <= CGestalt::maxSndFileFrames()) { // read file if size < global max
119 // logMsg("Read sound file \"%s\" %d frames %g sec %d channels",
120 // mPath.c_str(), duration(), durationInSecs(), channels());
121 unsigned numFrames = mAFReader->lengthInSamples;
122
123 this->readBufferFromFile(numFrames); // read entire file
124
125 mCurrentFrame = mStart;
126 }
127 }
128
129 void JSoundFile::openForWrite(SoundFileFormat tformat, unsigned tchannels, unsigned rate, unsigned bitDepth)
130 throw (CException) {
131 mMode = kSoundFileWrite;
132 String fname(mPath.c_str());
133 mIOFile = new File(fname); // create a JUCE file object
134 mOutStream = mIOFile->createOutputStream();
135 StringPairArray metaDict;
136 AiffAudioFormat afmt;
137 WavAudioFormat wfmt;
138
139 switch (tformat) {
140 case kSoundFileFormatAIFF:
141 mAFWriter = afmt.createWriterFor(mOutStream, (double) rate, tchannels, bitDepth, metaDict, 0);
142 break;
143 case kSoundFileFormatWAV:
144 mAFWriter = wfmt.createWriterFor(mOutStream, (double) rate, tchannels, bitDepth, metaDict, 0);
145 break;
146 default:
147 logMsg (kLogError, "Unsupported sound file format");
148 throw IOError("Unsupported sound file format");
149 }
150 initFromSndfile();
151 }
152
153 void JSoundFile::close() {
154 freeBuffer();
155 }
156
157 // read some samples from the file into the temp buffer
158
159 void JSoundFile::readBufferFromFile(unsigned numFrames) {
160 SampleBuffer sampleBufferPtr;
161 unsigned currentFrame = mCurrentFrame;
162 unsigned myChannels = mNumChannels;
163
164 this->checkBuffer(numFrames); // check my buffer, allocate if necessary
165 // if we are at the end of the file and not looping
166 if ((currentFrame >= (unsigned) mStop) && !mIsLooping) {
167 for (unsigned i = 0; i < mNumChannels; i++) {
168 sampleBufferPtr = mWavetable.monoBuffer(i);
169 memset(sampleBufferPtr, 0, numFrames * sizeof(sample));
170 }
171 return;
172 }
173 // JUCE read fcn
174 // logMsg ("Sound file read %d", numFrames);
175 // if (mAFReader->read(mWavetable.mBuffers, myChannels, mCurrentFrame, numFrames, false)) {
176 if (1) {
177 currentFrame += numFrames;
178 } else {
179 logMsg (kLogError, "Sound file read error");
180 throw IOError("Sound file read error");
181 }
182 // if we are past the end of the file...
183 if (currentFrame > (unsigned) mStop) {
184 unsigned numFramesRemaining = currentFrame - mStop;
185 unsigned numFramesRead = numFrames - numFramesRemaining;
186 // SampleBuffer tempBufferPtr = sampleBufferPtr + (numFramesRead * myChannels);
187 if (mIsLooping) { // loop back to start of file
188 while (numFramesRead < numFrames) {
189 currentFrame = seekTo(0, kPositionStart);
190 // call JUCE read function
191 // TODO LMS commented out mAFReader->read(mWavetable.mBuffers, myChannels, mCurrentFrame, numFrames, false);
192 currentFrame += numFramesRead;
193 }
194 } else {
195 unsigned bytesToClear = numFramesRemaining * sizeof(sample);
196 for (unsigned i = 0; i < mNumChannels; i++) {
197 sampleBufferPtr = mWavetable.monoBuffer(i);
198 memset(sampleBufferPtr, 0, bytesToClear);
199 }
200 }
201 }
202 }
203
204 //void JSoundFile::convertFormat(unsigned num, unsigned start) {
205 // SampleBuffer sampleBufferPtr;
206 // int * intBufferPtr;
207 // sample normFactor = 1.0 / (float) (32768 << 16);
208 //
209 // for (unsigned channelIndex = 0; channelIndex < mNumChannels; channelIndex++) {
210 /// sampleBufferPtr = mWavetable.monoBuffer(channelIndex) + start;
211 // intBufferPtr = mConvBuffer[channelIndex];
212 // for (unsigned j = 0; j < num; j++) {
213 // *sampleBufferPtr++ = ((float) *intBufferPtr++) * normFactor;
214 // }
215 // }
216 //}
217
218 // Seek
219
220 unsigned JSoundFile::seekTo(int position, SeekPosition whence) throw(CException) {
221 int whenceInt;
222 if (this->isCached()) {
223 mCurrentFrame = position;
224 return mCurrentFrame;
225 }
226 switch (whence) {
227 case kPositionStart:
228 whenceInt = position;
229 break;
230 case kPositionCurrent:
231 whenceInt = mCurrentFrame - position;
232 break;
233 case kPositionEnd:
234 whenceInt = duration() - position;
235 break;
236 default:
237 whenceInt = SEEK_CUR;
238 logMsg("Error: Invalid position seek flag. Used kPositionCurrent.");
239 break;
240 }
241 if (mOutStream)
242 mOutStream->setPosition(whenceInt);
243 return mCurrentFrame;
244 }
245
246 // write a CSL buffer to the interleaved output file
247
248 void JSoundFile::writeBuffer(Buffer &inputBuffer) throw(CException) {
249 unsigned numFrames = inputBuffer.mNumFrames;
250 // JUCE write fcn
251 // if (mAFWriter->write(inputBuffer.mBuffers, numFrames)) {
252 if (1) {
253 mCurrentFrame += numFrames;
254 } else {
255 logMsg (kLogError, "Sound file write error");
256 throw IOError("Sound file write error");
257 }
258 }
259