#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, sample and channel count ProcessContext (T * data, samplecnt_t samples, ChannelCount channels) : _data (data), _samples (samples), _channels (channels) { validate_data(); } /// Normal copy constructor ProcessContext (ProcessContext const & other) : Throwing(), _data (other._data), _samples (other._samples), _channels (other._channels), _flags (other._flags) { /* No need to validate data */ } /// "Copy constructor" with unique data, sample and channel count, but copies flags template ProcessContext (ProcessContext const & other, T * data, samplecnt_t samples, ChannelCount channels) : Throwing(), _data (data), _samples (samples), _channels (channels), _flags (other.flags()) { validate_data(); } /// "Copy constructor" with unique data and sample count, but copies channel count and flags template ProcessContext (ProcessContext const & other, T * data, samplecnt_t samples) : Throwing(), _data (data), _samples (samples), _channels (other.channels()), _flags (other.flags()) { validate_data(); } /// "Copy constructor" with unique data, but copies sample and channel count + flags template ProcessContext (ProcessContext const & other, T * data) : Throwing(), _data (data), _samples (other.samples()), _channels (other.channels()), _flags (other.flags()) { /* No need to validate data */ } /// Make new Context out of the beginning of this context ProcessContext beginning (samplecnt_t samples) { if (throw_level (ThrowProcess) && samples > _samples) { throw Exception (*this, boost::str (boost::format ("Trying to use too many samples of %1% for a new Context: %2% instead of %3%") % DebugUtils::demangled_name (*this) % samples % _samples)); } validate_data (); return ProcessContext (*this, _data, samples); } 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 samples tells how many samples the array pointed by data contains inline samplecnt_t const & samples() const { return _samples; } /** \a channels tells how many interleaved channels \a data contains * If \a channels is greater than 1, each channel contains \a samples / \a channels samples of data */ inline ChannelCount const & channels() const { return _channels; } /// Returns the amount of samples per channel inline samplecnt_t samples_per_channel() const { return _samples / _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; samplecnt_t _samples; ChannelCount _channels; mutable FlagField _flags; private: inline void validate_data() { if (throw_level (ThrowProcess) && (_samples % _channels != 0)) { throw Exception (*this, boost::str (boost::format ("Number of samples given to %1% was not a multiple of channels: %2% samples with %3% channels") % DebugUtils::demangled_name (*this) % _samples % _channels)); } } }; /// A process context that allocates and owns it's data buffer template class /*LIBAUDIOGRAPHER_API*/ AllocatingProcessContext : public ProcessContext { public: /// Allocates uninitialized memory AllocatingProcessContext (samplecnt_t samples, ChannelCount channels) : ProcessContext (new T[samples], samples, channels) {} /// Allocates and copies data from raw buffer AllocatingProcessContext (T const * data, samplecnt_t samples, ChannelCount channels) : ProcessContext (new T[samples], samples, channels) { TypeUtils::copy (data, ProcessContext::_data, samples); } /// Copy constructor, copies data from other ProcessContext AllocatingProcessContext (ProcessContext const & other) : ProcessContext (other, new T[other._samples]) { TypeUtils::copy (ProcessContext::_data, other._data, other._samples); } /// "Copy constructor" with uninitialized data, unique sample and channel count, but copies flags template AllocatingProcessContext (ProcessContext const & other, samplecnt_t samples, ChannelCount channels) : ProcessContext (other, new T[samples], samples, channels) {} /// "Copy constructor" with uninitialized data, unique sample count, but copies channel count and flags template AllocatingProcessContext (ProcessContext const & other, samplecnt_t samples) : ProcessContext (other, new T[samples], samples, other.channels()) {} /// "Copy constructor" uninitialized data, that copies sample and channel count + flags template AllocatingProcessContext (ProcessContext const & other) : ProcessContext (other, new T[other._samples]) {} ~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, sample and channel count ConstProcessContext (T const * data, samplecnt_t samples, ChannelCount channels) : context (const_cast(data), samples, channels) {} /// Copy constructor from const ProcessContext ConstProcessContext (ProcessContext const & other) : context (const_cast &> (other)) {} /// "Copy constructor", with unique data, sample and channel count, but copies flags template ConstProcessContext (ProcessContext const & other, T const * data, samplecnt_t samples, ChannelCount channels) : context (other, const_cast(data), samples, channels) {} /// "Copy constructor", with unique data and sample count, but copies channel count and flags template ConstProcessContext (ProcessContext const & other, T const * data, samplecnt_t samples) : context (other, const_cast(data), samples) {} /// "Copy constructor", with unique data, but copies sample 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