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