Cinder  0.8.6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Buffer.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2014, The Cinder Project
3 
4  This code is intended to be used with the Cinder C++ library, http://libcinder.org
5 
6  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
7  the following conditions are met:
8 
9  * Redistributions of source code must retain the above copyright notice, this list of conditions and
10  the following disclaimer.
11  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
12  the following disclaimer in the documentation and/or other materials provided with the distribution.
13 
14  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
15  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
16  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
17  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
18  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21  POSSIBILITY OF SUCH DAMAGE.
22 */
23 
24 #pragma once
25 
26 #include "cinder/CinderAssert.h"
27 
28 #include <vector>
29 #include <memory>
30 #include <cstdlib>
31 #include <algorithm>
32 
33 // TODO: It'd be nice to have a 'BufferView' or similar functionality
34 // - would not own the internal buffer, but would point to another one, with offset + size
35 // - alt. would be for BufferBaseT to take an alternate constructor
36 // - requires T* as data storage gain, which is also necessary to ensure 16byte alignment
37 
38 namespace cinder { namespace audio {
39 
41 template <typename T>
42 class BufferBaseT {
43  public:
45  typedef T SampleType;
46 
48  size_t getNumFrames() const { return mNumFrames; }
50  size_t getNumChannels() const { return mNumChannels; }
52  size_t getSize() const { return mNumFrames * mNumChannels; }
54  bool isEmpty() const { return mNumFrames == 0; }
56  T* getData() { return mData.data(); }
58  const T* getData() const { return mData.data(); }
59 
60  T& operator[]( size_t n )
61  {
62  CI_ASSERT( n < getSize() );
63  return mData[n];
64  }
65 
66  const T& operator[]( size_t n ) const
67  {
68  CI_ASSERT( n < getSize() );
69  return mData[n];
70  }
71 
73  void zero()
74  {
75  std::memset( mData.data(), 0, mData.size() * sizeof( T ) );
76  }
77 
78  protected:
79  BufferBaseT( size_t numFrames, size_t numChannels )
80  : mNumFrames( numFrames ), mNumChannels( numChannels ), mData( numFrames * numChannels )
81  {}
82 
83  std::vector<T> mData;
85 };
86 
88 template <typename T>
89 class BufferT : public BufferBaseT<T> {
90  public:
92  BufferT( size_t numFrames = 0, size_t numChannels = 1 )
93  : BufferBaseT<T>( numFrames, numChannels )
94  {}
95 
97  T* getChannel( size_t ch )
98  {
99  CI_ASSERT_MSG( ch < this->mNumChannels, "ch out of range" );
100  return &this->mData[ch * this->mNumFrames];
101  }
102 
104  const T* getChannel( size_t ch ) const
105  {
106  CI_ASSERT_MSG( ch < this->mNumChannels, "ch out of range" );
107  return &this->mData[ch * this->mNumFrames];
108  }
109 
110  using BufferBaseT<T>::zero;
111 
113  void zero( size_t startFrame, size_t numFrames )
114  {
115  CI_ASSERT( startFrame + numFrames <= this->mNumFrames );
116  for( size_t ch = 0; ch < this->mNumChannels; ch++ )
117  std::memset( &getChannel( ch )[startFrame], 0, numFrames * sizeof( T ) );
118  }
119 
121  void zeroChannel( size_t ch )
122  {
123  CI_ASSERT_MSG( ch < this->mNumChannels, "ch out of range" );
124  std::memset( getChannel( ch ), 0, this->getNumFrames() * sizeof( T ) );
125  }
126 
128  void copy( const BufferT<T> &other )
129  {
130  size_t numFrames = std::min( this->getNumFrames(), other.getNumFrames() );
131  size_t numChannels = std::min( this->getNumChannels(), other.getNumChannels() );
132 
133  for( size_t ch = 0; ch < numChannels; ch++ )
134  std::memmove( this->getChannel( ch ), other.getChannel( ch ), numFrames * sizeof( T ) );
135  }
136 
139  void copy( const BufferT<T> &other, size_t numFrames )
140  {
141  CI_ASSERT( this->getNumChannels() == other.getNumChannels() );
142  CI_ASSERT( numFrames <= this->getNumFrames() );
143  CI_ASSERT( numFrames <= other.getNumFrames() );
144 
145  for( size_t ch = 0; ch < this->getNumChannels(); ch++ )
146  std::memmove( this->getChannel( ch ), other.getChannel( ch ), numFrames * sizeof( T ) );
147  }
148 
151  void copyOffset( const BufferT<T> &other, size_t numFrames, size_t frameOffset, size_t otherFrameOffset )
152  {
153  CI_ASSERT( this->getNumChannels() == other.getNumChannels() );
154  CI_ASSERT( frameOffset + numFrames <= this->getNumFrames() );
155  CI_ASSERT( otherFrameOffset + numFrames <= other.getNumFrames() );
156 
157  for( size_t ch = 0; ch < this->getNumChannels(); ch++ )
158  std::memmove( this->getChannel( ch ) + frameOffset, other.getChannel( ch ) + otherFrameOffset, numFrames * sizeof( T ) );
159  }
160 
162  void copyChannel( size_t channel, const T *otherChannel )
163  {
164  CI_ASSERT_MSG( channel < this->getNumChannels(), "channel out of bounds" );
165  std::memmove( this->getChannel( channel ), otherChannel, this->getNumFrames() * sizeof( T ) );
166  }
167 };
168 
170 template <typename T>
171 class BufferInterleavedT : public BufferBaseT<T> {
172  public:
173  BufferInterleavedT( size_t numFrames = 0, size_t numChannels = 1 ) : BufferBaseT<T>( numFrames, numChannels ) {}
174 
175  using BufferBaseT<T>::zero;
176 
177  void zero( size_t startFrame, size_t numFrames )
178  {
179  CI_ASSERT( startFrame + numFrames <= this->mNumFrames );
180  std::memset( &this->mData[startFrame * this->mNumChannels], 0, numFrames * this->mNumChannels * sizeof( T ) );
181  }
182 };
183 
188 template <typename T>
189 class BufferSpectralT : public BufferT<T> {
190  public:
192  BufferSpectralT( size_t numFrames = 0 ) : BufferT<T>( numFrames / 2, 2 ) {}
193 
195  T* getReal() { return &this->mData[0]; }
197  const T* getReal() const { return &this->mData[0]; }
198 
200  T* getImag() { return &this->mData[this->mNumFrames]; }
202  const T* getImag() const { return &this->mData[this->mNumFrames]; }
203 };
204 
206 template <typename BufferTT>
207 class BufferDynamicT : public BufferTT {
208  public:
210  BufferDynamicT( size_t numFrames = 0, size_t numChannels = 1 ) : BufferTT( numFrames, numChannels ),
211  mAllocatedSize( numFrames * numChannels )
212  {}
213 
215  void setSize( size_t numFrames, size_t numChannels )
216  {
217  this->mNumFrames = numFrames;
218  this->mNumChannels = numChannels;
219  resizeIfNecessary();
220  }
221 
223  void setNumFrames( size_t numFrames )
224  {
225  this->mNumFrames = numFrames;
226  resizeIfNecessary();
227  }
228 
230  void setNumChannels( size_t numChannels )
231  {
232  this->mNumChannels = numChannels;
233  resizeIfNecessary();
234  }
235 
237  void shrinkToFit()
238  {
239  mAllocatedSize = this->getSize();
240  this->mData.resize( mAllocatedSize );
241  }
242 
244  size_t getAllocatedSize() const { return mAllocatedSize; }
245 
246  private:
247  void resizeIfNecessary()
248  {
249  size_t size = this->getSize();
250  if( mAllocatedSize < size ) {
251  mAllocatedSize = size;
252  this->mData.resize( mAllocatedSize );
253  }
254  }
255 
256  size_t mAllocatedSize;
257 };
258 
260 template<typename T>
261 struct FreeDeleter {
262  void operator()( T *x ) { std::free( x ); }
263 };
264 
266 template<typename T>
267 std::unique_ptr<T, FreeDeleter<T> > makeAlignedArray( size_t size, size_t alignment = 16 )
268 {
269  void *ptr = std::calloc( size, sizeof( T ) );
270 
271  // FIXME: broken on windows, this is returning NULL.
272  // unnecessary at the moment anyway, so it is commented out until fixed
273  //ptr = std::align( alignment, size, ptr, size );
274  //CI_ASSERT( ptr );
275 
276  return std::unique_ptr<T, FreeDeleter<T> >( static_cast<T *>( ptr ) );
277 }
278 
279 typedef std::unique_ptr<float, FreeDeleter<float> > AlignedArrayPtr;
280 typedef std::unique_ptr<double, FreeDeleter<double> > AlignedArrayPtrd;
281 
282 // ---------------------------------------------------------------------------------
283 // typedef's for the various flavors of Buffer's.
284 
288 
292 
293 typedef std::shared_ptr<Buffer> BufferRef;
294 typedef std::shared_ptr<BufferInterleaved> BufferInterleavedRef;
295 typedef std::shared_ptr<BufferSpectral> BufferSpectralRef;
296 typedef std::shared_ptr<BufferDynamic> BufferDynamicRef;
297 typedef std::shared_ptr<BufferDynamicInterleaved> BufferDynamicInterleavedRef;
298 typedef std::shared_ptr<BufferDynamicSpectral> BufferDynamicSpectralRef;
299 
300 } } // namespace cinder::audio
const T * getData() const
Returns a const pointer to the first sample in the data buffer.
Definition: Buffer.h:58
BufferDynamicT< BufferInterleaved > BufferDynamicInterleaved
Definition: Buffer.h:290
std::shared_ptr< Buffer > BufferRef
Definition: Buffer.h:293
T * getChannel(size_t ch)
Returns a pointer offset to the first sample of channel ch.
Definition: Buffer.h:97
cinder::Vec2i getSize()
Definition: AppCocoaTouch.mm:978
T * getReal()
Returns a pointer to the first sample in the real component channel.
Definition: Buffer.h:195
const T * getReal() const
Returns a const pointer to the first sample in the real component channel.
Definition: Buffer.h:197
void zero(size_t startFrame, size_t numFrames)
Assigns zero to numFrames frames starting at startFrame.
Definition: Buffer.h:113
BufferInterleavedT(size_t numFrames=0, size_t numChannels=1)
Definition: Buffer.h:173
void copy(const BufferT< T > &other, size_t numFrames)
Definition: Buffer.h:139
void copy(const BufferT< T > &other)
Copies min( this, other ) channels and frames from other to internal storage.
Definition: Buffer.h:128
const T * getChannel(size_t ch) const
Returns a const pointer offset to the first sample of channel ch.
Definition: Buffer.h:104
void shrinkToFit()
Shrinks the allocated size to match the specified size, freeing any extra memory. ...
Definition: Buffer.h:237
std::shared_ptr< BufferDynamic > BufferDynamicRef
Definition: Buffer.h:296
BufferInterleavedT< float > BufferInterleaved
Definition: Buffer.h:286
void setSize(size_t numFrames, size_t numChannels)
Sets the new size of the buffer to numFrames number of frames and numChannels number of channels...
Definition: Buffer.h:215
void zeroChannel(size_t ch)
Assigns zero to all samples in channel channel.
Definition: Buffer.h:121
BufferT(size_t numFrames=0, size_t numChannels=1)
Constructs a BufferT object with numFrames number of frames (default = 0) and numChannels number of c...
Definition: Buffer.h:92
std::shared_ptr< BufferInterleaved > BufferInterleavedRef
Definition: Buffer.h:294
BufferDynamicT< Buffer > BufferDynamic
Definition: Buffer.h:289
std::unique_ptr< T, FreeDeleter< T > > makeAlignedArray(size_t size, size_t alignment=16)
Returns an array of size elements of type T, aligned by alignment.
Definition: Buffer.h:267
#define min(a, b)
Definition: AppImplMsw.cpp:36
size_t mNumChannels
Definition: Buffer.h:84
size_t getNumChannels() const
Returns the number of channels in the buffer.
Definition: Buffer.h:50
void zero(size_t startFrame, size_t numFrames)
Definition: Buffer.h:177
size_t getNumFrames() const
Returns the number of frames in the buffer.
Definition: Buffer.h:48
void setNumFrames(size_t numFrames)
Sets the new number of frames in the buffer to numFrames. Will only resize of the new size (frames * ...
Definition: Buffer.h:223
size_t getSize() const
Returns the total size of the buffer (frames * channels).
Definition: Buffer.h:52
BufferSpectralT< float > BufferSpectral
Definition: Buffer.h:287
GLenum GLint x
Definition: GLee.h:987
std::unique_ptr< float, FreeDeleter< float > > AlignedArrayPtr
Definition: Buffer.h:279
GLenum GLsizei n
Definition: GLee.h:5780
void setNumChannels(size_t numChannels)
Sets the new number of channels in the buffer to numChannels. Will only resize of the new size (frame...
Definition: Buffer.h:230
Audio buffer that stores its channels of type T contiguously (ie. the first sample of channel 1 is di...
Definition: Buffer.h:89
T SampleType
The compile-time defined type of samples contained in the buffer.
Definition: Buffer.h:45
BufferDynamicT(size_t numFrames=0, size_t numChannels=1)
Constructs a BufferDynamicT object with numFrames number of frames (default = 0) and numChannels numb...
Definition: Buffer.h:210
void copyChannel(size_t channel, const T *otherChannel)
Copies otherChannel to the internal channel channel. Assumes there is at least getNumFrames() samples...
Definition: Buffer.h:162
BufferDynamicT< BufferSpectral > BufferDynamicSpectral
Definition: Buffer.h:291
void operator()(T *x)
Definition: Buffer.h:262
const T * getImag() const
Returns a const pointer to the first sample in the imaginary component channel.
Definition: Buffer.h:202
std::vector< T > mData
Definition: Buffer.h:83
BufferSpectralT(size_t numFrames=0)
Constructs a BufferSpectralT object of frames numFrames. There is always two channels, where channel 0 is the real component and 1 is the imaginary component.
Definition: Buffer.h:192
int int channel
Definition: GLee.h:17150
void zero()
Sets all samples to the value zero.
Definition: Buffer.h:73
T * getData()
Returns a pointer to the first sample in the data buffer.
Definition: Buffer.h:56
A resizable BufferT. The internally allocated buffer will grow as needed, but it will not shrink unle...
Definition: Buffer.h:207
A buffer that contains frequency domain audio data.
Definition: Buffer.h:189
std::shared_ptr< BufferSpectral > BufferSpectralRef
Definition: Buffer.h:295
const T & operator[](size_t n) const
Definition: Buffer.h:66
size_t getAllocatedSize() const
Returns the number of samples allocated in this buffer (may be larger than getSize()).
Definition: Buffer.h:244
size_t mNumFrames
Definition: Buffer.h:84
void copyOffset(const BufferT< T > &other, size_t numFrames, size_t frameOffset, size_t otherFrameOffset)
Definition: Buffer.h:151
BufferT< float > Buffer
Definition: Buffer.h:285
T * getImag()
Returns a pointer to the first sample in the imaginary component channel.
Definition: Buffer.h:200
Audio buffer that stores its channels of type T in one interleaved array (ie. the first sample of cha...
Definition: Buffer.h:171
std::shared_ptr< BufferDynamicSpectral > BufferDynamicSpectralRef
Definition: Buffer.h:298
BufferBaseT(size_t numFrames, size_t numChannels)
Definition: Buffer.h:79
Base class for the various Buffer classes. The template parameter T defined the sample type (precisio...
Definition: Buffer.h:42
GLsizeiptr size
Definition: GLee.h:2089
std::unique_ptr< double, FreeDeleter< double > > AlignedArrayPtrd
Definition: Buffer.h:280
bool isEmpty() const
Returns true if number of frames is zero, false otherwise.
Definition: Buffer.h:54
#define CI_ASSERT_MSG(expr, msg)
Definition: CinderAssert.h:76
std::shared_ptr< BufferDynamicInterleaved > BufferDynamicInterleavedRef
Definition: Buffer.h:297
#define CI_ASSERT(expr)
Definition: CinderAssert.h:75
Simple functor wrapping free(), suitable for unique_ptr's that allocate memory with malloc...
Definition: Buffer.h:261
T & operator[](size_t n)
Definition: Buffer.h:60