globally change all use of "frame" to refer to audio into "sample".
[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_samples (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, samplecnt_t max_samples_per_channel)
39         {
40                 reset();
41                 channels = num_channels;
42                 max_samples = max_samples_per_channel;
43                 buffer = new T[max_samples];
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                 samplecnt_t samples = c.samples();
64                 T const * data = c.data();
65
66                 samplecnt_t const  samples_per_channel = samples / 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) && samples_per_channel > max_samples) {
73                         throw Exception (*this, "too many samples 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 < samples_per_channel; ++i) {
81                                 buffer[i] = data[channel + (channels * i)];
82                         }
83
84                         ProcessContext<T> c_out (c, buffer, samples_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_samples = 0;
100         }
101
102         std::vector<OutputPtr> outputs;
103         unsigned int channels;
104         samplecnt_t max_samples;
105         T * buffer;
106 };
107
108 } // namespace
109
110 #endif // AUDIOGRAPHER_DEINTERLEAVER_H