![]() |
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_WAVETABLE_H 00040 #define PLONK_WAVETABLE_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 00053 template<class SampleType> 00054 class WavetableBase : private NumericalArray<SampleType> 00055 { 00056 public: 00057 typedef NumericalArray<SampleType> Buffer; 00058 00059 WavetableBase() throw() 00060 { 00061 } 00062 00063 WavetableBase (Buffer const& buffer) throw() 00064 : Buffer (Buffer::withSize (buffer.length() * 2, false)) 00065 { 00066 const int bufferLength = buffer.length(); 00067 plonk_assert (bufferLength > 0); 00068 00069 const SampleType* const bufferSamples = buffer.getArray(); 00070 SampleType* tableSamples = Buffer::getArray(); 00071 00072 int i; 00073 00074 // copy twice (could probably get away with copying just the first four samples 00075 // for most interpolation techniques) 00076 00077 for (i = 0; i < bufferLength; ++i) 00078 *tableSamples++ = bufferSamples[i]; 00079 00080 for (i = 0; i < bufferLength; ++i) 00081 *tableSamples++ = bufferSamples[i]; 00082 } 00083 00086 WavetableBase (WavetableBase const& copy) throw() 00087 : Buffer (static_cast<Buffer const&> (copy)) 00088 { 00089 } 00090 00091 WavetableBase (Dynamic const& other) throw() 00092 : Buffer (other.as<WavetableBase>().getInternal()) 00093 { 00094 } 00095 00097 WavetableBase& operator= (WavetableBase const& other) throw() 00098 { 00099 if (this != &other) 00100 this->setInternal (other.getInternal());//this->setInternal (other.containerCopy().getInternal()); 00101 00102 return *this; 00103 } 00104 00105 // using Buffer::containerCopy; 00106 using Buffer::getInternal; 00107 00108 int length() const throw() 00109 { 00110 return Buffer::length() / 2; 00111 } 00112 00113 int size() const throw() 00114 { 00115 return Buffer::size(); 00116 } 00117 00118 const SampleType* getArray() const throw() 00119 { 00120 return Buffer::getArray(); 00121 } 00122 00123 SampleType operator[] (const int index) const throw() 00124 { 00125 if ((index < 0) || (index >= this->length())) 00126 return SampleType (0); 00127 else 00128 return this->getArray()[index]; 00129 } 00130 00131 SampleType atUnchecked (const int index) const throw() 00132 { 00133 plonk_assert ((index >= 0) && (index < this->length())); 00134 return this->getArray()[index]; 00135 } 00136 00137 void put (const int index, SampleType const& value) throw() 00138 { 00139 const int tableLength = this->length(); 00140 plonk_assert ((index >= 0) && (index < tableLength)); 00141 SampleType* const tableSamples = Buffer::getArray(); 00142 tableSamples[index] = value; 00143 tableSamples[index + tableLength] = value; 00144 } 00145 00146 WavetableBase& normalise() throw() 00147 { 00148 Buffer::normalise(); 00149 return *this; 00150 } 00151 00152 static WavetableBase sineTable (const int size, const double repeats = 1.0) throw() 00153 { 00154 return WavetableBase (Buffer::sineTable (size, repeats)); 00155 } 00156 00158 static WavetableBase cosineTable (const int size, const double repeats = 1.0) throw() 00159 { 00160 return WavetableBase (Buffer::cosineTable (size, repeats)); 00161 } 00162 00164 static WavetableBase cosineWindow (const int size, const double repeats = 1.0) throw() 00165 { 00166 return WavetableBase (Buffer::cosineWindow (size, repeats)); 00167 } 00168 00170 static WavetableBase triangleWindow (const int size) throw() 00171 { 00172 return WavetableBase (Buffer::triangleWindow (size)); 00173 } 00174 00176 static WavetableBase bartlettWindow (const int size) throw() 00177 { 00178 return WavetableBase (Buffer::bartlettWindow (size)); 00179 } 00180 00182 static WavetableBase hannWindow (const int size) throw() 00183 { 00184 return WavetableBase (Buffer::hannWindow (size)); 00185 } 00186 00188 static WavetableBase hammingWindow (const int size) throw() 00189 { 00190 return WavetableBase (Buffer::hammingWindow (size)); 00191 } 00192 00194 static WavetableBase blackmanWindow (const int size, const double alpha = 0.16) throw() 00195 { 00196 return WavetableBase (Buffer::blackmanWindow (size, alpha)); 00197 } 00198 00199 static const WavetableBase& sine512() throw() 00200 { 00201 static const WavetableBase table (Buffer::sineTable (512, 1.0)); 00202 return table; 00203 } 00204 00205 static const WavetableBase& sine8192() throw() 00206 { 00207 static const WavetableBase table (Buffer::sineTable (8192, 1.0)); 00208 return table; 00209 } 00210 00211 static const WavetableBase& cosine512() throw() 00212 { 00213 static const WavetableBase table (Buffer::cosineTable (512, 1.0)); 00214 return table; 00215 } 00216 00217 static const WavetableBase& cosine8192() throw() 00218 { 00219 static const WavetableBase table (Buffer::cosineTable (8192, 1.0)); 00220 return table; 00221 } 00222 00223 static WavetableBase harmonic (const int size, Buffer const& weights) throw() 00224 { 00225 return WavetableBase (Buffer::harmonicTable (size, weights)); 00226 } 00227 00228 static WavetableBase harmonic8192 (Buffer const& weights) throw() 00229 { 00230 return WavetableBase (Buffer::harmonicTable (8192, weights)); 00231 } 00232 00233 static const WavetableBase& harmonicSaw() throw() 00234 { 00235 static const WavetableBase table (WavetableBase::harmonic8192 (Buffer::series (21, 1, 1) 00236 .reciprocal() 00237 .normalise())); 00238 return table; 00239 } 00240 00241 static WavetableBase harmonicSaw (const int size, const int numHarmonics = 21) throw() 00242 { 00243 return WavetableBase::harmonic (size, Buffer::series (numHarmonics, 1, 1) 00244 .reciprocal().normalise()); 00245 } 00246 00247 static const WavetableBase& harmonicSquare() throw() 00248 { 00249 static const WavetableBase table (WavetableBase::harmonic8192 ((Buffer::series (21, 1, 1).reciprocal() * Buffer (SampleType (1), SampleType (0))) 00250 .normalise())); 00251 return table; 00252 } 00253 00254 static WavetableBase harmonicSquare (const int size, const int numHarmonics = 21) throw() 00255 { 00256 plonk_assert (numHarmonics >= 2); 00257 return WavetableBase::harmonic (size, (Buffer::series (numHarmonics, 1, 1).reciprocal() * Buffer (SampleType (1), SampleType (0))) 00258 .normalise()); 00259 } 00260 00261 static const WavetableBase& harmonicTri() throw() 00262 { 00263 static const WavetableBase table (WavetableBase::harmonic8192 ((Buffer::series (21, 1, 1).reciprocal() * Buffer (SampleType (1), SampleType (0), SampleType (-1), SampleType (0))) 00264 .squared() 00265 .normalise())); 00266 return table; 00267 } 00268 00269 static WavetableBase harmonicTri (const int size, const int numHarmonics = 21) throw() 00270 { 00271 plonk_assert (numHarmonics >= 4); 00272 return WavetableBase::harmonic (size, (Buffer::series (numHarmonics, 1, 1).reciprocal() * Buffer (SampleType (1), SampleType (0), SampleType (-1), SampleType (0))) 00273 .squared() 00274 .normalise()); 00275 } 00276 00277 00278 PLONK_OBJECTARROWOPERATOR(WavetableBase); 00279 00280 }; 00281 00282 #endif // PLONK_WAVETABLE_H