diff options
author | Sakari Bergen <sakari.bergen@beatwaves.net> | 2010-03-15 19:11:48 +0000 |
---|---|---|
committer | Sakari Bergen <sakari.bergen@beatwaves.net> | 2010-03-15 19:11:48 +0000 |
commit | 830911f6f9451d83a58043b3f9084d3caa164b7b (patch) | |
tree | f4ca4e3d86b51d66e7cecfb6b370cc4eb553e2d7 /libs/audiographer/audiographer/general/interleaver.h | |
parent | 44f4b84551d36ef4103d09452768f5ba53e0002c (diff) |
Fix export, which has been broken since the boost::signals2 changes. Also update Audiographer, bacause of its incomplete sndfile handling. Audiographer is equal to revision 74
git-svn-id: svn://localhost/ardour2/branches/3.0@6760 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/audiographer/audiographer/general/interleaver.h')
-rw-r--r-- | libs/audiographer/audiographer/general/interleaver.h | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/libs/audiographer/audiographer/general/interleaver.h b/libs/audiographer/audiographer/general/interleaver.h new file mode 100644 index 0000000000..98a71f3afd --- /dev/null +++ b/libs/audiographer/audiographer/general/interleaver.h @@ -0,0 +1,152 @@ +#ifndef AUDIOGRAPHER_INTERLEAVER_H +#define AUDIOGRAPHER_INTERLEAVER_H + +#include "audiographer/types.h" +#include "audiographer/sink.h" +#include "audiographer/exception.h" +#include "audiographer/throwing.h" +#include "audiographer/utils/listed_source.h" + +#include <vector> +#include <cmath> + +namespace AudioGrapher +{ + +/// Interleaves many streams of non-interleaved data into one interleaved stream +template<typename T = DefaultSampleType> +class Interleaver + : public ListedSource<T> + , public Throwing<> +{ + public: + + /// Constructs an interleaver \n RT safe + Interleaver() + : channels (0) + , max_frames (0) + , buffer (0) + {} + + ~Interleaver() { reset(); } + + /// Inits the interleaver. Must be called before using. \n Not RT safe + void init (unsigned int num_channels, nframes_t max_frames_per_channel) + { + reset(); + channels = num_channels; + max_frames = max_frames_per_channel; + + buffer = new T[channels * max_frames]; + + for (unsigned int i = 0; i < channels; ++i) { + inputs.push_back (InputPtr (new Input (*this, i))); + } + } + + /** Returns the input indexed by \a channel \n RT safe + * \n The \a process function of returned Sinks are also RT Safe + */ + typename Source<T>::SinkPtr input (unsigned int channel) + { + if (throw_level (ThrowObject) && channel >= channels) { + throw Exception (*this, "Channel out of range"); + } + + return boost::static_pointer_cast<Sink<T> > (inputs[channel]); + } + + private: + + class Input : public Sink<T> + { + public: + Input (Interleaver & parent, unsigned int channel) + : frames_written (0), parent (parent), channel (channel) {} + + void process (ProcessContext<T> const & c) + { + if (parent.throw_level (ThrowProcess) && c.channels() > 1) { + throw Exception (*this, "Data input has more than on channel"); + } + if (parent.throw_level (ThrowStrict) && frames_written) { + throw Exception (*this, "Input channels out of sync"); + } + frames_written = c.frames(); + parent.write_channel (c, channel); + } + + using Sink<T>::process; + + nframes_t frames() { return frames_written; } + void reset() { frames_written = 0; } + + private: + nframes_t frames_written; + Interleaver & parent; + unsigned int channel; + }; + + void reset () + { + inputs.clear(); + delete [] buffer; + buffer = 0; + channels = 0; + max_frames = 0; + } + + void reset_channels () + { + for (unsigned int i = 0; i < channels; ++i) { + inputs[i]->reset(); + } + + } + + void write_channel (ProcessContext<T> const & c, unsigned int channel) + { + if (throw_level (ThrowProcess) && c.frames() > max_frames) { + reset_channels(); + throw Exception (*this, "Too many frames given to an input"); + } + + for (unsigned int i = 0; i < c.frames(); ++i) { + buffer[channel + (channels * i)] = c.data()[i]; + } + + nframes_t const ready_frames = ready_to_output(); + if (ready_frames) { + ProcessContext<T> c_out (c, buffer, ready_frames, channels); + ListedSource<T>::output (c_out); + reset_channels (); + } + } + + nframes_t ready_to_output() + { + nframes_t ready_frames = inputs[0]->frames(); + if (!ready_frames) { return 0; } + + for (unsigned int i = 1; i < channels; ++i) { + nframes_t const frames = inputs[i]->frames(); + if (!frames) { return 0; } + if (throw_level (ThrowProcess) && frames != ready_frames) { + init (channels, max_frames); + throw Exception (*this, "Frames count out of sync"); + } + } + return ready_frames * channels; + } + + typedef boost::shared_ptr<Input> InputPtr; + std::vector<InputPtr> inputs; + + unsigned int channels; + nframes_t max_frames; + T * buffer; +}; + +} // namespace + +#endif // AUDIOGRAPHER_INTERLEAVER_H |