pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plonk_QueueChannel.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_QUEUECHANNEL_H
00040 #define PLONK_QUEUECHANNEL_H
00041 
00042 #include "../channel/plonk_ChannelInternalCore.h"
00043 #include "../plonk_GraphForwardDeclarations.h"
00044 
00045 
00046 template<class SampleType> class QueueChannelInternal;
00047 
00048 PLONK_CHANNELDATA_DECLARE(QueueChannelInternal,SampleType)
00049 {
00050     ChannelInternalCore::Data base;
00051     int preferredNumChannels;
00052 };
00053 
00054 
00056 template<class SampleType>
00057 class QueueChannelInternal
00058 :   public ProxyOwnerChannelInternal<SampleType, PLONK_CHANNELDATA_NAME(QueueChannelInternal,SampleType)>
00059 {
00060 public:
00061     typedef PLONK_CHANNELDATA_NAME(QueueChannelInternal,SampleType)             Data;
00062     typedef ChannelBase<SampleType>                                             ChannelType;
00063     typedef ObjectArray<ChannelType>                                            ChannelArrayType;
00064     typedef ProxyOwnerChannelInternal<SampleType,Data>                          Internal;
00065     typedef UnitBase<SampleType>                                                UnitType;
00066     typedef InputDictionary                                                     Inputs;
00067     typedef NumericalArray<SampleType>                                          Buffer;
00068     typedef LockFreeQueue<UnitType>                                             QueueType;
00069     
00070     QueueChannelInternal (Inputs const& inputs,
00071                           Data const& data,
00072                           BlockSize const& blockSize,
00073                           SampleRate const& sampleRate,
00074                           ChannelArrayType& channels) throw()
00075     :   Internal (data.preferredNumChannels > 0 ? data.preferredNumChannels : inputs.getMaxNumChannels(),
00076                   inputs, data, blockSize, sampleRate, channels)
00077     {
00078         QueueType& queue = this->getInputAsUnitQueue (IOKey::UnitQueue);
00079         currentUnit = queue.pop();
00080     }
00081     
00082     Text getName() const throw()
00083     {
00084         return "Queue";
00085     }
00086     
00087     IntArray getInputKeys() const throw()
00088     {
00089         const IntArray keys (IOKey::UnitQueue);
00090         return keys;
00091     }
00092     
00093     void initChannel (const int channel) throw()
00094     {
00095         if ((channel % this->getNumChannels()) == 0)
00096         {
00097             // should look at the initial array in case no preference was given really...
00098             this->setBlockSize (BlockSize::decide (BlockSize::getDefault(),
00099                                                    this->getBlockSize()));
00100             this->setSampleRate (SampleRate::decide (SampleRate::getDefault(),
00101                                                      this->getSampleRate()));
00102         }
00103     
00104         this->initProxyValue (channel, currentUnit.getValue (channel));
00105     }
00106     
00107     void process (ProcessInfo& info, const int /*channel*/) throw()
00108     {
00109         const Data& data = this->getState();
00110                 
00111         const int numChannels = this->getNumChannels();
00112         int i, channel;
00113         
00114         for (channel = 0; channel < numChannels; ++channel)
00115         {
00116             const Buffer& inputBuffer (currentUnit.process (info, channel));
00117             const SampleType* const inputSamples = inputBuffer.getArray();
00118             const int inputBufferLength = inputBuffer.length();
00119             
00120             Buffer& outputBuffer = this->getOutputBuffer (channel);
00121             SampleType* const outputSamples = outputBuffer.getArray();
00122             const int outputBufferLength = outputBuffer.length();
00123             
00124             if (inputBufferLength == outputBufferLength)
00125             {
00126                 Buffer::copyData (outputSamples, inputSamples, outputBufferLength);
00127             }
00128             else if (inputBufferLength == 1)
00129             {
00130                 NumericalArrayFiller<SampleType>::fill (outputSamples, inputSamples[0], outputBufferLength);
00131             }
00132             else
00133             {
00134                 double inputPosition = 0.0;
00135                 const double inputIncrement = double (inputBufferLength) / double (outputBufferLength);
00136                 
00137                 for (i = 0; i < outputBufferLength; ++i)
00138                 {
00139                     outputSamples[i] += inputSamples[int (inputPosition)];
00140                     inputPosition += inputIncrement;
00141                 }
00142             }
00143             
00144             if (info.getShouldDelete())
00145             {
00146                 QueueType& queue = this->getInputAsUnitQueue (IOKey::UnitQueue);
00147                 currentUnit = queue.pop();
00148                 info.resetShouldDelete();
00149             }
00150         }
00151     }
00152     
00153 private:
00154     UnitType currentUnit;
00155 };
00156 
00157 
00158 //------------------------------------------------------------------------------
00159 
00174 template<class SampleType>
00175 class QueueUnit
00176 {
00177 public:    
00178     typedef QueueChannelInternal<SampleType>        QueueInternal;
00179     typedef typename QueueInternal::Data            Data;
00180     typedef ChannelBase<SampleType>                 ChannelType;
00181     typedef ChannelInternal<SampleType,Data>        Internal;
00182     typedef ChannelInternalBase<SampleType>         InternaBase;
00183     typedef UnitBase<SampleType>                    UnitType;
00184     typedef InputDictionary                         Inputs;
00185     typedef NumericalArray<SampleType>              Buffer;
00186     typedef NumericalArray2D<SampleType>            BufferArray;
00187     typedef LockFreeQueue<UnitType>                 QueueType;
00188 
00189     
00190 //    static inline UnitInfos getInfo() throw()
00191 //    {
00192 //        const double blockSize = (double)BlockSize::getDefault().getValue();
00193 //        const double sampleRate = SampleRate::getDefault().getValue();
00194 //
00195 //        return UnitInfo ("Queue", "Plays a queue of units in sequence.",
00196 //                         
00197 //                         // output
00198 //                         1, 
00199 //                         IOKey::Generic,     Measure::None,      IOInfo::NoDefault,  IOLimit::None, 
00200 //                         IOKey::End,
00201 //                         
00202 //                         // inputs
00203 //                         IOKey::Buffer,         Measure::None,
00204 //                         IOKey::OverlapMake,    Measure::Factor,    0.5,        IOLimit::Clipped, Measure::NormalisedUnipolar,  0.0, 1.0,
00205 //                         IOKey::BlockSize,      Measure::Samples,   blockSize,  IOLimit::Minimum, Measure::Samples,             1.0,
00206 //                         IOKey::SampleRate,     Measure::Hertz,     sampleRate, IOLimit::Minimum, Measure::Hertz,               0.0,
00207 //                         IOKey::End);
00208 //    }    
00209     
00211     static inline UnitType ar (QueueType const& queue,
00212                                const int preferredNumChannels = 0,
00213                                BlockSize const& preferredBlockSize = BlockSize::getDefault(),
00214                                SampleRate const& preferredSampleRate = SampleRate::getDefault()) throw()
00215     {        
00216         Inputs inputs;
00217         inputs.put (IOKey::UnitQueue, queue);
00218         
00219         Data data = { { -1.0, -1.0 }, preferredNumChannels };
00220         
00221         return UnitType::template proxiesFromInputs<QueueInternal> (inputs,
00222                                                                     data,
00223                                                                     preferredBlockSize,
00224                                                                     preferredSampleRate);
00225     }
00226     
00227     static inline UnitType kr (QueueType const& queue,                                
00228                                const int preferredNumChannels = 0) throw()
00229     {
00230         return ar (queue, 
00231                    preferredNumChannels,
00232                    BlockSize::getControlRateBlockSize(),
00233                    SampleRate::getControlRate());
00234     }
00235       
00236 };
00237 
00238 typedef QueueUnit<PLONK_TYPE_DEFAULT> Queue;
00239 
00240 
00241 
00242 
00243 #endif // PLONK_BLOCKCHANNEL_H
00244 
00245 
 All Classes Functions Typedefs Enumerations Enumerator Properties