CSL 5.2

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

- File List
- File Members

CSL_Core.cpp
Go to the documentation of this file.
1 //
2 // CSL_Core.cpp -- the implementation of Buffer, UnitGenerator, IO, mix-ins, etc.
3 //
4 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
5 //
6
7 #include "CSL_Core.h" // it's all declared here
8 #include "RingBuffer.h" // UnitGenerator uses RingBuffers
9 #include <string.h> // for bzero / memset
10 #include <stdlib.h> // for malloc
11 #include <math.h>
12 #ifndef WIN32
13 #include <samplerate.h> // libsamplerate header file
14 #endif
15 using namespace csl;
16
17 #ifdef WIN32
18
19 #define rint(x) ((int)(x + 0.5f))
20
21 #endif
22
23 //
24 // Basic buffer methods
25 //
26
27 // Constructor with size args does not allocate
28
29 Buffer::Buffer(unsigned numChannels, unsigned numFrames) :
30 mNumChannels(0),
31 mNumFrames(0),
32 mNumAlloc(0),
33 mMonoBufferByteSize(0),
34 mSequence(0),
35 mAreBuffersAllocated(false),
36 mDidIAllocateBuffers(false),
37 mIsPopulated(false),
38 mAreBuffersZero(true),
39 mType(kSamples),
40 mBuffers(0) {
41 setSize(numChannels, numFrames);
42 }
43
44 // Free on destruction
45
46 Buffer::~Buffer() {
47 if (mDidIAllocateBuffers)
48 freeBuffers();
49 }
50
51 // SetSize creates the vector of sample pointers, does not allocate the sample storage
52
53
54 void Buffer::setSize(unsigned numChannels, unsigned numFrames) {
55 if (mAreBuffersAllocated && mDidIAllocateBuffers && (mNumChannels != numChannels)
56 && (mNumAlloc < numFrames)) {
57 freeBuffers();
58 mDidIAllocateBuffers = false;
59 mAreBuffersAllocated = false;
60 }
61 if (mNumChannels != numChannels) {
62 mNumChannels = numChannels; // Transfer parameters to member variables
63 if (mBuffers)
64 delete mBuffers; // free buffer pointers
65 mBuffers = new SampleBuffer[numChannels]; // reserve space for buffers
66 for (unsigned i = 0; i < mNumChannels; i++)
67 mBuffers[i] = 0;
68 }
69 if (mNumFrames != numFrames) {
70 mNumFrames = numFrames;
71 mMonoBufferByteSize = mNumFrames * sizeof(sample);
72 }
73 mIsPopulated = false;
74 }
75
76 // set size and don't allocate vector space either
77
78 void Buffer::setSizeOnly(unsigned numChannels, unsigned numFrames) {
79 mNumChannels = numChannels;
80 mNumFrames = numFrames;
81 mMonoBufferByteSize = numFrames * sizeof(sample);
82 }
83
84 // allocate if not already there
85
86 void Buffer::checkBuffers() throw (MemoryError) {
87 if ( ! mAreBuffersAllocated)
88 allocateBuffers();
89 }
90
91 // allocate the sample arrays
92
93 //#define FVERBOSE_MALLOC // define for verbose debugging of buffer alloc/free
94
95 void Buffer::allocateBuffers() throw (MemoryError) {
96 #ifdef FVERBOSE_MALLOC
97 logMsg(" Buffer::allocateBuffers(%x %d %d)", this, mNumChannels, mNumFrames);
98 #endif
99 for (unsigned i = 0; i < mNumChannels; i++) {
100 SAFE_MALLOC(mBuffers[i], sample, mNumFrames);
101 memset(mBuffers[i], 0, mNumFrames * sizeof(sample));
102 }
103 // if (mNumFrames < 16)
104 // logMsg("Small buffer: %d", mNumFrames);
105 mAreBuffersAllocated = true;
106 mDidIAllocateBuffers = true;
107 mNumAlloc = mNumFrames;
108 }
109
110 // free them carefully
111
112 void Buffer::freeBuffers() {
113 if ( ! mAreBuffersAllocated)
114 return; // they aren't allocated -- I shouldn't free them
115 if ( ! mDidIAllocateBuffers)
116 return; // I didn't allocate them -- I shouldn't free them
117 if (& mBuffers == NULL)
118 return;
119 #ifdef FVERBOSE_MALLOC
120 logMsg(" Buffer::freeBuffers (%x %d %d)", this, mNumChannels, mNumFrames);
121 #endif
122 try {
123 for (unsigned i = 0; i < mNumChannels; i++) {
124 if (mBuffers[i]) {
125 delete mBuffers[i]; // do the delete
126 mBuffers[i] = NULL; // set to zero right away
127 }
128 }
129 } catch (std::exception ex) {
130 logMsg(kLogError, "\nError in Buffer::freeBuffers: %s\n", ex.what());
131 throw MemoryError("Error in Buffer::freeBuffers");
132 }
133 mAreBuffersAllocated = false;
134 mDidIAllocateBuffers = false;
135 delete mBuffers;
136 mBuffers = 0;
137 mNumAlloc = 0;
138 }
139
140 // empty the sample buffers
141
142 void Buffer::zeroBuffers() {
143 if ( ! mAreBuffersAllocated)
144 return;
145 for (unsigned i = 0; i < mNumChannels; i++)
146 memset(mBuffers[i], 0, mMonoBufferByteSize);
147 mAreBuffersZero = true;
148 }
149
150 /// answer a samp ptr tested for extent (offset + maxFrame)
151
152 sample * Buffer::samplePtrFor(unsigned channel, unsigned offset){
153 return(mBuffers[channel] + offset);
154 }
155
156 /// answer a samp ptr tested for extent (offset + maxFrame)
157
158 sample * Buffer::samplePtrFor(unsigned channel, unsigned offset, unsigned maxFrame){
159 if (mNumAlloc >= (offset + maxFrame))
160 return(mBuffers[channel] + offset);
161 return NULL;
162 }
163
164 ///< answer whether the receiver can store numFrames more frames
165
166 bool Buffer::canStore(unsigned numFrames) {
167 return ((mNumFrames + numFrames) < mNumAlloc);
168 }
169
170 // fill with a constant
171
172 void Buffer::fillWith(sample value) {
173 float * bbuffer = NULL;
174 unsigned outBufNum, i;
175 unsigned numChans = mNumChannels;
176 unsigned numFrames = mNumFrames;
177 for (outBufNum = 0; outBufNum < numChans; outBufNum++) {
178 bbuffer = mBuffers[outBufNum];
179 for (i = 0; i < numFrames; i++)
180 *bbuffer++ = value;
181 }
182 mAreBuffersZero = false;
183 }
184
185 // copy the "header" info
186
187 void Buffer::copyHeaderFrom(Buffer & source) throw (RunTimeError) {
188 if ((source.mNumChannels > mNumChannels) || (source.mNumFrames > mNumAlloc)) {
189 logMsg("Buffer::copyHeaderFrom(ch %d %d, fr %d %d)",
190 mNumChannels, source.mNumChannels, mNumAlloc, source.mNumFrames);
191 throw RunTimeError("Can't reallocate buffers at run-time");
192 }
193 mNumChannels = source.mNumChannels; // copy members
194 mNumFrames = source.mNumFrames;
195 mMonoBufferByteSize = mNumFrames * sizeof(sample);
196 mSequence = source.mSequence;
197 mType = source.mType;
198 }
199
200 // Copy everything but samples from the argument to the receiver
201
202 void Buffer::copyFrom(Buffer & source) throw (RunTimeError) {
203 this->freeBuffers(); // free everything
204 delete mBuffers;
205 mNumChannels = source.mNumChannels; // copy members
206 mNumFrames = source.mNumFrames;
207 mNumAlloc = source.mNumAlloc;
208 mMonoBufferByteSize = mNumFrames * sizeof(sample);
209 mSequence = source.mSequence;
210 mBuffers = new SampleBuffer[mNumChannels]; // reserve space for buffers
211 // copy sample pointers
212 for (unsigned outBufNum = 0; outBufNum < mNumChannels; outBufNum++) {
213 mBuffers[outBufNum] = source.monoBuffer(outBufNum);
214 }
215 mAreBuffersZero = false; // set flags
216 mAreBuffersAllocated = true;
217 mDidIAllocateBuffers = false;
218 }
219
220 // Copy samples from the argument to the receiver; be paranoid about size limits
221
222 void Buffer::copySamplesFrom(Buffer & source) throw (RunTimeError) {
223 if ((source.mNumChannels > mNumChannels) || (source.mNumFrames > mNumAlloc)) {
224 logMsg(kLogError, "Buffer::copySamplesFrom(ch %d %d, fr %d %d)",
225 mNumChannels, source.mNumChannels, mNumAlloc, source.mNumFrames);
226 throw RunTimeError("Can't reallocate buffers at run-time");
227 }
228 mNumChannels = source.mNumChannels;
229 mNumFrames = source.mNumFrames;
230 mMonoBufferByteSize = mNumFrames * sizeof(sample);
231 for (unsigned outBufNum = 0; outBufNum < mNumChannels; outBufNum++) { // copy loop
232 unsigned sBufNum = csl_min(outBufNum, (source.mNumChannels - 1));
233 memcpy(mBuffers[outBufNum], source.monoBuffer(sBufNum), mMonoBufferByteSize);
234 }
235 mAreBuffersZero = false;
236 }
237
238 void Buffer::copyOnlySamplesFrom(Buffer & source) throw (RunTimeError) {
239 if ((source.mNumChannels > mNumChannels) || (source.mNumFrames > mNumAlloc)) {
240 logMsg(kLogError, "Buffer::copyOnlySamplesFrom(ch %d %d, fr %d %d)",
241 mNumChannels, source.mNumChannels, mNumFrames, source.mNumFrames);
242 throw RunTimeError("Can't reallocate buffers at run-time");
243 }
244 for (unsigned outBufNum = 0; outBufNum < mNumChannels; outBufNum++) {
245 unsigned sBufNum = csl_min(outBufNum, (source.mNumChannels - 1));
246 memcpy(mBuffers[outBufNum], source.monoBuffer(sBufNum), mMonoBufferByteSize);
247 }
248 }
249
250 ///< same with write offset
251
252 void Buffer::copySamplesFromTo(Buffer & source, unsigned offset) throw (RunTimeError) {
253 if ((source.mNumChannels > mNumChannels) || ((offset + source.mNumFrames) > mNumAlloc)) {
254 logMsg(kLogError, "Buffer::copyOnlySamplesFrom(ch %d %d, fr %d %d)",
255 mNumChannels, source.mNumChannels, mNumFrames, source.mNumFrames);
256 throw RunTimeError("Can't reallocate buffers at run-time");
257 }
258 for (unsigned outBufNum = 0; outBufNum < mNumChannels; outBufNum++) {
259 unsigned sBufNum = csl_min(outBufNum, (source.mNumChannels - 1));
260 memcpy(mBuffers[outBufNum] + offset, source.monoBuffer(sBufNum),
261 (source.mNumFrames * sizeof(sample)));
262 }
263 }
264
265 #ifdef USE_SRC
266
267 // convert the sample rate using libSampleRate
268
269 Status Buffer::convertRate(int fromRate, int toRate) {
270 double src_ratio = (double) toRate / (double) fromRate;
271 int error;
272 // scaled buffer length
273 unsigned newLen = (unsigned) (rint(((double) mNumFrames) * src_ratio));
274 SRC_STATE * src_state; // SRC structs
275 SRC_DATA src_data;
276 // create/allocate new scaled buffer
277 Buffer * newBuf = new Buffer(mNumChannels, newLen);
278 newBuf->allocateBuffers();
279
280 // logMsg("Buffer::convertRate from %d to %d = %d frames", fromRate, toRate, newLen);
281 // create temp name and rename file
282 src_ratio = (double) toRate / (double) fromRate;
283 if (src_is_valid_ratio (src_ratio) == 0) {
284 logMsg (kLogError, "Error: Sample rate change out of valid range.");
285 return kErr;
286 }
287 /* Initialize the sample rate converter. */
288 if ((src_state = src_new (SRC_SINC_FASTEST /* SRC_SINC_BEST_QUALITY */, 1, &error)) == NULL) {
289 logMsg ("Error : src_new() failed : %s.", src_strerror (error));
290 exit (1);
291 };
292 src_data.src_ratio = src_ratio; // set up SRC
293 src_data.input_frames = mNumFrames;
294 src_data.output_frames = newLen;
295 src_data.end_of_input = 1;
296 // loop over the channels
297 for (unsigned i = 0; i < mNumChannels; i++) {
298 src_data.data_in = mBuffers[i];
299 src_data.data_out = newBuf->buffer(i);
300 // call src_process
301 error = src_process(src_state, &src_data);
302 if (error) {
303 logMsg("SRC Error : %s", src_strerror(error));
304 return kErr;
305 }
306 }
307 src_state = src_delete (src_state);
308 this->copyFrom(*newBuf); // copy sample pointers to me
309 mDidIAllocateBuffers = true; // toggle ownership flags
310 newBuf->mDidIAllocateBuffers = false;
311 delete newBuf;
312 return kOk;
313 }
314
315 #endif
316
317 ///////////////////////////////////
318
319 #ifdef CSL_DSP_BUFFER /// Buffer Sample Processing (optional)
320
321 #include <libtsp.h> // for the autocorrelation
322
323 ///< get the root-mean-square of the samples
324
325 sample Buffer::rms(unsigned chan) {
326 unsigned thech = chan % mNumChannels;
327 unsigned numFrames = mNumFrames;
328 sample val, sum = 0.0;
329 sample* buffer = mBuffers[thech];
330 for (unsigned i = 0; i < numFrames; i++) {
331 val = *buffer++;
332 sum += (val * val);
333 }
334 return sum / numFrames;
335 }
336
337 ///< get the average of the samples
338
339 sample Buffer::avg(unsigned chan) {
340 unsigned thech = chan % mNumChannels;
341 unsigned numFrames = mNumFrames;
342 sample sum = 0.0;
343 sample* buffer = mBuffers[thech];
344 for (unsigned i = 0; i < numFrames; i++)
345 sum += *buffer++;
346 return sum / numFrames;
347 }
348
349 ///< get the max of the samples
350
351 sample Buffer::max(unsigned chan) {
352 unsigned thech = chan % mNumChannels;
353 unsigned numFrames = mNumFrames;
354 sample val, tmax = 0.0;
355 sample* buffer = mBuffers[thech];
356 for (unsigned i = 0; i < numFrames; i++) {
357 val = *buffer++;
358 if (fabs(val) > tmax) tmax - fabs(val);
359 }
360 return tmax;
361 }
362
363 ///< get the min of the samples
364
365 sample Buffer::min(unsigned chan) {
366 unsigned thech = chan % mNumChannels;
367 unsigned numFrames = mNumFrames;
368 sample val, tmax = 0.0;
369 sample* buffer = mBuffers[thech];
370 for (unsigned i = 0; i < numFrames; i++) {
371 val = *buffer++;
372 if (fabs(val) > tmax) tmax - fabs(val);
373 }
374 return tmax;
375 }
376
377 ///< count the zero-crossings in the samples
378
379 unsigned int Buffer::zeroX(unsigned chan) {
380 unsigned thech = chan % mNumChannels;
381 unsigned numFrames = mNumFrames, count = 0, sign = 0;
382 sample val;
383 sample* buffer = mBuffers[thech];
384 for (unsigned i = 0; i < numFrames; i++) {
385 val = *buffer++;
386 if (((val > 0) && sign) || ((val < 0) && ! sign)) {
387 count += 1;
388 sign = 1 - sign;
389 }
390 }
391 return count;
392 }
393
394 ///< answer the index of the peak value
395
396 unsigned int Buffer::indexOfPeak(unsigned chan) {
397 unsigned thech = chan % mNumChannels;
398 unsigned numFrames = mNumFrames, index;
399 sample val, tmax = -1000000.0;
400 sample* buffer = mBuffers[thech];
401 for (unsigned i = 0; i < numFrames; i++) {
402 val = *buffer++;
403 if (val > tmax) {
404 tmax = val;
405 index = i;
406 }
407 }
408 return index;
409 }
410
411 ///< answer the index of the peak value
412
413 unsigned int Buffer::indexOfPeak(unsigned chan, unsigned lo, unsigned hi) {
414 unsigned index = 0, thech = chan % mNumChannels;
415 sample val, tmax = -100000.0;
416 sample* buffer = mBuffers[thech] + lo;
417 for (unsigned i = lo; i < hi; i++) {
418 val = *buffer++;
419 if (val > tmax) {
420 tmax = val;
421 index = i;
422 }
423 }
424 return index;
425 }
426
427 ///< answer the index of the peak value
428
429 unsigned int Buffer::indexOfMin(unsigned chan) {
430 unsigned thech = chan % mNumChannels;
431 unsigned numFrames = mNumFrames, index;
432 sample val, tmin = 1000000.0;
433 sample* buffer = mBuffers[thech];
434 for (unsigned i = 0; i < numFrames; i++) {
435 val = *buffer++;
436 if (val < tmin) {
437 tmin = val;
438 index = i;
439 }
440 }
441 return index;
442 }
443
444 ///< answer the index of the peak value
445
446 unsigned int Buffer::indexOfMin(unsigned chan, unsigned lo, unsigned hi) {
447 unsigned index = 0, thech = chan % mNumChannels;
448 sample val, tmin = 1000000.0;
449 sample* buffer = mBuffers[thech] + lo;
450 for (unsigned i = lo; i < hi; i++) {
451 val = *buffer++;
452 if (val < tmin) {
453 tmin = val;
454 index = i;
455 }
456 }
457 return index;
458 }
459
460 ///< write the autocorrelation into the given array
461
462 void Buffer::autocorrelation(unsigned chan, SampleBuffer result) {
463 unsigned thech = chan % mNumChannels;
464 unsigned numFrames = mNumFrames;
465 sample* buffer = mBuffers[thech];
466 // SPautoc (const float in[], int in_size, float out[], int out_size)
467 // - out[i] is autocorrelation with lag i
468 SPautoc (buffer, numFrames, result, numFrames); // perform autocorrelation
469 }
470
471 #endif // CSL_DSP_BUFFER
472
473
474 // Sample buffer with channel map and count
475 // the map is so that one can have (e.g.,) a buffer that stands for 3 channels within an 8-channel space
476
477 BufferCMap::BufferCMap() : Buffer() { }
478
479 BufferCMap::BufferCMap(unsigned numChannels, unsigned numFrames) :
480 Buffer(numChannels, numFrames),
481 mRealNumChannels(numChannels) { }
482
483 BufferCMap::BufferCMap(unsigned numChannels, unsigned realNumChannels, unsigned numFrames) :
484 Buffer(numChannels, numFrames),
485 mRealNumChannels(realNumChannels) { }
486
487 BufferCMap::~BufferCMap() { }
488
489
490 //-------------------------------------------------------------------------------------------------//
491 //
492 // UnitGenerator implementation
493 //
494
495 // mono by default
496
497 UnitGenerator::UnitGenerator(unsigned rate, unsigned chans) : Model(),
498 mFrameRate(rate),
499 mNumChannels(chans),
500 mCopyPolicy(kCopy),
501 mNumOutputs(0),
502 mOutputCache(0),
503 mSequence(0)
504 /* mName(0) */
505 { }
506
507 ///< Destructor
508
509 UnitGenerator::~UnitGenerator() {
510 // logMsg(" ~UnitGenerator %x", this);
511 }
512
513 void UnitGenerator::zeroBuffer(Buffer & outputBuffer, unsigned outBufNum) {
514 float * buffer = outputBuffer.monoBuffer(outBufNum);
515 memset(buffer, 0, outputBuffer.mMonoBufferByteSize);
516 }
517
518 // output management and auto-fan-out
519
520 void UnitGenerator::addOutput(UnitGenerator * ugen) {
521 // logMsg("UnitGenerator::addOutput %x to %x", ugen, this);
522 mOutputs.push_back(ugen); // if adding the 2nd output, set up fan-out cache
523 if ((mNumOutputs == 1) && (mOutputCache == 0)) {
524 mOutputCache = new Buffer(mNumChannels, CGestalt::maxBufferFrames());
525 mOutputCache->allocateBuffers();
526 }
527 mNumOutputs++;
528 }
529
530 void UnitGenerator::removeOutput(UnitGenerator * ugen) {
531 UGenVector::iterator pos;
532 for (pos = mOutputs.begin(); pos != mOutputs.end(); ++pos) {
533 if (*pos == ugen) {
534 mOutputs.erase(pos);
535 break;
536 }
537 }
538 mNumOutputs--;
539 }
540
541 // pretty-print the receiver
542
543 void UnitGenerator::dump() {
544 logMsg("a UnitGenerator with %d outputs", mOutputs.size());
545 }
546
547 // check for fan-out; if fanning out, copy previous buffer & return true
548
549 bool UnitGenerator::checkFanOut(Buffer & outputBuffer) throw (CException) {
550 if (mNumOutputs > 1) { // if we're doing auto-fan-out
551 if (outputBuffer.mSequence <= mSequence) { // if we've already computed this seq #
552 // and block copy samples from the cache into the output
553 outputBuffer.copyOnlySamplesFrom(*mOutputCache);
554 // logMsg("UnitGenerator::checkFanOut");
555 return true; // finished!
556 }
557 }
558 return false;
559 }
560
561 // if fanning out, store last output and set seq number
562
563 void UnitGenerator::handleFanOut(Buffer & outputBuffer) throw (CException) {
564 if (mNumOutputs > 1) // if we're doing auto-fan-out and this is the first time
565 mOutputCache->copySamplesFrom(outputBuffer); // store it in the buffer
566 mSequence = csl_max(mSequence, outputBuffer.mSequence); // remember my seq #
567 // this->changed((void *) & outputBuffer); // signal dependents (if any) of my change
568 }
569
570 //
571 // Generic next buffer function: call the private (mono) version for each I/O channel;
572 // copy or expand depending on the mCopyPolicy;
573 // copy to the private cache in case of fan-out.
574 //
575
576 void UnitGenerator::nextBuffer(Buffer & outputBuffer) throw (CException) {
577 unsigned numOutputChannels = outputBuffer.mNumChannels;
578 unsigned bufferByteSize = outputBuffer.mMonoBufferByteSize;
579 SampleBuffer buffer0 = outputBuffer.monoBuffer(0);
580 #ifdef CSL_DEBUG
581 logMsg("UnitGenerator::nextBuffer");
582 #endif
583 if (checkFanOut(outputBuffer)) return;
584 // Copy the output buffer samples
585 switch (mCopyPolicy) {
586 default:
587 case kCopy: // compute 1 channel and copy it
588 this->nextBuffer(outputBuffer, 0); // this is where most of the work gets done in CSL
589 for (unsigned i = 1; i < numOutputChannels; i += mNumChannels)
590 memcpy (outputBuffer.monoBuffer(i), buffer0, bufferByteSize);
591 break;
592 case kExpand: // loop through the requested output channels
593 for (unsigned i = 0; i < numOutputChannels; i += mNumChannels)
594 nextBuffer(outputBuffer, i); // call private nextBuffer per-channel
595 break;
596 case kIgnore: // Only do as many channels as I have
597 this->nextBuffer(outputBuffer, 0);
598 break;
599 }
600 handleFanOut(outputBuffer); // process possible fan-out
601 }
602
603 // Generic private next buffer implementation; by default, just zero out the buffer
604
605 void UnitGenerator::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
606 for (unsigned i = 0; i < mNumChannels; i++)
607 zeroBuffer(outputBuffer, i); // my subclasses do more interesting things here
608 }
609
610 //-------------------------------------------------------------------------------------------------//
611 //
612 // Port implementation
613
614 Port::Port() :
615 mUGen(NULL),
616 mBuffer(new Buffer(1, CGestalt::blockSize())),
617 mValue(0),
618 mValuePtr(& mValue),
619 mPtrIncrement(0) { }
620
621 Port::Port(UnitGenerator * ug) :
622 mUGen(ug),
623 mBuffer(new Buffer(ug->numChannels(), CGestalt::blockSize())),
624 mValue(0),
625 mPtrIncrement(1) {
626 mBuffer->allocateBuffers();
627 mValuePtr = mBuffer->monoBuffer(0) - 1; // set to -1 since nextValue does pre-increment
628 }
629
630 Port::Port(float value) :
631 mUGen(NULL),
632 mBuffer(NULL),
633 mValue(value),
634 mValuePtr(& mValue),
635 mPtrIncrement(0) { }
636
637 Port::~Port() {
638
639
640 }
641
642 // check the port's buffer and allocate it if needed
643
644 void Port::checkBuffer() throw (LogicError) {
645 Buffer * buf = mBuffer;
646 UnitGenerator * ug = mUGen;
647
648 if (buf == 0)
649 throw LogicError("Checking an unassigned buffer");
650 if ((buf->mNumChannels != ug->numChannels()) || (buf->mNumFrames == 1)) {
651 buf->freeBuffers();
652 buf->setSize(ug->numChannels(), CGestalt::blockSize());
653 buf->allocateBuffers();
654 }
655 }
656
657 // Call this to reset the pointer without re-pulling the input (see SumOfSines)
658
659 void Port::resetPtr() {
660 if (mPtrIncrement) // if I'm dynamic
661 mValuePtr = (mBuffer->monoBuffer(0)) - 1; // set to -1 since nextValue does pre-increment
662 }
663
664 // Answer whether the receiver is active
665
666 bool Port::isActive() {
667 if (mUGen == NULL)
668 return (true);
669 else
670 return mUGen->isActive();
671 }
672
673 // pretty-print the receiver
674
675 void Port::dump() {
676 logMsg("a Port with UGen = %x, value = %g, incr = %d", mUGen, mValue, mPtrIncrement);
677 if (mUGen != 0) {
678 fprintf(stderr, "\t");
679 mUGen->dump();
680 }
681 }
682
683 //-------------------------------------------------------------------------------------------------//
684 //
685 // Controllable implementation -- Grab the dynamic values for the scale and offset controls
686
687 ///< Destructor
688
689 Controllable::~Controllable() {
690 for (PortMap::iterator pos = mInputs.begin(); pos != mInputs.end(); pos++)
691 delete (pos->second);
692 mInputs.clear();
693 }
694
695 void Controllable::pullInput(Port * thePort, unsigned numFrames) throw (CException) {
696 #ifdef CSL_DEBUG
697 logMsg("Controllable::pullInput");
698 #endif
699 if (thePort == NULL) {
700 logMsg("Controllable::pullInput port == null!");
701 return;
702 }
703 UnitGenerator * theUG = thePort->mUGen; // get its UGen
704 if (theUG == NULL) { // if it's a static variable
705 // logMsg("Controllable::pullInput UG == null!");
706 return; // ignore it
707 }
708 Buffer * theBuffer = thePort->mBuffer; // else get the buffer
709 if (theBuffer == NULL) { // if it's a static variable
710 logMsg("Controllable::pullInput Buffer == null!");
711 return; // ignore it
712 }
713 thePort->checkBuffer();
714 theBuffer->mNumFrames = numFrames;
715 theBuffer->mType = kSamples;
716 theBuffer->zeroBuffers();
717
718 theUG->nextBuffer(* theBuffer); //////// and ask the UGen for nextBuffer()
719
720 theBuffer->mIsPopulated = true;
721 thePort->mValuePtr = (thePort->mBuffer->monoBuffer(0)) - 1;
722 thePort->mValueIndex = 0;
723 }
724
725 // Controllable implementation -- this version writes into the buffer you pass it
726
727 void Controllable::pullInput(Port * thePort, Buffer & theBuffer) throw (CException) {
728 if (thePort == NULL)
729 return;
730 UnitGenerator * theUG = thePort->mUGen; // get its UGen
731 if (theUG == NULL) // if it's a static variable
732 return; // ignore it
733 theUG->nextBuffer(theBuffer); ///////// and ask the UGen for nextBuffer()
734
735 theBuffer.mIsPopulated = true;
736 thePort->mValuePtr = (theBuffer.monoBuffer(0)) - 1;
737 thePort->mValueIndex = 0;
738 }
739
740 // Plug in a unit generator to the named input slot
741
742 void Controllable::addInput(CSL_MAP_KEY key, UnitGenerator & uGen) {
743 #ifdef CSL_DEBUG
744 logMsg("Controllable::set input \"%d\" UGen", key);
745 #endif
746 Port * thePort = mInputs[key]; // get the named port
747 if (thePort != 0) // if port found
748 delete thePort;
749 thePort = new Port(&uGen);
750 mInputs[key] = thePort; // add it to the list of inputs
751 uGen.addOutput((UnitGenerator *) this); // be sure to add me as an output of the other guy
752 }
753
754 void Controllable::addInput(CSL_MAP_KEY key, float value) {
755 #ifdef CSL_DEBUG
756 logMsg("Controllable::set input \"%d\" to %g", key, value);
757 #endif
758 Port * thePort = mInputs[key]; // get the named port
759 if (thePort == 0) { // if no port found
760 thePort = new Port(value);
761 mInputs[key] = thePort; // add it to the list of inputs
762 } else
763 thePort->mValue = value;
764 }
765
766 // get a port
767
768 Port * Controllable::getPort(CSL_MAP_KEY name) {
769 return(mInputs[name]);
770 }
771
772 // Pretty-print the receiver
773
774 void Controllable::dump() {
775 logMsg("a Controllable with the map:");
776 for (PortMap::iterator pos = mInputs.begin(); pos != mInputs.end(); ++pos) {
777 switch (pos->first) {
778 case CSL_FREQUENCY:
779 logMsg(" key: Frequency = UG: ");
780 break;
781 case CSL_SCALE:
782 logMsg(" key: Scale = UG: ");
783 break;
784 case CSL_OFFSET:
785 logMsg(" key: Offset = UG: ");
786 break;
787 case CSL_INPUT:
788 // case CSL_INPUT_L:
789 // case CSL_INPUT_R:
790 logMsg(" key: Input = UG: ");
791 break;
792 default:
793 logMsg(" key: Other = UG: ");
794
795 }
796 pos->second->dump(); // go up the graph tree dumping inputs and controls
797 }
798 }
799
800 /////////////////////////////////////////////////
801 //
802 // Phased implementation -- Constructors
803
804 Phased::Phased() : Controllable(), mPhase(0.0f) {
805 mInputs[CSL_FREQUENCY] = new Port;
806 #ifdef CSL_DEBUG
807 logMsg("Phased::add freq input");
808 #endif
809 }
810
811 Phased::Phased(UnitGenerator & frequency, float phase) : mPhase(phase) {
812 this->addInput(CSL_FREQUENCY, frequency);
813 #ifdef CSL_DEBUG
814 logMsg("Phased::add freq input");
815 #endif
816 }
817
818 Phased::Phased(float frequency, float phase) : mPhase(phase) {
819 this->addInput(CSL_FREQUENCY, frequency);
820 #ifdef CSL_DEBUG
821 logMsg("Phased::add freq input");
822 #endif
823 }
824
825 Phased::~Phased() { /* ?? */ }
826
827 // Accessors
828
829 void Phased::setFrequency(UnitGenerator & frequency) {
830 this->addInput(CSL_FREQUENCY, frequency);
831 }
832
833 void Phased::setFrequency(float frequency) {
834 this->addInput(CSL_FREQUENCY, frequency);
835 }
836
837 // Scalable -- Constructors
838
839 Scalable::Scalable() {
840 mInputs[CSL_SCALE] = new Port;
841 mInputs[CSL_OFFSET] = new Port;
842 #ifdef CSL_DEBUG
843 logMsg("Scalable::add null inputs");
844 #endif
845 }
846
847 Scalable::Scalable(float scale) {
848 this->addInput(CSL_SCALE, scale);
849 mInputs[CSL_OFFSET] = new Port;
850 #ifdef CSL_DEBUG
851 logMsg("Scalable::add scale input");
852 #endif
853 }
854
855 Scalable::Scalable(float scale, float offset) {
856 this->addInput(CSL_SCALE, scale);
857 this->addInput(CSL_OFFSET, offset);
858 #ifdef CSL_DEBUG
859 logMsg("Scalable::add scale/offset input values");
860 #endif
861 }
862
863 Scalable::Scalable(UnitGenerator & scale, float offset) {
864 this->addInput(CSL_SCALE, scale);
865 this->addInput(CSL_OFFSET, offset);
866 #ifdef CSL_DEBUG
867 logMsg("Scalable::add scale/offset input values");
868 #endif
869 }
870
871 Scalable::Scalable(UnitGenerator & scale, UnitGenerator & offset) {
872 this->addInput(CSL_SCALE, scale);
873 this->addInput(CSL_OFFSET, offset);
874 #ifdef CSL_DEBUG
875 logMsg("Scalable::add scale/offset input values");
876 #endif
877 }
878
879 Scalable::~Scalable() {
880 // if (mInputs) {
881 //
882 // }
883 }
884
885 // Scalable -- Accessors
886
887 void Scalable::setScale(UnitGenerator & scale) {
888 this->addInput(CSL_SCALE, scale);
889 #ifdef CSL_DEBUG
890 logMsg("Scalable::set scale input UG");
891 #endif
892 }
893
894 void Scalable::setScale(float scale) {
895 this->addInput(CSL_SCALE, scale);
896 #ifdef CSL_DEBUG
897 logMsg("Scalable::set scale input value");
898 #endif
899 }
900
901 void Scalable::setOffset(UnitGenerator & offset) {
902 this->addInput(CSL_OFFSET, offset);
903 #ifdef CSL_DEBUG
904 logMsg("Scalable::set offset input UG");
905 #endif
906 }
907
908 void Scalable::setOffset(float offset) {
909 this->addInput(CSL_OFFSET, offset);
910 #ifdef CSL_DEBUG
911 logMsg("Scalable::set offset input value");
912 #endif
913 }
914
915 // trigger passed on here
916
917 void Scalable::trigger() {
918 if (mInputs[CSL_SCALE])
919 mInputs[CSL_SCALE]->trigger();
920 if (mInputs[CSL_OFFSET])
921 mInputs[CSL_OFFSET]->trigger();
922 }
923
924 // answer whether scale = 1 & offset = 0
925
926 //void isScaled() {
927 //
928 //}
929
930 /////////////////////////////////////////////////
931 //
932 // Effect implementation
933
934 Effect::Effect() : Controllable(), UnitGenerator() {
935 isInline = false;
936 // mInputs[CSL_INPUT] = new Port;
937 #ifdef CSL_DEBUG
938 logMsg("Effect::add null input");
939 #endif
940 }
941
942 Effect::Effect(UnitGenerator & input) : Controllable(), UnitGenerator() {
943 isInline = false;
944 mNumChannels = input.numChannels();
945 this->addInput(CSL_INPUT, input);
946 #ifdef CSL_DEBUG
947 logMsg("Effect::add input UG");
948 #endif
949 }
950
951 bool Effect::isActive() {
952 Port * iPort = mInputs[CSL_INPUT];
953 if (iPort)
954 return (iPort->isActive());
955 return true; // subclasses might not use mInputs[CSL_INPUT]
956 }
957
958 void Effect::setInput(UnitGenerator & input) {
959 isInline = false;
960 this->addInput(CSL_INPUT, input);
961 #ifdef CSL_DEBUG
962 logMsg("Effect::add input");
963 #endif
964 }
965
966 // Get my input's next buffer
967
968 void Effect::pullInput(Buffer & outputBuffer) throw (CException) {
969 #ifdef CSL_DEBUG
970 logMsg("Effect::pullInput");
971 #endif
972 if (isInline) // if inline, just use the input pointer
973 mInputPtr = outputBuffer.buffer(0);
974 else {
975 Port * iPort = mInputs[CSL_INPUT];
976 // else pull a buffer from my input
977 Controllable::pullInput(iPort, outputBuffer);
978
979 mInputPtr = outputBuffer.buffer(0);
980 }
981 }
982
983 void Effect::pullInput(unsigned numFrames) throw (CException) {
984 #ifdef CSL_DEBUG
985 logMsg("Effect::pullInput");
986 #endif
987 Port * iPort = mInputs[CSL_INPUT];
988 Controllable::pullInput(iPort, numFrames);
989 mInputPtr = iPort->mBuffer->buffer(0);
990 }
991
992 ///< trigger passed on here
993
994 void Effect::trigger() {
995 if (mInputs[CSL_INPUT])
996 mInputs[CSL_INPUT]->trigger();
997 }
998
999 // FanOut methods
1000
1001 FanOut::FanOut(UnitGenerator & in, unsigned taps)
1002 : Effect(in), mNumFanOuts(taps), mCurrent(taps) {
1003 #ifdef CSL_DEBUG
1004 logMsg("FanOut::FanOut %d", mNumFanOuts);
1005 #endif
1006 }
1007
1008 void FanOut::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
1009 throw LogicError("Asking for mono nextBuffer of a FanOut");
1010 }
1011
1012 // nextBuffer just pulls the input every "mOutputs" calls
1013
1014 void FanOut::nextBuffer(Buffer & outputBuffer) throw (CException) {
1015 if (outputBuffer.mNumChannels != mNumChannels)
1016 throw LogicError("Asking for wrong output ch # of a FanOut");
1017 if (mCurrent >= mNumFanOuts) {
1018 pullInput(outputBuffer.mNumFrames);
1019 mCurrent = 0;
1020 // logMsg(" reset");
1021 } // Copy the output buffer samples
1022 Buffer * buf = mInputs[CSL_INPUT]->mBuffer;
1023 outputBuffer.copyOnlySamplesFrom(*buf);
1024 // logMsg("FanOut %d", mCurrent);
1025 mCurrent++;
1026 }
1027
1028 // Splitter class -- a de-multiplexer for multi-channel signals
1029
1030 Splitter::Splitter(UnitGenerator & in)
1031 : FanOut(in, in.numChannels()) { }
1032
1033 void Splitter::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
1034 throw LogicError("Asking for mono nextBuffer of a Splitter");
1035 }
1036
1037 // Like for FanOut, next-buffer calls the input every mOutput calls,
1038 // but it only copies one channel at a time to the output
1039
1040 void Splitter::nextBuffer(Buffer & outputBuffer) throw (CException) {
1041 if (outputBuffer.mNumChannels != 1)
1042 throw LogicError("Asking for a stereo output of a channel splitter");
1043 // pull input
1044 if (mCurrent >= mNumFanOuts) {
1045 pullInput(outputBuffer.mNumFrames);
1046 mCurrent = 0;
1047 }
1048 Buffer * buf = mInputs[CSL_INPUT]->mBuffer;
1049 if (buf == 0)
1050 throw LogicError("Missing buffer in channel splitter");
1051 unsigned bufferByteSize = outputBuffer.mMonoBufferByteSize;
1052 SampleBuffer dest = outputBuffer.monoBuffer(0);
1053 SampleBuffer src = buf->monoBuffer(mCurrent);
1054 memcpy(dest, src, bufferByteSize);
1055 mCurrent++;
1056 }
1057
1058 // Joiner class -- a multiplexer for multi-channel signals
1059
1060 Joiner::Joiner(UnitGenerator & in1, UnitGenerator & in2) : Effect() {
1061 Controllable::addInput(0, in1);
1062 Controllable::addInput(1, in2);
1063 mNumChannels = 2;
1064 }
1065
1066 void Joiner::addInput(UnitGenerator & in) { ///< add the argument to vector of inputs
1067 Controllable::addInput(mNumChannels, in);
1068 mNumChannels++;
1069 }
1070
1071 bool Joiner::isActive() {
1072 for (unsigned i = 0; i < mNumChannels; i++) {
1073 if (mInputs[i]->mUGen->isActive())
1074 return true;
1075 }
1076 return false;
1077 }
1078
1079
1080 void Joiner::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
1081 throw LogicError("Asking for mono nextBuffer of a Joiner");
1082 }
1083
1084 // nextBuffer calls each of the input channels as a mono channel
1085
1086 void Joiner::nextBuffer(Buffer & outputBuffer) throw (CException) {
1087 if (outputBuffer.mNumChannels != mNumChannels) {
1088 throw LogicError("Wrong number of channels in a joiner");
1089 }
1090 // set up the fake mono buffer
1091 Buffer tempBuffer(1, outputBuffer.mNumFrames);
1092
1093 // loop through the mono inputs
1094 for (unsigned i = 0; i < mNumChannels; i++) {
1095 // put the mono in samples into 1 channel of the output
1096 tempBuffer.setBuffer(0, outputBuffer.monoBuffer(i));
1097 // get a buffer of mono samples from one of the inputs
1098 mInputs[i]->mUGen->nextBuffer(tempBuffer);
1099 }
1100 }
1101
1102 ///< trigger passed on here
1103
1104 void Joiner::trigger() {
1105 for (unsigned i = 0; i < mNumChannels; i++)
1106 mInputs[i]->trigger();
1107 }
1108
1109 // Writeable implementation
1110
1111 void Writeable::writeBuffer(Buffer & inputBuffer, unsigned bufNum) throw (CException) {
1112 // no-op here
1113 }
1114
1115 void Writeable::writeBuffer(Buffer & inputBuffer) throw (CException) {
1116 unsigned numBufs = inputBuffer.mNumChannels;
1117 for (unsigned i = 0; i < numBufs; i++)
1118 writeBuffer(inputBuffer, i);
1119 }
1120
1121 // Seekable
1122
1123 void Seekable::reset() throw (CException) { // reset-to-zero
1124 int pos = seekTo(0, kPositionStart);
1125 if (pos == 0)
1126 throw IOError("Error seeking");
1127 }
1128
1129 // Interleave = copy from CSL-style Buffer object to an interleaved sample vector
1130
1131 void Interleaver::interleave(Buffer & output, SampleBuffer samples,
1132 unsigned numFrames, unsigned numChannels) throw (CException) {
1133
1134 unsigned numOutputChannels = output.mNumChannels;
1135 unsigned numChannelsToInterleave = csl_min(numOutputChannels, numChannels);
1136 unsigned numChannelsBeyond = numChannels - numChannelsToInterleave;
1137
1138 for (unsigned frame = 0; frame < numFrames; frame++) {
1139 for (unsigned channel = 0; channel < numChannelsToInterleave; channel++)
1140 *samples++ = output.monoBuffer(channel)[frame];
1141 for (unsigned j = 0; j < numChannelsBeyond; j++)
1142 *samples++ = 0;
1143 }
1144 }
1145
1146 // Interleave, short * version
1147
1148 void Interleaver::interleave(Buffer & output, short * samples, unsigned numFrames,
1149 unsigned numChannels) throw (CException) {
1150
1151 unsigned numOutputChannels = output.mNumChannels;
1152 unsigned numChannelsToInterleave = csl_min(numOutputChannels, numChannels);
1153 unsigned numChannelsBeyond = numChannels - numChannelsToInterleave;
1154
1155 for (unsigned frame = 0; frame < numFrames; frame++) {
1156 for (unsigned channel = 0; channel < numChannelsToInterleave; channel++)
1157 *samples++ = (short) ((output.monoBuffer(channel)[frame]) * 32767.0);
1158 for (unsigned j = 0; j < numChannelsBeyond; j++)
1159 *samples++ = 0;
1160 }
1161 }
1162
1163 /// Remap = re-assign channels from the source buffer to the target while interleaving
1164
1165 void Interleaver::interleaveAndRemap(Buffer & output, SampleBuffer samples, unsigned numFrames,
1166 unsigned numChannels, unsigned *channelMap) throw (CException) {
1167
1168 unsigned numOutputChannels = output.mNumChannels;
1169 unsigned numChannelsToInterleave = csl_min(numOutputChannels, numChannels);
1170 unsigned numChannelsBeyond = numChannels - numChannelsToInterleave;
1171 unsigned *map = channelMap;
1172
1173 for (unsigned frame = 0; frame < numFrames; frame++) {
1174 for (unsigned channel = 0; channel < numChannelsToInterleave; channel++)
1175 *samples++ = output.monoBuffer(map[channel])[frame];
1176 for (unsigned j = 0; j < numChannelsBeyond; j++)
1177 *samples++ = 0;
1178 }
1179 }
1180
1181 // De-interleave = copy from interleaved SampleBuffer to CSL Buffer object
1182
1183 void Interleaver::deinterleave(Buffer & output, SampleBuffer samples, unsigned numFrames,
1184 unsigned numChannels) throw (CException) {
1185
1186 unsigned numOutputChannels = output.mNumChannels;
1187 unsigned numChannelsToDeinterleave = csl_min(numOutputChannels, numChannels);
1188 SampleBuffer currentOutputBuffer;
1189 SampleBuffer inputBuffer;
1190 unsigned i;
1191
1192 for (i = 0; i < numChannelsToDeinterleave; i++) {
1193 currentOutputBuffer = output.monoBuffer(i);
1194 inputBuffer = samples + i;
1195 for (unsigned j = 0; j < numFrames; j++, inputBuffer += numChannels) {
1196 *currentOutputBuffer++ = *inputBuffer;
1197 }
1198 }
1199 if (numOutputChannels > numChannelsToDeinterleave) {
1200 for (i = numChannelsToDeinterleave; i < numOutputChannels; i++)
1201 memset(output.monoBuffer(i), 0, output.mMonoBufferByteSize);
1202 }
1203 }
1204
1205 // De-interleave, short * version
1206
1207 void Interleaver::deinterleave(Buffer & output, short * samples, unsigned numFrames,
1208 unsigned numChannels) throw (CException) {
1209
1210 unsigned numOutputChannels = output.mNumChannels;
1211 unsigned numChannelsToDeinterleave = csl_min(numOutputChannels, numChannels);
1212 SampleBuffer currentOutputBuffer;
1213 short * inputBuffer;
1214 unsigned i;
1215
1216 for (i = 0; i < numChannelsToDeinterleave; i++) {
1217 currentOutputBuffer = output.monoBuffer(i);
1218 inputBuffer = samples + i;
1219 for (unsigned j = 0; j < numFrames; j++, inputBuffer += numChannels) {
1220 *currentOutputBuffer++ = ((float )*inputBuffer) / 32767.0f;
1221 }
1222 }
1223 if (numOutputChannels > numChannelsToDeinterleave) {
1224 for (i = numChannelsToDeinterleave; i < numOutputChannels; i++)
1225 memset(output.monoBuffer(i), 0, output.mMonoBufferByteSize);
1226 }
1227 }
1228
1229 //////////////////////////// IO class methods /////////////////////////////////
1230
1231 // Global array of all known IO devices
1232
1233 vector < IODevice *> gIODevices;
1234
1235 // General IO Constructors in all modes
1236
1237 IO::IO(unsigned s_rate, unsigned b_size, int in_device, int out_device,
1238 unsigned in_chans, unsigned out_chans)
1239 : mGraph(NULL), mNumFramesPlayed(0), mSequence(0),
1240 mLoggingPeriod(CGestalt::loggingPeriod()),
1241 mNumInChannels(in_chans), mNumOutChannels(out_chans),
1242 mNumRealInChannels(in_chans), mNumRealOutChannels(out_chans),
1243 mStatus(kIONew), mInterleaved(false) {
1244 logMsg("Create IO: %d s @ %d Hz; %d i %d o", b_size, s_rate, in_chans, out_chans);
1245 }
1246
1247 // set/clear the root generator
1248
1249 void IO::setRoot(UnitGenerator & root) {
1250 root.addOutput((UnitGenerator *) this);
1251 mGraph = & root;
1252 }
1253
1254 void IO::clearRoot() {
1255 if (mGraph != NULL)
1256 mGraph->removeOutput((UnitGenerator *) this);
1257 mGraph = NULL;
1258 }
1259
1260 // increment and answer my seq #
1261
1262 unsigned IO::getAndIncrementSequence() {
1263 mSequence++;
1264 return mSequence;
1265 }
1266
1267 // IO method to call a CSL client's DSP graph
1268
1269 void IO::pullInput(Buffer & outBuffer, SampleBuffer out) throw(CException) {
1270
1271 #ifdef DO_TIMING
1272 static struct timeval * mte = & mThen;
1273 static struct timeval * mno = & mNow;
1274 GET_TIME(mte);
1275 float maxSampEver = 0.0f;
1276 #endif
1277 // unsigned numFrames = outBuffer.mNumFrames;
1278 // unsigned numChans = outBuffer.mNumChannels;
1279
1280 if (mGraph) {
1281 try {
1282 outBuffer.mSequence = this->getAndIncrementSequence();
1283
1284 mGraph->nextBuffer(outBuffer); ////// call the graph's nextBuffer method //////
1285
1286 } catch (CException ex) {
1287 // handler: log error and play silence
1288 logMsg(kLogError, "An error occured in the CSL nextBuffer method: %s\n",
1289 ex.mMessage.c_str());
1290 // memset(out, 0, (numFrames * numChans * sizeof(sample)));
1291 }
1292 }
1293 #ifdef DO_TIMING
1294 GET_TIME(mno);
1295 printTimeStatistics(mno, mte, & mThisSec, & mTimeSum, & mTimeVals);
1296 #endif
1297 }
1298
1299 #ifdef CSL_WINDOWS
1300
1301 #ifdef DO_TIMING // DO_TIMING
1302
1303 int (timeval *val, void * e) {
1304 LARGE_INTEGER ticksPerSecond;
1305 LARGE_INTEGER tick; // A point in time
1306 // get the high resolution counter's accuracy
1307 QueryPerformanceFrequency(&ticksPerSecond);
1308 float ticksPerUSecond = ticksPerSecond.QuadPart / 1000000;
1309 // what time is it?
1310 QueryPerformanceCounter(&tick);
1311 val->tv_sec = tick.QuadPart/ticksPerSecond.QuadPart;
1312 val->tv_usec = tick.QuadPart/ticksPerUSecond;
1313 // cerr << "Fraction: " << val->tv_sec << "/" << val->tv_usec << " " << ticksPerUSecond << endl;
1314 return 0;
1315 }
1316 #endif
1317
1318 #endif
1319
1320 // IO Timing method
1321
1322 #ifdef DO_TIMING
1323 //#include "Mixer.h"
1324 //#include "Instrument.h"
1325 //extern std::vector<Instrument *> gInstLibrary;
1326
1327 void IO::printTimeStatistics(struct timeval * now, struct timeval * then, long * thisSec,
1328 long * timeSum, long * timeVals) {
1329
1330 if (now->tv_sec - * thisSec > (long) mLoggingPeriod) { // print stats once every so often
1331 *thisSec = now->tv_sec;
1332 if (*timeSum != 0.0) { // print and reset counters
1333 float cycleTime = (float) CGestalt::blockSize() * 1000000.0f / (float) CGestalt::frameRate();
1334 // remember % usage
1335 mUsage = (float) *timeSum / *timeVals * 100.0f / cycleTime;
1336 *timeVals = 0;
1337 *timeSum = 0;
1338 logMsg("\tCPU usage: %.2f percent (%5.3f).", mUsage, maxSampEver);
1339 // logMsg("\tIO: %d active clients", ((Mixer *) mGraph)->activeSources());
1340 // unsigned num_instruments = library.size();
1341 // for (unsigned i = 0; i < num_instruments; i++) {
1342 // Instrument * instr = library[i];
1343 // if (instr->graph()->isActive())
1344 // logMsg("\t\tInstrument %s.%d", instr->name().c_str(), i);
1345 // }
1346 }
1347 } else { // count blocks with active sounds and sum exec. times
1348 *timeVals += 1;
1349 *timeSum += SUB_TIMES(now, then);
1350 }
1351 // cerr << "here now/this: " << now->tvSec << " " << then->tvSec << endl;
1352 }
1353
1354 #endif
1355
1356 // Answer the most recent input buffer
1357
1358 Buffer & IO::getInput() throw(CException) {
1359 return getInput(mInputBuffer.mNumFrames, mInputBuffer.mNumChannels);
1360 }
1361
1362 // really get the desired format of input
1363
1364 Buffer & IO::getInput(unsigned numFrames, unsigned numChannels) throw(CException) {
1365 if (mNumInChannels == 0)
1366 throw IOError("Can't get unopened input");
1367 if (mInterleaved) {
1368 Interleaver interleaver;
1369 interleaver.deinterleave(mInputBuffer, mInputPointer, numFrames, numChannels);
1370 mInputBuffer.mIsPopulated = true;
1371 }
1372 return(mInputBuffer);
1373 }
1374
1375 // IO Device
1376
1377 IODevice::IODevice(char * name, unsigned index, unsigned maxIn, unsigned maxOut, bool isIn, bool isOut)
1378 : mIndex(index), mMaxInputChannels(maxIn), mMaxOutputChannels(maxOut),
1379 mIsDefaultIn(isIn), mIsDefaultOut(isOut) {
1380 strcpy(mName, name);
1381 }
1382
1383 IODevice::IODevice(string name, unsigned index, unsigned maxIn, unsigned maxOut, bool isIn, bool isOut)
1384 : mIndex(index), mMaxInputChannels(maxIn), mMaxOutputChannels(maxOut),
1385 mIsDefaultIn(isIn), mIsDefaultOut(isOut) {
1386 strcpy(mName, name.c_str());
1387 }
1388
1389 // pretty-print an IO Device
1390
1391 void IODevice::dump() {
1392 logMsg(" IO: %d = %s - %d i %d o %g Hz%s%s",
1393 mIndex,
1394 mName,
1395 mMaxInputChannels, mMaxOutputChannels,
1396 mFrameRate,
1397 (mIsDefaultIn ? " - def in" : ""),
1398 (mIsDefaultOut ? " - def out" : ""));
1399 }