ape  0.5.0
Audio Programming Environment
misc.h
Go to the documentation of this file.
1 #ifndef CPPAPE_MISC_H
2 #define CPPAPE_MISC_H
3 
4 #include <cstdint>
5 #include <vector>
6 #include <assert.h>
7 #include <type_traits>
8 
9 #include "interpolation.h"
10 
11 namespace ape
12 {
23  template<typename T>
24  struct uarray
25  {
26  public:
27 
31  typedef T value_type;
32 
36  uarray(std::vector<T>& source) : uarray(source.data(), source.size()) {}
40  uarray(const std::vector<typename std::remove_const_t<T>>& source) : uarray(source.data(), source.size()) {}
44  uarray(T* buffer, std::size_t length)
45  : buffer(buffer), length(length)
46  {
47 #ifndef CPPAPE_RELEASE
48  assert(buffer);
49 #endif
50  }
54  uarray(T* begin, T* end)
55  : buffer(begin), length(end - begin)
56  {
57 #ifndef CPPAPE_RELEASE
58  assert(begin);
59  assert(end);
60 #endif
61  }
62 
66  T& operator [] (std::size_t index)
67  {
68 #ifndef CPPAPE_RELEASE
69  assert(index < length);
70 #endif
71  return buffer[index];
72  }
73 
77  const T& operator [] (std::size_t index) const
78  {
79 #ifndef CPPAPE_RELEASE
80  assert(index < length);
81 #endif
82  return buffer[index];
83  }
84 
88  T* begin() noexcept { return buffer; }
92  const T* begin() const noexcept { return buffer; }
96  T* end() noexcept { return buffer + length; }
100  const T* end() const noexcept { return buffer + length; }
104  T* data() noexcept { return buffer; }
108  const T* data() const noexcept { return buffer; }
109 
113  std::size_t size() const noexcept { return length; }
114 
126  uarray<T> slice(std::size_t offset, std::size_t newLength = -1) noexcept
127  {
128  assert(offset <= length);
129  if (newLength == -1)
130  newLength = length - offset;
131 
132  assert((offset + newLength) <= length);
133  return { buffer + offset, newLength };
134  }
135 
136  template<typename Other>
137  typename std::enable_if<std::is_standard_layout<Other>::value && !std::is_const<T>::value, uarray<Other>>::type
138  reinterpret() noexcept
139  {
140  static_assert((sizeof(T) / sizeof(Other)) * sizeof(Other) == sizeof(T), "Other is not divisble by T");
141  static_assert(alignof(T) <= alignof(Other), "Other is less aligned than T");
142 
143  constexpr auto ratio = sizeof(T) / sizeof(Other);
144 
145  return { reinterpret_cast<Other*>(buffer), length * ratio };
146  }
147 
148  template<typename Other>
149  typename std::enable_if<std::is_standard_layout<Other>::value && std::is_const<T>::value, uarray<const Other>>::type
150  reinterpret() const noexcept
151  {
152  static_assert((sizeof(T) / sizeof(Other)) * sizeof(Other) == sizeof(T), "Other is not divisble by T");
153  static_assert(alignof(T) <= alignof(Other), "Other is less aligned than T");
154 
155  constexpr auto ratio = sizeof(T) / sizeof(Other);
156 
157  return { reinterpret_cast<const Other*>(buffer), length * ratio };
158  }
159 
171  uarray<const T> slice(std::size_t offset, std::size_t newLength = -1) const noexcept
172  {
173  assert(offset <= length);
174 
175  if (newLength == -1)
176  newLength = length - offset;
177 
178  assert((offset + newLength) <= length);
179  return { buffer + offset, newLength };
180  }
181 
182 
186  operator uarray<const T>() const noexcept
187  {
188  return { begin(), end() };
189  }
190 
191  private:
192 
193  T* const buffer;
194  const std::size_t length;
195  };
196 
211  template<typename T>
212  struct umatrix
213  {
214  public:
215 
216  typedef T value_type;
217 
225  struct iterator
226  {
227  typedef std::ptrdiff_t difference_type;
228  typedef T value_type;
229  typedef value_type* pointer;
231  typedef std::bidirectional_iterator_tag iterator_category;
232 
233  iterator(umatrix<T> matrix, std::size_t row = 0)
234  : source(matrix), row(row)
235  {
236 
237  }
238 
240  {
241  row++;
242  return *this;
243  }
244 
246  {
247  row--;
248  return *this;
249  }
250 
252  {
253  iterator copy{ this };
254  row++;
255  return copy;
256  }
257 
259  {
260  iterator copy{ this };
261  row--;
262  return copy;
263  }
264 
266  {
267  return source[row];
268  }
269 
270  bool operator == (const iterator& right) const noexcept
271  {
272  return row == right.row && source.data == right.source.data;
273  }
274 
275  bool operator != (const iterator& right) const noexcept
276  {
277  return !(*this == right);
278  }
279 
280  private:
281  umatrix<T> source;
282  std::size_t row;
283  };
284 
288  umatrix(T * const * data, std::size_t channelsOrRows, std::size_t samplesOrColumns)
289  : data(data)
290  , numRows(channelsOrRows)
291  , numColumns(samplesOrColumns)
292  {
293 
294  }
295 
302  uarray<T> operator [] (std::size_t row) const CPPAPE_NOEXCEPT_IF_RELEASE
303  {
304 #ifndef CPPAPE_RELEASE
305  assert(row < numRows);
306 #endif
307 
308  return { data[row], numColumns };
309  }
310 
314  iterator begin() const noexcept { return { *this }; }
319  iterator end() const noexcept { return { *this, numRows }; }
320 
324  std::size_t samples() const noexcept { return numColumns; }
328  std::size_t channels() const noexcept { return numRows; }
332  std::size_t rows() const noexcept { return numRows; }
336  std::size_t columns() const noexcept { return numColumns; }
337 
341  auto pointers() { return data; }
342  const auto pointers() const noexcept { return data; }
343 
347  operator umatrix<const T> () const noexcept
348  {
349  return { data, numColumns, numRows };
350  }
351 
352  protected:
353  T* const * data;
354  std::size_t numRows, numColumns;
355  };
356 
360  template<typename T>
362  {
367  void resize(std::size_t channelCount, std::size_t samples)
368  {
369  channels.resize(channelCount);
370  buffer.resize(channelCount * samples);
371 
372  for (std::size_t c = 0; c < channelCount; ++c)
373  channels[c] = buffer.data() + c * samples;
374  }
375 
380  operator umatrix<T>() noexcept
381  {
382  return umatrix<T> { channels.data(), channels.size(), buffer.size() / channels.size() };
383  }
384 
388  operator umatrix<const T>() const noexcept
389  {
390  return umatrix<const T> { channels.data(), channels.size(), buffer.size() / channels.size() };
391  }
392 
396  umatrix<T> asMatrix() noexcept
397  {
398  return umatrix<T> { channels.data(), channels.size(), buffer.size() / channels.size() };
399  }
400 
401  std::vector<T*> channels;
402  std::vector<T> buffer;
403  };
404 
409  template<typename T>
411  {
412  public:
413 
414  circular_signal(uarray<const T> source) : source(source) {}
415 
416  T operator()(std::int64_t x) const noexcept
417  {
418  auto mod = x % source.size();
419  x = mod < 0 ? mod + source.size() : mod;
420  return source[x];
421  }
422 
423  T operator()(std::int32_t x) const noexcept
424  {
425  auto mod = x % source.size();
426  x = mod < 0 ? mod + source.size() : mod;
427  return source[x];
428  }
429 
430  T operator()(std::uint64_t x) const noexcept
431  {
432  return source[x % source.size()];
433  }
434 
435  T operator()(std::uint32_t x) const noexcept
436  {
437  return source[x % source.size()];
438  }
439 
443  T operator() (double x) const noexcept
444  {
445  return hermite4(*this, x);
446  }
447 
448  private:
449 
450  uarray<const T> source;
451  };
452 
458  template<typename T>
460  {
461  public:
462 
463  windowed_signal(uarray<const T> source) : source(source) {}
464 
465  T operator()(std::int64_t x) const noexcept
466  {
467  if (x >= 0 && x < source.size())
468  return source[x];
469 
470  return static_cast<T>(0);
471  }
472 
473  T operator()(std::int32_t x) const noexcept
474  {
475  if (x >= 0 && x < source.size())
476  return source[x];
477 
478  return static_cast<T>(0);
479  }
480 
481  T operator()(std::uint64_t x) const noexcept
482  {
483  if (x < source.size())
484  return source[x];
485 
486  return static_cast<T>(0);
487  }
488 
489  T operator()(std::uint32_t x) const noexcept
490  {
491  if (x < source.size())
492  return source[x];
493 
494  return static_cast<T>(0);
495  }
496 
500  T operator() (double x) const noexcept
501  {
502  return hermite4(*this, x);
503  }
504 
505  private:
506 
507  uarray<const T> source;
508  };
509 
517  template<typename T>
518  struct circular_iterator // : std::iterator<std::forward_iterator_tag, T>
519  {
520  public:
521 
522  using value_type = T;
523  using difference_type = std::ptrdiff_t;
525  using pointer = T*;
526  using iterator_category = std::forward_iterator_tag;
528 
529  template<typename Container>
530  friend auto cyclic_begin(Container& c, std::size_t offset);
531 
532  template<typename Container>
533  friend auto cyclic_end(Container& c, std::size_t offset, std::size_t length);
534 
535  // LegacyIterator
536  reference operator * () noexcept { return base[origin]; }
537 
538  this_type operator ++(int) noexcept
539  {
540  this_type copy(*this);
541  ++copy;
542  return copy;
543  }
544 
545  // LegacyInputIterator
546  this_type& operator ++() noexcept
547  {
548  if (++origin >= bounds)
549  origin -= bounds;
550 
551  distance++;
552 
553  return *this;
554  }
555 
556  pointer operator -> () noexcept { return base + origin; }
557 
558 
559  // LegacyBidirectionalIterator
560  this_type operator --(int) noexcept
561  {
562  this_type copy(*this);
563  --copy;
564  return copy;
565  }
566 
567  // LegacyInputIterator
568  this_type& operator --() noexcept
569  {
570  if (origin == 0)
571  origin = bounds - 1;
572  else
573  origin--;
574 
575  distance--;
576 
577  return *this;
578  }
579 
580 
582  {
583  return
584  left.base == right.base &&
585  left.distance == right.distance &&
586  left.origin == right.origin &&
587  left.bounds == right.bounds;
588  }
589 
591  {
592  return !(left == right);
593  }
594 
595  private:
596  pointer base;
597  std::ptrdiff_t distance;
598  std::size_t origin;
599  std::size_t bounds;
600  };
601 
602 
613  template<typename Container>
614  inline auto cyclic_begin(Container& c, std::size_t offset)
615  {
617  ret.base = c.data();
618  ret.distance = 0;
619  ret.origin = offset % c.size();
620  ret.bounds = c.size();
621  return ret;
622  }
623 
636  template<typename Container>
637  inline auto cyclic_end(Container& c, std::size_t offset, std::size_t length)
638  {
640  ret.base = c.data();
641  ret.distance = length;
642  ret.origin = (offset + length) % c.size();
643  ret.bounds = c.size();
644 
645  return ret;
646  }
647 
651  template<typename T>
652  inline void clear(std::vector<T>& arr) noexcept
653  {
654  std::fill(arr.begin(), arr.end(), T());
655  }
656 
660  template<typename T>
661  inline typename std::enable_if<!std::is_const_v<T>>::type
662  clear(uarray<T> arr) noexcept
663  {
664  std::fill(arr.begin(), arr.end(), T());
665  }
666 
670  template<typename T>
671  inline typename std::enable_if<!std::is_const_v<T>>::type
672  clear(umatrix<T> mat, std::size_t offset = 0) noexcept
673  {
674  for (std::size_t c = offset; c < mat.channels(); ++c)
675  {
676  clear(mat[c]);
677  }
678  }
679 
680  template<typename T>
681  inline uarray<T> as_uarray(std::vector<T>& vec)
682  {
683  return { vec };
684  }
685 
686  template<typename T>
687  inline uarray<const T> as_uarray(const std::vector<T>& vec)
688  {
689  return { vec };
690  }
691 
692  template<typename T>
693  inline uarray<T> as_uarray(T* data, std::size_t size)
694  {
695  return { data, size };
696  }
697 
698  template<typename T>
699  inline uarray<const T> as_uarray(const T* data, std::size_t size)
700  {
701  return { data, size };
702  }
703 }
704 
705 #endif
ape::cyclic_begin
auto cyclic_begin(Container &c, std::size_t offset)
Constructs a suitable beginning iterator of a cyclic iteration on c . Iteration effectively wraps aro...
Definition: misc.h:614
ape::umatrix::operator[]
uarray< T > operator[](std::size_t row) const CPPAPE_NOEXCEPT_IF_RELEASE
Access the row in the matrix.
Definition: misc.h:302
ape::cyclic_end
auto cyclic_end(Container &c, std::size_t offset, std::size_t length)
Specifies an "end" to cyclic_begin
Definition: misc.h:637
ape::circular_iterator::iterator_category
std::forward_iterator_tag iterator_category
Definition: misc.h:526
ape::umatrix::umatrix
umatrix(T *const *data, std::size_t channelsOrRows, std::size_t samplesOrColumns)
Construct from a pointer array.
Definition: misc.h:288
ape::DynamicSampleMatrix::asMatrix
umatrix< T > asMatrix() noexcept
Explicitly alias as a mutable umatrix.
Definition: misc.h:396
ape::windowed_signal
An infinitely indexable read-only signal that windows the original signal (ie. it is zero outside of ...
Definition: misc.h:459
ape::uarray::begin
T * begin() noexcept
Returns an iterator to the beginning of the array pointed to
Definition: misc.h:88
ape::umatrix::begin
iterator begin() const noexcept
Retrieve an iterator that can enumerate channels contained in this matrix.
Definition: misc.h:314
ape::circular_iterator::value_type
T value_type
Definition: misc.h:522
ape::umatrix::iterator::operator*
uarray< T > operator*()
Definition: misc.h:265
ape::circular_iterator::reference
value_type & reference
Definition: misc.h:524
ape::umatrix::iterator::iterator_category
std::bidirectional_iterator_tag iterator_category
Definition: misc.h:231
ape::as_uarray
uarray< T > as_uarray(std::vector< T > &vec)
Definition: misc.h:681
interpolation.h
ape::uarray::data
const T * data() const noexcept
Retrieve a const raw pointer to the array pointed to
Definition: misc.h:108
ape::umatrix
A container representing a 2d rectangular array (and can be used syntactically like one)....
Definition: misc.h:212
ape::windowed_signal::operator()
T operator()(std::uint32_t x) const noexcept
Definition: misc.h:489
ape::umatrix::iterator::operator==
bool operator==(const iterator &right) const noexcept
Definition: misc.h:270
ape::umatrix::pointers
auto pointers()
Returns a possibly cv-qualified T * const*
Definition: misc.h:341
ape::circular_iterator::operator==
friend bool operator==(circular_iterator< T > left, circular_iterator< T > right)
Definition: misc.h:581
ape::umatrix::columns
std::size_t columns() const noexcept
samples()
Definition: misc.h:336
ape::umatrix::iterator::operator++
iterator & operator++()
Definition: misc.h:239
ape::windowed_signal::operator()
T operator()(std::int64_t x) const noexcept
Definition: misc.h:465
ape::circular_iterator::difference_type
std::ptrdiff_t difference_type
Definition: misc.h:523
ape::circular_iterator::operator--
this_type & operator--() noexcept
Definition: misc.h:568
ape::umatrix::numColumns
std::size_t numColumns
Definition: misc.h:354
ape::umatrix::value_type
T value_type
Definition: misc.h:216
ape::circular_iterator::cyclic_begin
friend auto cyclic_begin(Container &c, std::size_t offset)
Constructs a suitable beginning iterator of a cyclic iteration on c . Iteration effectively wraps aro...
Definition: misc.h:614
ape::DynamicSampleMatrix::buffer
std::vector< T > buffer
Definition: misc.h:402
ape::umatrix::channels
std::size_t channels() const noexcept
Definition: misc.h:328
ape::umatrix::iterator::operator--
iterator & operator--()
Definition: misc.h:245
ape::circular_iterator::operator++
this_type & operator++() noexcept
Definition: misc.h:546
ape::uarray::end
T * end() noexcept
Returns an iterator pointing to 1 element past the end of the array pointed to
Definition: misc.h:96
ape::circular_signal::operator()
T operator()(std::int32_t x) const noexcept
Definition: misc.h:423
ape::DynamicSampleMatrix::resize
void resize(std::size_t channelCount, std::size_t samples)
Retranslate the buffers and contents to adhere to the dimensionality given by the arguments....
Definition: misc.h:367
ape::umatrix::end
iterator end() const noexcept
Retrieve an iterator pointing to one past the last channel in this matrix. begin()
Definition: misc.h:319
ape::umatrix::iterator::iterator
iterator(umatrix< T > matrix, std::size_t row=0)
Definition: misc.h:233
ape::uarray
An unowned array wrapper - a mutable "view" of something else, that cannot be resized....
Definition: misc.h:24
ape::uarray::uarray
uarray(T *buffer, std::size_t length)
Construct from a possibly cv-qualified source
Definition: misc.h:44
ape::umatrix::iterator::difference_type
std::ptrdiff_t difference_type
Definition: misc.h:227
ape::umatrix::iterator::reference
value_type & reference
Definition: misc.h:230
ape::windowed_signal::windowed_signal
windowed_signal(uarray< const T > source)
Definition: misc.h:463
ape::hermite4
const T hermite4(const T offset, const T ym1, const T y0, const T y1, const T y2)
Do hermite 4 interpolation given the four y-coordinates
Definition: interpolation.h:76
ape
Definition: audiofile.h:7
ape::umatrix::pointers
const auto pointers() const noexcept
Definition: misc.h:342
ape::uarray::end
const T * end() const noexcept
Returns a const iterator pointing to 1 element past the end of the array pointed to
Definition: misc.h:100
ape::umatrix::iterator::value_type
T value_type
Definition: misc.h:228
ape::umatrix::data
T *const * data
Definition: misc.h:353
ape::uarray::slice
uarray< T > slice(std::size_t offset, std::size_t newLength=-1) noexcept
Returns a new, constant uarray formed from a slice of the original.
Definition: misc.h:126
ape::uarray::size
std::size_t size() const noexcept
Returns the size of the array pointed to by this uarray
Definition: misc.h:113
ape::umatrix::samples
std::size_t samples() const noexcept
Definition: misc.h:324
ape::uarray::uarray
uarray(std::vector< T > &source)
Construct from a mutable vector.
Definition: misc.h:36
ape::uarray::slice
uarray< const T > slice(std::size_t offset, std::size_t newLength=-1) const noexcept
Returns a new, constant uarray formed from a slice of the original.
Definition: misc.h:171
ape::circular_signal::circular_signal
circular_signal(uarray< const T > source)
Definition: misc.h:414
ape::circular_iterator::operator*
reference operator*() noexcept
Definition: misc.h:536
ape::uarray::data
T * data() noexcept
Retrieve a raw pointer to the array pointed to
Definition: misc.h:104
ape::umatrix::iterator::operator!=
bool operator!=(const iterator &right) const noexcept
Definition: misc.h:275
ape::uarray::uarray
uarray(T *begin, T *end)
Construct from a possibly cv-qualified iterator pair
Definition: misc.h:54
ape::umatrix::iterator::pointer
value_type * pointer
Definition: misc.h:229
ape::circular_iterator
LegacyForwardIterator with capability of iterating N steps around a flat source with an offset....
Definition: misc.h:518
ape::circular_signal::operator()
T operator()(std::uint64_t x) const noexcept
Definition: misc.h:430
ape::circular_iterator::pointer
T * pointer
Definition: misc.h:525
ape::uarray::uarray
uarray(const std::vector< typename std::remove_const_t< T >> &source)
Construct a read-only uarray from a const-qualified vector.
Definition: misc.h:40
ape::circular_iterator::operator!=
friend bool operator!=(circular_iterator< T > left, circular_iterator< T > right)
Definition: misc.h:590
ape::circular_signal
An infinitely indexable read-only signal that repeats the original signal. Supports signed and unsign...
Definition: misc.h:410
ape::DynamicSampleMatrix::channels
std::vector< T * > channels
Definition: misc.h:401
ape::uarray::reinterpret
std::enable_if< std::is_standard_layout< Other >::value &&std::is_const< T >::value, uarray< const Other > >::type reinterpret() const noexcept
Definition: misc.h:150
ape::uarray::operator[]
T & operator[](std::size_t index)
Access a potential read-only element at index
Definition: misc.h:66
ape::DynamicSampleMatrix
An owned 2d rectangular matrix that supports a T** representation and being aliased as a umatrix.
Definition: misc.h:361
ape::windowed_signal::operator()
T operator()(std::uint64_t x) const noexcept
Definition: misc.h:481
ape::circular_iterator::cyclic_end
friend auto cyclic_end(Container &c, std::size_t offset, std::size_t length)
Specifies an "end" to cyclic_begin
Definition: misc.h:637
ape::umatrix::iterator
Iterator for enumerating the rows of a umatrix umatrix<T>::begin()
Definition: misc.h:225
ape::umatrix::rows
std::size_t rows() const noexcept
channels()
Definition: misc.h:332
ape::clear
void clear(std::vector< T > &arr) noexcept
Clear a uarray of non-const qualified T elements to a default-initialized value.
Definition: misc.h:652
ape::uarray::begin
const T * begin() const noexcept
Returns a const iterator to the beginning of the array pointed to
Definition: misc.h:92
ape::circular_iterator::operator->
pointer operator->() noexcept
Definition: misc.h:556
ape::windowed_signal::operator()
T operator()(std::int32_t x) const noexcept
Definition: misc.h:473
ape::uarray::value_type
T value_type
Alias for T
Definition: misc.h:31
ape::circular_signal::operator()
T operator()(std::uint32_t x) const noexcept
Definition: misc.h:435
ape::circular_signal::operator()
T operator()(std::int64_t x) const noexcept
Definition: misc.h:416
ape::umatrix::numRows
std::size_t numRows
Definition: misc.h:354
ape::uarray::reinterpret
std::enable_if< std::is_standard_layout< Other >::value &&!std::is_const< T >::value, uarray< Other > >::type reinterpret() noexcept
Definition: misc.h:138