1 #ifndef AUDIOGRAPHER_PROCESS_CONTEXT_H 2 #define AUDIOGRAPHER_PROCESS_CONTEXT_H 3 4 #include <boost/static_assert.hpp> 5 #include <boost/type_traits.hpp> 6 #include <boost/format.hpp> 7 8 #include "audiographer/visibility.h" 9 #include "exception.h" 10 #include "debug_utils.h" 11 #include "types.h" 12 #include "flag_field.h" 13 #include "throwing.h" 14 #include "type_utils.h" 15 16 namespace AudioGrapher 17 { 18 19 20 /** 21 * Processing context. Constness only applies to data, not flags 22 */ 23 24 template <typename T = DefaultSampleType> 25 class /*LIBAUDIOGRAPHER_API*/ ProcessContext 26 : public Throwing<> 27 { 28 // Support older compilers that don't support template base class initialization without template parameters 29 // This will need to be modified if if it's modified above 30 static const ThrowLevel throwLevel = DEFAULT_THROW_LEVEL; 31 32 BOOST_STATIC_ASSERT (boost::has_trivial_destructor<T>::value); 33 34 public: 35 36 typedef FlagField::Flag Flag; 37 38 enum Flags { 39 EndOfInput = 0 40 }; 41 42 public: 43 44 /// Basic constructor with data, sample and channel count ProcessContext(T * data,samplecnt_t samples,ChannelCount channels)45 ProcessContext (T * data, samplecnt_t samples, ChannelCount channels) 46 : _data (data), _samples (samples), _channels (channels) 47 { validate_data(); } 48 49 /// Normal copy constructor ProcessContext(ProcessContext<T> const & other)50 ProcessContext (ProcessContext<T> const & other) 51 : Throwing<throwLevel>(), _data (other._data), _samples (other._samples), _channels (other._channels), _flags (other._flags) 52 { /* No need to validate data */ } 53 54 /// "Copy constructor" with unique data, sample and channel count, but copies flags 55 template<typename Y> ProcessContext(ProcessContext<Y> const & other,T * data,samplecnt_t samples,ChannelCount channels)56 ProcessContext (ProcessContext<Y> const & other, T * data, samplecnt_t samples, ChannelCount channels) 57 : Throwing<throwLevel>(), _data (data), _samples (samples), _channels (channels), _flags (other.flags()) 58 { validate_data(); } 59 60 /// "Copy constructor" with unique data and sample count, but copies channel count and flags 61 template<typename Y> ProcessContext(ProcessContext<Y> const & other,T * data,samplecnt_t samples)62 ProcessContext (ProcessContext<Y> const & other, T * data, samplecnt_t samples) 63 : Throwing<throwLevel>(), _data (data), _samples (samples), _channels (other.channels()), _flags (other.flags()) 64 { validate_data(); } 65 66 /// "Copy constructor" with unique data, but copies sample and channel count + flags 67 template<typename Y> ProcessContext(ProcessContext<Y> const & other,T * data)68 ProcessContext (ProcessContext<Y> const & other, T * data) 69 : Throwing<throwLevel>(), _data (data), _samples (other.samples()), _channels (other.channels()), _flags (other.flags()) 70 { /* No need to validate data */ } 71 72 /// Make new Context out of the beginning of this context beginning(samplecnt_t samples)73 ProcessContext beginning (samplecnt_t samples) 74 { 75 if (throw_level (ThrowProcess) && samples > _samples) { 76 throw Exception (*this, boost::str (boost::format 77 ("Trying to use too many samples of %1% for a new Context: %2% instead of %3%") 78 % DebugUtils::demangled_name (*this) % samples % _samples)); 79 } 80 validate_data (); 81 82 return ProcessContext (*this, _data, samples); 83 } 84 ~ProcessContext()85 virtual ~ProcessContext () {} 86 87 /// \a data points to the array of data to process data()88 inline T const * data() const { return _data; } data()89 inline T * data() { return _data; } 90 91 /// \a samples tells how many samples the array pointed by data contains samples()92 inline samplecnt_t const & samples() const { return _samples; } 93 94 /** \a channels tells how many interleaved channels \a data contains 95 * If \a channels is greater than 1, each channel contains \a samples / \a channels samples of data 96 */ channels()97 inline ChannelCount const & channels() const { return _channels; } 98 99 /// Returns the amount of samples per channel samples_per_channel()100 inline samplecnt_t samples_per_channel() const { return _samples / _channels; } 101 102 /* Flags */ 103 has_flag(Flag flag)104 inline bool has_flag (Flag flag) const { return _flags.has (flag); } set_flag(Flag flag)105 inline void set_flag (Flag flag) const { _flags.set (flag); } remove_flag(Flag flag)106 inline void remove_flag (Flag flag) const { _flags.remove (flag); } flags()107 inline FlagField const & flags () const { return _flags; } 108 109 protected: 110 T * const _data; 111 samplecnt_t _samples; 112 ChannelCount _channels; 113 114 mutable FlagField _flags; 115 116 private: validate_data()117 inline void validate_data() 118 { 119 if (throw_level (ThrowProcess) && (_samples % _channels != 0)) { 120 throw Exception (*this, boost::str (boost::format 121 ("Number of samples given to %1% was not a multiple of channels: %2% samples with %3% channels") 122 % DebugUtils::demangled_name (*this) % _samples % _channels)); 123 } 124 } 125 }; 126 127 /// A process context that allocates and owns it's data buffer 128 template <typename T = DefaultSampleType> 129 class /*LIBAUDIOGRAPHER_API*/ AllocatingProcessContext : public ProcessContext<T> 130 { 131 public: 132 /// Allocates uninitialized memory AllocatingProcessContext(samplecnt_t samples,ChannelCount channels)133 AllocatingProcessContext (samplecnt_t samples, ChannelCount channels) 134 : ProcessContext<T> (new T[samples], samples, channels) {} 135 136 /// Allocates and copies data from raw buffer AllocatingProcessContext(T const * data,samplecnt_t samples,ChannelCount channels)137 AllocatingProcessContext (T const * data, samplecnt_t samples, ChannelCount channels) 138 : ProcessContext<T> (new T[samples], samples, channels) 139 { TypeUtils<float>::copy (data, ProcessContext<T>::_data, samples); } 140 141 /// Copy constructor, copies data from other ProcessContext AllocatingProcessContext(ProcessContext<T> const & other)142 AllocatingProcessContext (ProcessContext<T> const & other) 143 : ProcessContext<T> (other, new T[other._samples]) 144 { TypeUtils<float>::copy (ProcessContext<T>::_data, other._data, other._samples); } 145 146 /// "Copy constructor" with uninitialized data, unique sample and channel count, but copies flags 147 template<typename Y> AllocatingProcessContext(ProcessContext<Y> const & other,samplecnt_t samples,ChannelCount channels)148 AllocatingProcessContext (ProcessContext<Y> const & other, samplecnt_t samples, ChannelCount channels) 149 : ProcessContext<T> (other, new T[samples], samples, channels) {} 150 151 /// "Copy constructor" with uninitialized data, unique sample count, but copies channel count and flags 152 template<typename Y> AllocatingProcessContext(ProcessContext<Y> const & other,samplecnt_t samples)153 AllocatingProcessContext (ProcessContext<Y> const & other, samplecnt_t samples) 154 : ProcessContext<T> (other, new T[samples], samples, other.channels()) {} 155 156 /// "Copy constructor" uninitialized data, that copies sample and channel count + flags 157 template<typename Y> AllocatingProcessContext(ProcessContext<Y> const & other)158 AllocatingProcessContext (ProcessContext<Y> const & other) 159 : ProcessContext<T> (other, new T[other._samples]) {} 160 ~AllocatingProcessContext()161 ~AllocatingProcessContext () { delete [] ProcessContext<T>::_data; } 162 }; 163 164 /// A wrapper for a const ProcesContext which can be created from const data 165 template <typename T = DefaultSampleType> 166 class /*LIBAUDIOGRAPHER_API*/ ConstProcessContext 167 { 168 public: 169 /// Basic constructor with data, sample and channel count ConstProcessContext(T const * data,samplecnt_t samples,ChannelCount channels)170 ConstProcessContext (T const * data, samplecnt_t samples, ChannelCount channels) 171 : context (const_cast<T *>(data), samples, channels) {} 172 173 /// Copy constructor from const ProcessContext ConstProcessContext(ProcessContext<T> const & other)174 ConstProcessContext (ProcessContext<T> const & other) 175 : context (const_cast<ProcessContext<T> &> (other)) {} 176 177 /// "Copy constructor", with unique data, sample and channel count, but copies flags 178 template<typename ProcessContext> ConstProcessContext(ProcessContext const & other,T const * data,samplecnt_t samples,ChannelCount channels)179 ConstProcessContext (ProcessContext const & other, T const * data, samplecnt_t samples, ChannelCount channels) 180 : context (other, const_cast<T *>(data), samples, channels) {} 181 182 /// "Copy constructor", with unique data and sample count, but copies channel count and flags 183 template<typename ProcessContext> ConstProcessContext(ProcessContext const & other,T const * data,samplecnt_t samples)184 ConstProcessContext (ProcessContext const & other, T const * data, samplecnt_t samples) 185 : context (other, const_cast<T *>(data), samples) {} 186 187 /// "Copy constructor", with unique data, but copies sample and channel count + flags 188 template<typename ProcessContext> ConstProcessContext(ProcessContext const & other,T const * data)189 ConstProcessContext (ProcessContext const & other, T const * data) 190 : context (other, const_cast<T *>(data)) {} 191 192 inline operator ProcessContext<T> const & () { return context; } operator()193 inline ProcessContext<T> const & operator() () { return context; } 194 inline ProcessContext<T> const * operator& () { return &context; } 195 196 private: 197 ProcessContext<T> const context; 198 }; 199 200 } // namespace 201 202 #endif // AUDIOGRAPHER_PROCESS_CONTEXT_H 203