#ifndef AUDIOGRAPHER_PROCESS_CONTEXT_H #define AUDIOGRAPHER_PROCESS_CONTEXT_H #include #include #include #include "audiographer/visibility.h" #include "exception.h" #include "debug_utils.h" #include "types.h" #include "flag_field.h" #include "throwing.h" #include "type_utils.h" namespace AudioGrapher { /** * Processing context. Constness only applies to data, not flags */ template class /*LIBAUDIOGRAPHER_API*/ ProcessContext : public Throwing<> { // Support older compilers that don't support template base class initialization without template parameters // This will need to be modified if if it's modified above static const ThrowLevel throwLevel = DEFAULT_THROW_LEVEL; BOOST_STATIC_ASSERT (boost::has_trivial_destructor::value); public: typedef FlagField::Flag Flag; enum Flags { EndOfInput = 0 }; public: /// Basic constructor with data, frame and channel count ProcessContext (T * data, framecnt_t frames, ChannelCount channels) : _data (data), _frames (frames), _channels (channels) { validate_data(); } /// Normal copy constructor ProcessContext (ProcessContext const & other) : Throwing(), _data (other._data), _frames (other._frames), _channels (other._channels), _flags (other._flags) { /* No need to validate data */ } /// "Copy constructor" with unique data, frame and channel count, but copies flags template ProcessContext (ProcessContext const & other, T * data, framecnt_t frames, ChannelCount channels) : Throwing(), _data (data), _frames (frames), _channels (channels), _flags (other.flags()) { validate_data(); } /// "Copy constructor" with unique data and frame count, but copies channel count and flags template ProcessContext (ProcessContext const & other, T * data, framecnt_t frames) : Throwing(), _data (data), _frames (frames), _channels (other.channels()), _flags (other.flags()) { validate_data(); } /// "Copy constructor" with unique data, but copies frame and channel count + flags template ProcessContext (ProcessContext const & other, T * data) : Throwing(), _data (data), _frames (other.frames()), _channels (other.channels()), _flags (other.flags()) { /* No need to validate data */ } /// Make new Context out of the beginning of this context ProcessContext beginning (framecnt_t frames) { if (throw_level (ThrowProcess) && frames > _frames) { throw Exception (*this, boost::str (boost::format ("Trying to use too many frames of %1% for a new Context: %2% instead of %3%") % DebugUtils::demangled_name (*this) % frames % _frames)); } validate_data (); return ProcessContext (*this, _data, frames); } virtual ~ProcessContext () {} /// \a data points to the array of data to process inline T const * data() const { return _data; } inline T * data() { return _data; } /// \a frames tells how many frames the array pointed by data contains inline framecnt_t const & frames() const { return _frames; } /** \a channels tells how many interleaved channels \a data contains * If \a channels is greater than 1, each channel contains \a frames / \a channels frames of data */ inline ChannelCount const & channels() const { return _channels; } /// Returns the amount of frames per channel inline framecnt_t frames_per_channel() const { return _frames / _channels; } /* Flags */ inline bool has_flag (Flag flag) const { return _flags.has (flag); } inline void set_flag (Flag flag) const { _flags.set (flag); } inline void remove_flag (Flag flag) const { _flags.remove (flag); } inline FlagField const & flags () const { return _flags; } protected: T * const _data; framecnt_t _frames; ChannelCount _channels; mutable FlagField _flags; private: inline void validate_data() { if (throw_level (ThrowProcess) && (_frames % _channels != 0)) { throw Exception (*this, boost::str (boost::format ("Number of frames given to %1% was not a multiple of channels: %2% frames with %3% channels") % DebugUtils::demangled_name (*this) % _frames % _channels)); } } }; /// A process context that allocates and owns it's data buffer template class /*LIBAUDIOGRAPHER_API*/ AllocatingProcessContext : public ProcessContext { public: /// Allocates uninitialized memory AllocatingProcessContext (framecnt_t frames, ChannelCount channels) : ProcessContext (new T[frames], frames, channels) {} /// Allocates and copies data from raw buffer AllocatingProcessContext (T const * data, framecnt_t frames, ChannelCount channels) : ProcessContext (new T[frames], frames, channels) { TypeUtils::copy (data, ProcessContext::_data, frames); } /// Copy constructor, copies data from other ProcessContext AllocatingProcessContext (ProcessContext const & other) : ProcessContext (other, new T[other._frames]) { TypeUtils::copy (ProcessContext::_data, other._data, other._frames); } /// "Copy constructor" with uninitialized data, unique frame and channel count, but copies flags template AllocatingProcessContext (ProcessContext const & other, framecnt_t frames, ChannelCount channels) : ProcessContext (other, new T[frames], frames, channels) {} /// "Copy constructor" with uninitialized data, unique frame count, but copies channel count and flags template AllocatingProcessContext (ProcessContext const & other, framecnt_t frames) : ProcessContext (other, new T[frames], frames, other.channels()) {} /// "Copy constructor" uninitialized data, that copies frame and channel count + flags template AllocatingProcessContext (ProcessContext const & other) : ProcessContext (other, new T[other._frames]) {} ~AllocatingProcessContext () { delete [] ProcessContext::_data; } }; /// A wrapper for a const ProcesContext which can be created from const data template class /*LIBAUDIOGRAPHER_API*/ ConstProcessContext { public: /// Basic constructor with data, frame and channel count ConstProcessContext (T const * data, framecnt_t frames, ChannelCount channels) : context (const_cast(data), frames, channels) {} /// Copy constructor from const ProcessContext ConstProcessContext (ProcessContext const & other) : context (const_cast &> (other)) {} /// "Copy constructor", with unique data, frame and channel count, but copies flags template ConstProcessContext (ProcessContext const & other, T const * data, framecnt_t frames, ChannelCount channels) : context (other, const_cast(data), frames, channels) {} /// "Copy constructor", with unique data and frame count, but copies channel count and flags template ConstProcessContext (ProcessContext const & other, T const * data, framecnt_t frames) : context (other, const_cast(data), frames) {} /// "Copy constructor", with unique data, but copies frame and channel count + flags template ConstProcessContext (ProcessContext const & other, T const * data) : context (other, const_cast(data)) {} inline operator ProcessContext const & () { return context; } inline ProcessContext const & operator() () { return context; } inline ProcessContext const * operator& () { return &context; } private: ProcessContext const context; }; } // namespace #endif // AUDIOGRAPHER_PROCESS_CONTEXT_H