![]() |
pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
|
00001 /* 00002 ------------------------------------------------------------------------------- 00003 This file is part of the Plink, Plonk, Plank libraries 00004 by Martin Robinson 00005 00006 http://code.google.com/p/pl-nk/ 00007 00008 Copyright University of the West of England, Bristol 2011-14 00009 All rights reserved. 00010 00011 Redistribution and use in source and binary forms, with or without 00012 modification, are permitted provided that the following conditions are met: 00013 00014 * Redistributions of source code must retain the above copyright 00015 notice, this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright 00017 notice, this list of conditions and the following disclaimer in the 00018 documentation and/or other materials provided with the distribution. 00019 * Neither the name of University of the West of England, Bristol nor 00020 the names of its contributors may be used to endorse or promote products 00021 derived from this software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00024 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00025 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00026 DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF THE WEST OF ENGLAND, BRISTOL BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 This software makes use of third party libraries. For more information see: 00035 doc/license.txt included in the distribution. 00036 ------------------------------------------------------------------------------- 00037 */ 00038 00039 #if PLANK_INLINING_FUNCTIONS 00040 00041 template<class SampleType> 00042 static inline int paCallback (const void *input, void *output, 00043 unsigned long frameCount, 00044 const PaStreamCallbackTimeInfo* timeInfo, 00045 PaStreamCallbackFlags statusFlags, 00046 void *userData) 00047 { 00048 PortAudioAudioHostBase<SampleType>* host = static_cast<PortAudioAudioHostBase<SampleType>*> (userData); 00049 return host->callback ((const SampleType**)input, (SampleType**)output, 00050 frameCount, timeInfo, statusFlags); 00051 } 00052 00053 static inline bool paCheckError (PaError err) 00054 { 00055 if (err != paNoError) 00056 { 00057 printf ("paerror '%s' (%d)\n", Pa_GetErrorText (err), err); 00058 return true; 00059 } 00060 00061 return false; 00062 } 00063 00064 //static inline void paGetInfo() 00065 //{ 00066 // const PaDeviceIndex inputDeviceId = Pa_GetDefaultInputDevice(); 00067 // const PaDeviceIndex outputDeviceId = Pa_GetDefaultOutputDevice(); 00068 // 00069 // const PaDeviceInfo* inputInfo = Pa_GetDeviceInfo (inputDeviceId); 00070 // const PaDeviceInfo* outputInfo = Pa_GetDeviceInfo (outputDeviceId); 00071 // 00072 // 00073 //} 00074 00075 //------------------------------------------------------------------------------ 00076 00077 template<class SampleType> 00078 PortAudioAudioHostBase<SampleType>::PortAudioAudioHostBase() throw() 00079 : stream (0) 00080 { 00081 PaError err; 00082 err = Pa_Initialize(); 00083 paCheckError (err); 00084 00085 this->setPreferredHostBlockSize (512); 00086 this->setPreferredGraphBlockSize (128); 00087 this->setPreferredHostSampleRate (44100.0); 00088 this->setNumInputs (1); 00089 this->setNumOutputs (2); 00090 } 00091 00092 template<class SampleType> 00093 PortAudioAudioHostBase<SampleType>::~PortAudioAudioHostBase() 00094 { 00095 if (stream) 00096 this->stopHost(); 00097 00098 PaError err; 00099 err = Pa_Terminate(); 00100 paCheckError (err); 00101 } 00102 00103 template<class SampleType> 00104 Text PortAudioAudioHostBase<SampleType>::getHostName() const throw() 00105 { 00106 return "PortAudio (" + TypeUtility<SampleType>::getTypeName() + ")"; 00107 } 00108 00109 template<class SampleType> 00110 Text PortAudioAudioHostBase<SampleType>::getNativeHostName() const throw() 00111 { 00112 const PaHostApiIndex paHostIndex = Pa_GetDefaultHostApi(); 00113 const PaHostApiInfo* info = Pa_GetHostApiInfo (paHostIndex); 00114 return info->name; 00115 } 00116 00117 template<class SampleType> 00118 Text PortAudioAudioHostBase<SampleType>::getInputName() const throw() 00119 { 00120 const PaDeviceIndex deviceId = Pa_GetDefaultInputDevice(); 00121 const PaDeviceInfo* info = Pa_GetDeviceInfo (deviceId); 00122 return info->name; 00123 } 00124 00125 template<class SampleType> 00126 Text PortAudioAudioHostBase<SampleType>::getOutputName() const throw() 00127 { 00128 const PaDeviceIndex deviceId = Pa_GetDefaultOutputDevice(); 00129 const PaDeviceInfo* info = Pa_GetDeviceInfo (deviceId); 00130 return info->name; 00131 } 00132 00133 template<class SampleType> 00134 double PortAudioAudioHostBase<SampleType>::getCpuUsage() const throw() 00135 { 00136 if (!stream) return 0.0; 00137 return Pa_GetStreamCpuLoad (stream); 00138 } 00139 00140 template<class SampleType> 00141 void PortAudioAudioHostBase<SampleType>::stopHost() throw() 00142 { 00143 PaError err; 00144 00145 err = Pa_StopStream (stream); 00146 paCheckError (err); 00147 00148 err = Pa_CloseStream (stream); 00149 paCheckError (err); 00150 00151 stream = NULL; 00152 this->setIsRunning (false); 00153 } 00154 00155 template<class SampleType> 00156 void PortAudioAudioHostBase<SampleType>::startHost() throw() 00157 { 00158 PaError err; 00159 00160 PaSampleFormat sampleFormat; 00161 00162 switch (TypeUtility<SampleType>::getTypeCode()) 00163 { 00164 case TypeCode::Float: sampleFormat = paFloat32; break; 00165 case TypeCode::Short: sampleFormat = paInt16; break; 00166 case TypeCode::Int: sampleFormat = paInt32; break; 00167 case TypeCode::Int24: sampleFormat = paInt24; break; 00168 case TypeCode::Char: sampleFormat = paInt8; break; 00169 default: sampleFormat = 0; break; 00170 } 00171 00172 if (sampleFormat != 0) 00173 { 00174 err = Pa_OpenDefaultStream (&stream, 00175 this->getNumInputs(), this->getNumOutputs(), 00176 sampleFormat | paNonInterleaved, 00177 this->getPreferredHostSampleRate(), this->getPreferredHostBlockSize(), 00178 paCallback<SampleType>, 00179 this); 00180 00181 // if our preferred sample rate and block size are invalid hopefully we get an error 00182 if (paCheckError (err)) 00183 return; 00184 00185 this->startHostInternal(); 00186 00187 err = Pa_StartStream (stream); 00188 paCheckError (err); 00189 } 00190 else plonk_assertfalse; 00191 } 00192 00193 template<class SampleType> 00194 int PortAudioAudioHostBase<SampleType>::callback (const SampleType **inputData, SampleType **outputData, 00195 unsigned long frameCount, 00196 const PaStreamCallbackTimeInfo* timeInfo, 00197 PaStreamCallbackFlags statusFlags) throw() 00198 { 00199 (void)timeInfo; 00200 (void)statusFlags; 00201 00202 this->setPreferredHostBlockSize ((int)frameCount); 00203 00204 ConstBufferArray& inputs = this->getInputs(); 00205 BufferArray& outputs = this->getOutputs(); 00206 00207 const int numInputs = inputs.length(); 00208 const int numOutputs = outputs.length(); 00209 00210 int i; 00211 00212 for (i = 0; i < numInputs; ++i) 00213 inputs.atUnchecked (i) = inputData[i]; 00214 00215 for (i = 0; i < numOutputs; ++i) 00216 outputs.atUnchecked (i) = outputData[i]; 00217 00218 this->process(); 00219 00220 return paContinue; 00221 } 00222 00223 00224 #if (defined(__OBJC__) && !PLONK_IOS)|| DOXYGEN 00225 END_PLONK_NAMESPACE 00226 00227 @class PLAudioHost; 00228 00229 using namespace plonk; 00230 00235 @protocol PLAudioHostDelegate <NSObject> 00236 @optional 00237 - (FloatUnit)constructGraphFloat:(PLAudioHost*)host; 00238 - (ShortUnit)constructGraphShort:(PLAudioHost*)host; 00239 - (IntUnit)constructGraphInt:(PLAudioHost*)host; 00240 - (DoubleUnit)constructGraphDouble:(PLAudioHost*)host; 00241 - (void)hostStarting:(PLAudioHost*)host; 00242 - (void)hostStopped:(PLAudioHost*)host; 00243 @end 00244 00245 00252 @interface PLAudioHost : NSObject 00253 { 00254 void* peer; 00255 id<PLAudioHostDelegate> delegate; 00256 int type; 00257 } 00258 00259 @property (nonatomic, assign) id delegate; 00260 @property (nonatomic, readonly) NSString* hostName; 00261 @property (nonatomic, readonly) NSString* nativeHostName; 00262 @property (nonatomic, readonly) NSString* inputName; 00263 @property (nonatomic, readonly) NSString* outputName; 00264 @property (nonatomic, readonly) double cpuUsage; 00265 @property (nonatomic, readonly) BOOL isRunning; 00266 @property (nonatomic, readonly) Dynamic outputUnit; 00267 @property (nonatomic) int numInputs; 00268 @property (nonatomic) int numOutputs; 00269 @property (nonatomic) int preferredHostBlockSize; 00270 @property (nonatomic) int preferredGraphBlockSize; 00271 @property (nonatomic) double preferredHostSampleRate; 00272 00274 - (void)startHost; 00275 00277 - (void)stopHost; 00278 00279 @end 00280 00281 BEGIN_PLONK_NAMESPACE 00282 00283 template<class SampleType> 00284 class PortAudioAudioHostPeerBase : public PortAudioAudioHostBase<SampleType> 00285 { 00286 public: 00287 typedef typename PortAudioAudioHostBase<SampleType>::UnitType UnitType; 00288 00289 PortAudioAudioHostPeerBase (PLAudioHost* p) 00290 : peer (p) 00291 { 00292 } 00293 00294 void hostStarting() throw() 00295 { 00296 if ([peer.delegate respondsToSelector:@selector(hostStarting:)]) 00297 [peer.delegate hostStarting:peer]; 00298 } 00299 00300 void hostStopped() throw() 00301 { 00302 if ([peer.delegate respondsToSelector:@selector(hostStopped:)]) 00303 [peer.delegate hostStopped:peer]; 00304 } 00305 00306 PLAudioHost* getPeer() const throw() { return peer; } 00307 00308 private: 00309 PLAudioHost* peer; // no need to retain as the Obj-C peer owns this object 00310 00311 PortAudioAudioHostPeerBase(); 00312 }; 00313 00315 template<class SampleType> 00316 class PortAudioAudioHostPeer : public PortAudioAudioHostPeerBase<SampleType> 00317 { 00318 public: 00319 // pure virtual constructGraph not implemented to cause a compile-time error 00320 // only float, short, int and double sample types are supported 00321 }; 00322 00323 template<> 00324 class PortAudioAudioHostPeer<float> : public PortAudioAudioHostPeerBase<float> 00325 { 00326 public: 00327 PortAudioAudioHostPeer (PLAudioHost* peer) 00328 : PortAudioAudioHostPeerBase<float> (peer) 00329 { 00330 } 00331 00332 FloatUnit constructGraph() throw() 00333 { 00334 PLAudioHost* const peer = this->getPeer(); 00335 plonk_assert (peer.delegate != nil); 00336 return [peer.delegate constructGraphFloat:peer]; 00337 } 00338 }; 00339 00340 template<> 00341 class PortAudioAudioHostPeer<short> : public PortAudioAudioHostPeerBase<short> 00342 { 00343 public: 00344 PortAudioAudioHostPeer (PLAudioHost* peer) 00345 : PortAudioAudioHostPeerBase<short> (peer) 00346 { 00347 } 00348 00349 ShortUnit constructGraph() throw() 00350 { 00351 PLAudioHost* const peer = this->getPeer(); 00352 plonk_assert (peer.delegate != nil); 00353 return [peer.delegate constructGraphShort:peer]; 00354 } 00355 }; 00356 00357 template<> 00358 class PortAudioAudioHostPeer<int> : public PortAudioAudioHostPeerBase<int> 00359 { 00360 public: 00361 PortAudioAudioHostPeer (PLAudioHost* peer) 00362 : PortAudioAudioHostPeerBase<int> (peer) 00363 { 00364 } 00365 00366 IntUnit constructGraph() throw() 00367 { 00368 PLAudioHost* const peer = this->getPeer(); 00369 plonk_assert (peer.delegate != nil); 00370 return [peer.delegate constructGraphInt:peer]; 00371 } 00372 }; 00373 00374 template<> 00375 class PortAudioAudioHostPeer<double> : public PortAudioAudioHostPeerBase<double> 00376 { 00377 public: 00378 PortAudioAudioHostPeer (PLAudioHost* peer) 00379 : PortAudioAudioHostPeerBase<double> (peer) 00380 { 00381 } 00382 00383 DoubleUnit constructGraph() throw() 00384 { 00385 PLAudioHost* const peer = this->getPeer(); 00386 plonk_assert (peer.delegate != nil); 00387 return [peer.delegate constructGraphInt:peer]; 00388 } 00389 }; 00390 00391 #if PLONK_AUDIOHOST_PORTAUDIO_COMPILEOBJC 00392 00393 END_PLONK_NAMESPACE 00394 00395 using namespace plonk; 00396 00397 @implementation PLAudioHost 00398 00399 - (id)init 00400 { 00401 if (self = [super init]) 00402 { 00403 peer = nil; 00404 type = TypeCode::Unknown; 00405 } 00406 00407 return self; 00408 } 00409 00410 - (void)dealloc 00411 { 00412 self.delegate = nil; 00413 00414 #if !__has_feature(objc_arc) 00415 [super dealloc]; 00416 #endif 00417 } 00418 00419 - (NSString*)hostName 00420 { 00421 if (peer == nil) return @""; 00422 00423 switch ((const int)type) 00424 { 00425 case TypeCode::Float: 00426 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<float>* > (peer)->getHostName().getArray()]; 00427 00428 case TypeCode::Short: 00429 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<short>* > (peer)->getHostName().getArray()]; 00430 00431 case TypeCode::Int: 00432 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<int>* > (peer)->getNativeHostName().getArray()]; 00433 00434 case TypeCode::Double: 00435 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<double>* > (peer)->getNativeHostName().getArray()]; 00436 00437 default: 00438 return @""; 00439 } 00440 } 00441 00442 - (NSString*)nativeHostName 00443 { 00444 if (peer == nil) return @""; 00445 00446 switch ((const int)type) 00447 { 00448 case TypeCode::Float: 00449 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<float>* > (peer)->getNativeHostName().getArray()]; 00450 00451 case TypeCode::Short: 00452 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<short>* > (peer)->getNativeHostName().getArray()]; 00453 00454 case TypeCode::Int: 00455 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<int>* > (peer)->getNativeHostName().getArray()]; 00456 00457 case TypeCode::Double: 00458 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<double>* > (peer)->getNativeHostName().getArray()]; 00459 00460 default: 00461 return @""; 00462 } 00463 } 00464 00465 - (NSString*)inputName 00466 { 00467 if (peer == nil) return @""; 00468 00469 switch ((const int)type) 00470 { 00471 case TypeCode::Float: 00472 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<float>* > (peer)->getInputName().getArray()]; 00473 00474 case TypeCode::Short: 00475 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<short>* > (peer)->getInputName().getArray()]; 00476 00477 case TypeCode::Int: 00478 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<int>* > (peer)->getInputName().getArray()]; 00479 00480 case TypeCode::Double: 00481 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<double>* > (peer)->getInputName().getArray()]; 00482 00483 default: 00484 return @""; 00485 } 00486 } 00487 00488 - (NSString*)outputName 00489 { 00490 if (peer == nil) return @""; 00491 00492 switch ((const int)type) 00493 { 00494 case TypeCode::Float: 00495 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<float>* > (peer)->getInputName().getArray()]; 00496 00497 case TypeCode::Short: 00498 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<short>* > (peer)->getInputName().getArray()]; 00499 00500 case TypeCode::Int: 00501 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<int>* > (peer)->getInputName().getArray()]; 00502 00503 case TypeCode::Double: 00504 return [NSString stringWithUTF8String: static_cast< PortAudioAudioHostPeer<double>* > (peer)->getInputName().getArray()]; 00505 00506 default: 00507 return @""; 00508 } 00509 } 00510 00511 - (double)cpuUsage 00512 { 00513 if (peer == nil) return 0.0; 00514 00515 switch ((const int)type) 00516 { 00517 case TypeCode::Float: return static_cast< PortAudioAudioHostPeer<float>* > (peer)->getCpuUsage(); 00518 case TypeCode::Short: return static_cast< PortAudioAudioHostPeer<short>* > (peer)->getCpuUsage(); 00519 case TypeCode::Int: return static_cast< PortAudioAudioHostPeer<int>* > (peer)->getCpuUsage(); 00520 case TypeCode::Double: return static_cast< PortAudioAudioHostPeer<double>* > (peer)->getCpuUsage(); 00521 default: return 0.0; 00522 } 00523 } 00524 00525 - (BOOL)isRunning 00526 { 00527 if (peer == nil) return NO; 00528 00529 switch ((const int)type) 00530 { 00531 case TypeCode::Float: return static_cast< PortAudioAudioHostPeer<float>* > (peer)->getIsRunning() ? YES : NO; 00532 case TypeCode::Short: return static_cast< PortAudioAudioHostPeer<short>* > (peer)->getIsRunning() ? YES : NO; 00533 case TypeCode::Int: return static_cast< PortAudioAudioHostPeer<int>* > (peer)->getIsRunning() ? YES : NO; 00534 case TypeCode::Double: return static_cast< PortAudioAudioHostPeer<double>* > (peer)->getIsRunning() ? YES : NO; 00535 default: return NO; 00536 } 00537 } 00538 00539 - (BOOL)isPaused 00540 { 00541 if (peer == nil) return NO; 00542 00543 switch ((const int)type) 00544 { 00545 case TypeCode::Float: return static_cast< PortAudioAudioHostPeer<float>* > (peer)->getIsPaused() ? YES : NO; 00546 case TypeCode::Short: return static_cast< PortAudioAudioHostPeer<short>* > (peer)->getIsPaused() ? YES : NO; 00547 case TypeCode::Int: return static_cast< PortAudioAudioHostPeer<int>* > (peer)->getIsPaused() ? YES : NO; 00548 case TypeCode::Double: return static_cast< PortAudioAudioHostPeer<double>* > (peer)->getIsPaused() ? YES : NO; 00549 default: return NO; 00550 } 00551 } 00552 00553 - (Dynamic)outputUnit 00554 { 00555 Dynamic dyn; 00556 00557 if (peer != nil) 00558 { 00559 switch ((const int)type) 00560 { 00561 case TypeCode::Float: dyn = static_cast< PortAudioAudioHostPeer<float>* > (peer)->getOutputUnit(); break; 00562 case TypeCode::Short: dyn = static_cast< PortAudioAudioHostPeer<short>* > (peer)->getOutputUnit(); break; 00563 case TypeCode::Int: dyn = static_cast< PortAudioAudioHostPeer<int>* > (peer)->getOutputUnit(); break; 00564 case TypeCode::Double: dyn = static_cast< PortAudioAudioHostPeer<double>* > (peer)->getOutputUnit(); break; 00565 default: { } 00566 } 00567 } 00568 00569 return dyn; 00570 } 00571 00572 - (int)numInputs 00573 { 00574 if (peer == nil) return 0; 00575 00576 switch ((const int)type) 00577 { 00578 case TypeCode::Float: return static_cast< PortAudioAudioHostPeer<float>* > (peer)->getNumInputs(); 00579 case TypeCode::Short: return static_cast< PortAudioAudioHostPeer<short>* > (peer)->getNumInputs(); 00580 case TypeCode::Int: return static_cast< PortAudioAudioHostPeer<int>* > (peer)->getNumInputs(); 00581 case TypeCode::Double: return static_cast< PortAudioAudioHostPeer<double>* > (peer)->getNumInputs(); 00582 default: return 0.0; 00583 } 00584 } 00585 00586 - (void)setNumInputs:(int)numInputs 00587 { 00588 if (peer == nil) return; 00589 00590 switch ((const int)type) 00591 { 00592 case TypeCode::Float: static_cast< PortAudioAudioHostPeer<float>* > (peer)->setNumInputs (numInputs); break; 00593 case TypeCode::Short: static_cast< PortAudioAudioHostPeer<short>* > (peer)->setNumInputs (numInputs); break; 00594 case TypeCode::Int: static_cast< PortAudioAudioHostPeer<int>* > (peer)->setNumInputs (numInputs); break; 00595 case TypeCode::Double: static_cast< PortAudioAudioHostPeer<double>* > (peer)->setNumInputs (numInputs); break; 00596 default: { } 00597 } 00598 } 00599 00600 - (int)numOutputs 00601 { 00602 if (peer == nil) return 0; 00603 00604 switch ((const int)type) 00605 { 00606 case TypeCode::Float: return static_cast< PortAudioAudioHostPeer<float>* > (peer)->getNumOutputs(); 00607 case TypeCode::Short: return static_cast< PortAudioAudioHostPeer<short>* > (peer)->getNumOutputs(); 00608 case TypeCode::Int: return static_cast< PortAudioAudioHostPeer<int>* > (peer)->getNumOutputs(); 00609 case TypeCode::Double: return static_cast< PortAudioAudioHostPeer<double>* > (peer)->getNumOutputs(); 00610 default: return 0.0; 00611 } 00612 } 00613 00614 - (void)setNumOutputs:(int)numOutputs 00615 { 00616 if (peer == nil) return; 00617 00618 switch ((const int)type) 00619 { 00620 case TypeCode::Float: static_cast< PortAudioAudioHostPeer<float>* > (peer)->setNumOutputs (numOutputs); break; 00621 case TypeCode::Short: static_cast< PortAudioAudioHostPeer<short>* > (peer)->setNumOutputs (numOutputs); break; 00622 case TypeCode::Int: static_cast< PortAudioAudioHostPeer<int>* > (peer)->setNumOutputs (numOutputs); break; 00623 case TypeCode::Double: static_cast< PortAudioAudioHostPeer<double>* > (peer)->setNumOutputs (numOutputs); break; 00624 default: { } 00625 } 00626 } 00627 00628 - (int)preferredHostBlockSize 00629 { 00630 if (peer == nil) return 0; 00631 00632 switch ((const int)type) 00633 { 00634 case TypeCode::Float: return static_cast< PortAudioAudioHostPeer<float>* > (peer)->getPreferredHostBlockSize(); 00635 case TypeCode::Short: return static_cast< PortAudioAudioHostPeer<short>* > (peer)->getPreferredHostBlockSize(); 00636 case TypeCode::Int: return static_cast< PortAudioAudioHostPeer<int>* > (peer)->getPreferredHostBlockSize(); 00637 case TypeCode::Double: return static_cast< PortAudioAudioHostPeer<double>* > (peer)->getPreferredHostBlockSize(); 00638 default: return 0; 00639 } 00640 } 00641 00642 - (void)setPreferredHostBlockSize:(int)preferredHostBlockSize 00643 { 00644 if (peer == nil) return; 00645 00646 switch ((const int)type) 00647 { 00648 case TypeCode::Float: static_cast< PortAudioAudioHostPeer<float>* > (peer)->setPreferredHostBlockSize (preferredHostBlockSize); break; 00649 case TypeCode::Short: static_cast< PortAudioAudioHostPeer<short>* > (peer)->setPreferredHostBlockSize (preferredHostBlockSize); break; 00650 case TypeCode::Int: static_cast< PortAudioAudioHostPeer<int>* > (peer)->setPreferredHostBlockSize (preferredHostBlockSize); break; 00651 case TypeCode::Double: static_cast< PortAudioAudioHostPeer<double>* > (peer)->setPreferredHostBlockSize (preferredHostBlockSize); break; 00652 default: { } 00653 } 00654 } 00655 00656 - (int)preferredGraphBlockSize 00657 { 00658 if (peer == nil) return 0; 00659 00660 switch ((const int)type) 00661 { 00662 case TypeCode::Float: return static_cast< PortAudioAudioHostPeer<float>* > (peer)->getPreferredGraphBlockSize(); 00663 case TypeCode::Short: return static_cast< PortAudioAudioHostPeer<short>* > (peer)->getPreferredGraphBlockSize(); 00664 case TypeCode::Int: return static_cast< PortAudioAudioHostPeer<int>* > (peer)->getPreferredGraphBlockSize(); 00665 case TypeCode::Double: return static_cast< PortAudioAudioHostPeer<double>* > (peer)->getPreferredGraphBlockSize(); 00666 default: return 0; 00667 } 00668 } 00669 00670 - (void)setPreferredGraphBlockSize:(int)preferredGraphBlockSize 00671 { 00672 if (peer == nil) return; 00673 00674 switch ((const int)type) 00675 { 00676 case TypeCode::Float: static_cast< PortAudioAudioHostPeer<float>* > (peer)->setPreferredGraphBlockSize (preferredGraphBlockSize); break; 00677 case TypeCode::Short: static_cast< PortAudioAudioHostPeer<short>* > (peer)->setPreferredGraphBlockSize (preferredGraphBlockSize); break; 00678 case TypeCode::Int: static_cast< PortAudioAudioHostPeer<int>* > (peer)->setPreferredGraphBlockSize (preferredGraphBlockSize); break; 00679 case TypeCode::Double: static_cast< PortAudioAudioHostPeer<double>* > (peer)->setPreferredGraphBlockSize (preferredGraphBlockSize); break; 00680 default: { } 00681 } 00682 } 00683 00684 - (double)preferredHostSampleRate 00685 { 00686 if (peer == nil) return 0.0; 00687 00688 switch ((const int)type) 00689 { 00690 case TypeCode::Float: return static_cast< PortAudioAudioHostPeer<float>* > (peer)->getPreferredHostSampleRate(); 00691 case TypeCode::Short: return static_cast< PortAudioAudioHostPeer<short>* > (peer)->getPreferredHostSampleRate(); 00692 case TypeCode::Int: return static_cast< PortAudioAudioHostPeer<int>* > (peer)->getPreferredHostSampleRate(); 00693 case TypeCode::Double: return static_cast< PortAudioAudioHostPeer<double>* > (peer)->getPreferredHostSampleRate(); 00694 default: return 0.0; 00695 } 00696 } 00697 00698 - (void)setPreferredHostSampleRate:(double)preferredHostSampleRate 00699 { 00700 if (peer == nil) return; 00701 00702 switch ((const int)type) 00703 { 00704 case TypeCode::Float: static_cast< PortAudioAudioHostPeer<float>* > (peer)->setPreferredHostSampleRate (preferredHostSampleRate); break; 00705 case TypeCode::Short: static_cast< PortAudioAudioHostPeer<short>* > (peer)->setPreferredHostSampleRate (preferredHostSampleRate); break; 00706 case TypeCode::Int: static_cast< PortAudioAudioHostPeer<int>* > (peer)->setPreferredHostSampleRate (preferredHostSampleRate); break; 00707 case TypeCode::Double: static_cast< PortAudioAudioHostPeer<double>* > (peer)->setPreferredHostSampleRate (preferredHostSampleRate); break; 00708 default: { } 00709 } 00710 } 00711 00712 - (void)startHost 00713 { 00714 if (peer == nil) return; 00715 00716 switch ((const int)type) 00717 { 00718 case TypeCode::Float: static_cast< PortAudioAudioHostPeer<float>* > (peer)->startHost(); break; 00719 case TypeCode::Short: static_cast< PortAudioAudioHostPeer<short>* > (peer)->startHost(); break; 00720 case TypeCode::Int: static_cast< PortAudioAudioHostPeer<int>* > (peer)->startHost(); break; 00721 case TypeCode::Double: static_cast< PortAudioAudioHostPeer<double>* > (peer)->startHost(); break; 00722 default: { } 00723 } 00724 } 00725 00726 - (void)stopHost 00727 { 00728 if (peer == nil) return; 00729 00730 switch ((const int)type) 00731 { 00732 case TypeCode::Float: static_cast< PortAudioAudioHostPeer<float>* > (peer)->stopHost(); break; 00733 case TypeCode::Short: static_cast< PortAudioAudioHostPeer<short>* > (peer)->stopHost(); break; 00734 case TypeCode::Int: static_cast< PortAudioAudioHostPeer<int>* > (peer)->stopHost(); break; 00735 case TypeCode::Double: static_cast< PortAudioAudioHostPeer<double>* > (peer)->stopHost(); break; 00736 default: { } 00737 } 00738 } 00739 00740 - (id)delegate 00741 { 00742 return delegate; 00743 } 00744 00745 - (void)deletePeer 00746 { 00747 switch ((const int)type) 00748 { 00749 case TypeCode::Float: delete static_cast< PortAudioAudioHostPeer<float>* > (peer); break; 00750 case TypeCode::Short: delete static_cast< PortAudioAudioHostPeer<short>* > (peer); break; 00751 case TypeCode::Int: delete static_cast< PortAudioAudioHostPeer<int>* > (peer); break; 00752 case TypeCode::Double: delete static_cast< PortAudioAudioHostPeer<double>* > (peer); break; 00753 default: { } 00754 } 00755 00756 peer = nil; 00757 type = TypeCode::Unknown; 00758 } 00759 00760 - (void)setDelegate:(id)newDelegate 00761 { 00762 plonk_assert (delegate == nil || newDelegate == nil); 00763 00764 [self deletePeer]; 00765 00766 delegate = newDelegate; 00767 00768 if (delegate) 00769 { 00770 const unsigned int isFloat = [delegate respondsToSelector:@selector(constructGraphFloat:)] ? (1 << TypeCode::Float) : 0; 00771 const unsigned int isShort = [delegate respondsToSelector:@selector(constructGraphShort:)] ? (1 << TypeCode::Short) : 0; 00772 const unsigned int isInt = [delegate respondsToSelector:@selector(constructGraphInt:)] ? (1 << TypeCode::Int) : 0; 00773 const unsigned int isDouble = [delegate respondsToSelector:@selector(constructGraphDouble:)] ? (1 << TypeCode::Double) : 0; 00774 const unsigned int typeFlags = isFloat | isShort | isInt | isDouble; 00775 00776 if (typeFlags != 0 && Bits::isPowerOf2 (typeFlags)) 00777 { 00778 type = Bits::countTrailingZeroes (typeFlags); 00779 00780 switch ((const int)type) 00781 { 00782 case TypeCode::Float: peer = new PortAudioAudioHostPeer<float> (self); break; 00783 case TypeCode::Short: peer = new PortAudioAudioHostPeer<short> (self); break; 00784 case TypeCode::Int: peer = new PortAudioAudioHostPeer<int> (self); break; 00785 case TypeCode::Double: peer = new PortAudioAudioHostPeer<double> (self); break; 00786 00787 default: 00788 peer = nil; 00789 type = 0; 00790 } 00791 } 00792 else plonk_assertfalse; // either none or more than one constructGraph.. function was implemented 00793 } 00794 } 00795 00796 @end 00797 00798 BEGIN_PLONK_NAMESPACE 00799 #endif 00800 00801 #endif 00802 00803 00804 #endif // PLANK_INLINING_FUNCTIONS 00805