Only show user-presets in favorite sidebar
[ardour.git] / libs / audiographer / audiographer / process_context.h
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
45         ProcessContext (T * data, samplecnt_t samples, ChannelCount channels)
46                 : _data (data), _samples (samples), _channels (channels)
47         { validate_data(); }
48
49         /// Normal copy constructor
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>
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>
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>
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
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
85         virtual ~ProcessContext () {}
86
87         /// \a data points to the array of data to process
88         inline T const *            data()     const { return _data; }
89         inline T *                  data()           { return _data; }
90
91         /// \a samples tells how many samples the array pointed by data contains
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           */
97         inline ChannelCount const & channels() const { return _channels; }
98
99         /// Returns the amount of samples per channel
100         inline samplecnt_t            samples_per_channel() const { return _samples / _channels; }
101
102         /* Flags */
103
104         inline bool has_flag (Flag flag)    const { return _flags.has (flag); }
105         inline void set_flag (Flag flag)    const { _flags.set (flag); }
106         inline void remove_flag (Flag flag) const { _flags.remove (flag); }
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:
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
133         AllocatingProcessContext (samplecnt_t samples, ChannelCount channels)
134                 : ProcessContext<T> (new T[samples], samples, channels) {}
135
136         /// Allocates and copies data from raw buffer
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
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>
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>
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>
158         AllocatingProcessContext (ProcessContext<Y> const & other)
159                 : ProcessContext<T> (other, new T[other._samples]) {}
160
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
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
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>
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>
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>
189         ConstProcessContext (ProcessContext const & other, T const * data)
190                 : context (other, const_cast<T *>(data)) {}
191
192         inline operator ProcessContext<T> const & () { return context; }
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