globally change all use of "frame" to refer to audio into "sample".
[ardour.git] / libs / audiographer / audiographer / general / chunker.h
1 #ifndef AUDIOGRAPHER_CHUNKER_H
2 #define AUDIOGRAPHER_CHUNKER_H
3
4 #include "audiographer/visibility.h"
5 #include "audiographer/flag_debuggable.h"
6 #include "audiographer/sink.h"
7 #include "audiographer/type_utils.h"
8 #include "audiographer/utils/listed_source.h"
9
10 namespace AudioGrapher
11 {
12
13 /// A class that chunks process cycles into equal sized samples
14 template<typename T = DefaultSampleType>
15 class /*LIBAUDIOGRAPHER_API*/ Chunker
16   : public ListedSource<T>
17   , public Sink<T>
18   , public FlagDebuggable<>
19 {
20   public:
21         /** Constructs a new Chunker with a constant chunk size.
22           * \n NOT RT safe
23           */
24         Chunker (samplecnt_t chunk_size)
25           : chunk_size (chunk_size)
26           , position (0)
27         {
28                 buffer = new T[chunk_size];
29                 add_supported_flag (ProcessContext<T>::EndOfInput);
30         }
31
32         ~Chunker()
33         {
34                 delete [] buffer;
35         }
36
37         /** Outputs data in \a context in chunks with the size specified in the constructor.
38           * Note that some calls might not produce any output, while others may produce several.
39           * \n RT safe
40           */
41         void process (ProcessContext<T> const & context)
42         {
43                 check_flags (*this, context);
44
45                 samplecnt_t samples_left = context.samples();
46                 samplecnt_t input_position = 0;
47
48                 while (position + samples_left >= chunk_size) {
49                         // Copy from context to buffer
50                         samplecnt_t const samples_to_copy = chunk_size - position;
51                         TypeUtils<T>::copy (&context.data()[input_position], &buffer[position], samples_to_copy);
52
53                         // Update counters
54                         position = 0;
55                         input_position += samples_to_copy;
56                         samples_left -= samples_to_copy;
57
58                         // Output whole buffer
59                         ProcessContext<T> c_out (context, buffer, chunk_size);
60                         if (samples_left) { c_out.remove_flag(ProcessContext<T>::EndOfInput); }
61                         ListedSource<T>::output (c_out);
62                 }
63
64                 if (samples_left) {
65                         // Copy the rest of the data
66                         TypeUtils<T>::copy (&context.data()[input_position], &buffer[position], samples_left);
67                         position += samples_left;
68                 }
69
70                 if (context.has_flag (ProcessContext<T>::EndOfInput) && position > 0) {
71                         ProcessContext<T> c_out (context, buffer, position);
72                         ListedSource<T>::output (c_out);
73                 }
74         }
75         using Sink<T>::process;
76
77   private:
78         samplecnt_t chunk_size;
79         samplecnt_t position;
80         T * buffer;
81
82 };
83
84 } // namespace
85
86 #endif // AUDIOGRAPHER_CHUNKER_H
87