pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plonk_Signal.h
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
 All Classes Functions Typedefs Enumerations Enumerator Properties