fac38912d773245e17ee1ba3271d0e64f3431394
[ardour.git] / libs / audiographer / audiographer / general / deinterleaver.h
1 #ifndef AUDIOGRAPHER_DEINTERLEAVER_H
2 #define AUDIOGRAPHER_DEINTERLEAVER_H
3
4 #include "audiographer/visibility.h"
5 #include "audiographer/types.h"
6 #include "audiographer/source.h"
7 #include "audiographer/sink.h"
8 #include "audiographer/exception.h"
9 #include "audiographer/utils/identity_vertex.h"
10
11 #include <vector>
12
13 namespace AudioGrapher
14 {
15
16 /// Converts on stream of interleaved data to many streams of uninterleaved data.
17 template<typename T = DefaultSampleType>
18 class /*LIBAUDIOGRAPHER_API*/ DeInterleaver
19   : public Sink<T>
20   , public Throwing<>
21 {
22   private:
23         typedef boost::shared_ptr<IdentityVertex<T> > OutputPtr;
24         
25   public:
26         /// Constructor. \n RT safe
27         DeInterleaver()
28           : channels (0)
29           , max_frames (0)
30           , buffer (0)
31         {}
32         
33         ~DeInterleaver() { reset(); }
34         
35         typedef boost::shared_ptr<Source<T> > SourcePtr;
36         
37         /// Inits the deinterleaver. Must be called before using. \n Not RT safe
38         void init (unsigned int num_channels, framecnt_t max_frames_per_channel)
39         {
40                 reset();
41                 channels = num_channels;
42                 max_frames = max_frames_per_channel;
43                 buffer = new T[max_frames];
44                 
45                 for (unsigned int i = 0; i < channels; ++i) {
46                         outputs.push_back (OutputPtr (new IdentityVertex<T>));
47                 }
48         }
49         
50         /// Returns an output indexed by \a channel \n RT safe
51         SourcePtr output (unsigned int channel)
52         {
53                 if (throw_level (ThrowObject) && channel >= channels) {
54                         throw Exception (*this, "channel out of range");
55                 }
56                 
57                 return outputs[channel];
58         }
59         
60         /// Deinterleaves data and outputs it to the outputs. \n RT safe
61         void process (ProcessContext<T> const & c)
62         {
63                 framecnt_t frames = c.frames();
64                 T const * data = c.data();
65                 
66                 framecnt_t const  frames_per_channel = frames / channels;
67                 
68                 if (throw_level (ThrowProcess) && c.channels() != channels) {
69                         throw Exception (*this, "wrong amount of channels given to process()");
70                 }
71                 
72                 if (throw_level (ThrowProcess) && frames_per_channel > max_frames) {
73                         throw Exception (*this, "too many frames given to process()");
74                 }
75                 
76                 unsigned int channel = 0;
77                 for (typename std::vector<OutputPtr>::iterator it = outputs.begin(); it != outputs.end(); ++it, ++channel) {
78                         if (!*it) { continue; }
79                         
80                         for (unsigned int i = 0; i < frames_per_channel; ++i) {
81                                 buffer[i] = data[channel + (channels * i)];
82                         }
83                         
84                         ProcessContext<T> c_out (c, buffer, frames_per_channel, 1);
85                         (*it)->process (c_out);
86                 }
87         }
88         
89         using Sink<T>::process;
90         
91   private:
92
93         void reset ()
94         {
95                 outputs.clear();
96                 delete [] buffer;
97                 buffer = 0;
98                 channels = 0;
99                 max_frames = 0;
100         }
101         
102         std::vector<OutputPtr> outputs;
103         unsigned int channels;
104         framecnt_t max_frames;
105         T * buffer;
106 };
107
108 } // namespace
109
110 #endif // AUDIOGRAPHER_DEINTERLEAVER_H