![]() |
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 #ifndef PLONK_SIGNAL_H 00040 #define PLONK_SIGNAL_H 00041 00042 #include "../core/plonk_CoreForwardDeclarations.h" 00043 #include "plonk_ContainerForwardDeclarations.h" 00044 #include "plonk_DynamicContainer.h" 00045 00046 #include "../core/plonk_SmartPointer.h" 00047 #include "../core/plonk_WeakPointer.h" 00048 #include "plonk_ObjectArray.h" 00049 #include "plonk_SimpleArray.h" 00050 00051 #include "../graph/utility/plonk_SampleRate.h" 00052 00053 00054 00055 template<class SampleType> 00056 class SignalInternal : public SmartPointer 00057 { 00058 public: 00059 typedef NumericalArray<SampleType> Buffer; 00060 typedef NumericalArray2D<SampleType> Buffers; 00061 typedef Variable<SampleType> SampleVariable; 00062 typedef NumericalArray<SampleVariable> SampleVariableArray; 00063 00064 inline SignalInternal() throw() 00065 : numInterleavedChannels (1) 00066 { 00067 init(); 00068 } 00069 00070 inline SignalInternal (Buffers const& buffersToUse, 00071 SampleRate const& sampleRateToUse) throw() 00072 : buffers (buffersToUse), 00073 sampleRate (sampleRateToUse), 00074 numInterleavedChannels (1) 00075 { 00076 plonk_assert ((buffers.length() == 1) || buffers.isMatrix()); // each channel must be the same length 00077 init(); 00078 } 00079 00080 inline SignalInternal (Buffer const& buffer, 00081 SampleRate const& sampleRateToUse, 00082 const int interleavedChannelsInBuffer) throw() 00083 : buffers (buffer), 00084 sampleRate (sampleRateToUse), 00085 numInterleavedChannels (interleavedChannelsInBuffer) 00086 { 00087 plonk_assert (numInterleavedChannels > 0); 00088 init(); 00089 } 00090 00091 inline int getNumFrames() const throw() 00092 { 00093 const int numFramesPerBuffer = buffers.numColumns(); 00094 return numFramesPerBuffer / numInterleavedChannels; 00095 } 00096 00097 inline int getNumChannels() const throw() 00098 { 00099 if (numInterleavedChannels > 1) 00100 { 00101 plonk_assert (buffers.numRows() == 1); 00102 return numInterleavedChannels; 00103 } 00104 else 00105 { 00106 return buffers.numRows(); 00107 } 00108 } 00109 00110 inline int getFrameStride() const throw() 00111 { 00112 return isInterleaved() ? getNumChannels() : 1; 00113 } 00114 00115 SampleType* getSamples (const int channel) throw() 00116 { 00117 const int wrappedChannel = plonk::wrap (channel, 0, getNumChannels()); 00118 return isInterleaved() 00119 ? 00120 buffers.atUnchecked (0).getArray() + wrappedChannel 00121 : 00122 buffers.atUnchecked (wrappedChannel).getArray(); 00123 } 00124 00125 const SampleType* getSamples (const int channel) const throw() 00126 { 00127 const int wrappedChannel = plonk::wrap (channel, 0, getNumChannels()); 00128 return isInterleaved() 00129 ? 00130 buffers.atUnchecked (0).getArray() + wrappedChannel 00131 : 00132 buffers.atUnchecked (wrappedChannel).getArray(); 00133 } 00134 00135 inline bool isInterleaved() const throw() 00136 { 00137 plonk_assert(buffers.length() > 0); 00138 return (numInterleavedChannels > 1) || (buffers.numRows() == 1); 00139 } 00140 00141 inline Buffer getInterleaved() const throw() 00142 { 00143 plonk_assert(buffers.length() > 0); 00144 return (isInterleaved()) ? buffers.atUnchecked (0) : buffers.interleave(); 00145 } 00146 00147 inline Buffers getDeinterleaved() const throw() 00148 { 00149 plonk_assert(buffers.length() > 0); 00150 if (isInterleaved()) 00151 return buffers.atUnchecked (0).deinterleave (numInterleavedChannels); 00152 else 00153 return buffers; 00154 } 00155 00156 friend class SignalBase<SampleType>; 00157 00158 private: 00159 Buffers buffers; 00160 SampleRate sampleRate; 00161 const int numInterleavedChannels; 00162 00163 SampleVariableArray sampleVariables; 00164 IntVariableArray intVariables; 00165 00166 void init() throw() 00167 { 00168 sampleVariables.setSize (buffers.length(), false); 00169 intVariables.setSize (buffers.length(), false); 00170 } 00171 }; 00172 00173 //------------------------------------------------------------------------------ 00174 00176 template<class SampleType> 00177 class SignalBase : public SmartPointerContainer< SignalInternal<SampleType> > 00178 { 00179 public: 00180 typedef SignalInternal<SampleType> Internal; 00181 typedef SmartPointerContainer<Internal> Base; 00182 typedef WeakPointerContainer<SignalBase> Weak; 00183 00184 typedef typename Internal::Buffer Buffer; 00185 typedef typename Internal::Buffers Buffers; 00186 typedef typename Internal::SampleVariable SampleVariable; 00187 typedef typename Internal::SampleVariableArray SampleVariableArray; 00188 00189 SignalBase() throw() 00190 : Base (new Internal ()) 00191 { 00192 } 00193 00194 SignalBase (Buffers const& buffers, 00195 SampleRate const& sampleRate = SampleRate::getDefault()) throw() 00196 : Base (new Internal (buffers, sampleRate)) 00197 { 00198 } 00199 00200 SignalBase (Buffer const& buffer, 00201 SampleRate const& sampleRate = SampleRate::getDefault(), 00202 const int interleavedChannelsInBuffer = 1) throw() 00203 : Base (new Internal (buffer, sampleRate, interleavedChannelsInBuffer)) 00204 { 00205 } 00206 00207 explicit SignalBase (Internal* internalToUse) throw() 00208 : Base (internalToUse) 00209 { 00210 } 00211 00212 SignalBase (SignalBase const& copy) throw() 00213 : Base (static_cast<Base const&> (copy)) 00214 { 00215 } 00216 00217 SignalBase (Dynamic const& other) throw() 00218 : Base (other.as<SignalBase>().getInternal()) 00219 { 00220 } 00221 00223 SignalBase& operator= (SignalBase const& other) throw() 00224 { 00225 if (this != &other) 00226 this->setInternal (other.getInternal());//this->setInternal (other.containerCopy().getInternal()); 00227 00228 return *this; 00229 } 00230 00234 static SignalBase fromWeak (Weak const& weak) throw() 00235 { 00236 return weak.fromWeak(); 00237 } 00238 00239 static const SignalBase& getNull() throw() 00240 { 00241 static SignalBase null; 00242 return null; 00243 } 00244 00245 inline const Buffers& getBuffers() const throw() 00246 { 00247 return this->getInternal()->buffers; 00248 } 00249 00250 inline Buffers& getBuffers() throw() 00251 { 00252 return this->getInternal()->buffers; 00253 } 00254 00255 inline const SampleRate& getSampleRate() const throw() 00256 { 00257 return this->getInternal()->sampleRate; 00258 } 00259 00260 inline SampleRate& getSampleRate() throw() 00261 { 00262 return this->getInternal()->sampleRate; 00263 } 00264 00265 inline int getNumFrames() const throw() 00266 { 00267 return this->getInternal()->getNumFrames(); 00268 } 00269 00270 inline int getNumChannels() const throw() 00271 { 00272 return this->getInternal()->getNumChannels(); 00273 } 00274 00275 inline int getFrameStride() const throw() 00276 { 00277 return this->getInternal()->getFrameStride(); 00278 } 00279 00280 SampleType* getSamples (const int channel) throw() 00281 { 00282 return this->getInternal()->getSamples (channel); 00283 } 00284 00285 const SampleType* getSamples (const int channel) const throw() 00286 { 00287 return this->getInternal()->getSamples (channel); 00288 } 00289 00290 inline bool isInterleaved() const throw() 00291 { 00292 return this->getInternal()->isInterleaved(); 00293 } 00294 00295 inline Buffer getInterleaved() const throw() 00296 { 00297 return this->getInternal()->getInterleaved(); 00298 } 00299 00300 inline Buffers getDeinterleaved() const throw() 00301 { 00302 return this->getInternal()->getDeinterleaved(); 00303 } 00304 00305 inline SampleVariableArray& getSampleVariables() throw() 00306 { 00307 return this->getInternal()->sampleVariables; 00308 } 00309 00310 inline const SampleVariableArray& getSampleVariables() const throw() 00311 { 00312 return this->getInternal()->sampleVariables; 00313 } 00314 00315 inline IntVariableArray& getIntVariables() throw() 00316 { 00317 return this->getInternal()->intVariables; 00318 } 00319 00320 inline const IntVariableArray& getIntVariables() const throw() 00321 { 00322 return this->getInternal()->intVariables; 00323 } 00324 00325 00326 PLONK_OBJECTARROWOPERATOR(SignalBase); 00327 00328 }; 00329 00330 00331 00332 #endif // PLONK_SIGNAL_H