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