summaryrefslogtreecommitdiff
path: root/libs/audiographer/audiographer/general/interleaver.h
diff options
context:
space:
mode:
authorSakari Bergen <sakari.bergen@beatwaves.net>2010-03-15 19:11:48 +0000
committerSakari Bergen <sakari.bergen@beatwaves.net>2010-03-15 19:11:48 +0000
commit830911f6f9451d83a58043b3f9084d3caa164b7b (patch)
treef4ca4e3d86b51d66e7cecfb6b370cc4eb553e2d7 /libs/audiographer/audiographer/general/interleaver.h
parent44f4b84551d36ef4103d09452768f5ba53e0002c (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.h152
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