tomwalters@268
|
1 // Copyright 2010, Thomas Walters
|
tomwalters@268
|
2 //
|
tomwalters@268
|
3 // AIM-C: A C++ implementation of the Auditory Image Model
|
tomwalters@268
|
4 // http://www.acousticscale.org/AIMC
|
tomwalters@268
|
5 //
|
tomwalters@318
|
6 // Licensed under the Apache License, Version 2.0 (the "License");
|
tomwalters@318
|
7 // you may not use this file except in compliance with the License.
|
tomwalters@318
|
8 // You may obtain a copy of the License at
|
tomwalters@268
|
9 //
|
tomwalters@318
|
10 // http://www.apache.org/licenses/LICENSE-2.0
|
tomwalters@268
|
11 //
|
tomwalters@318
|
12 // Unless required by applicable law or agreed to in writing, software
|
tomwalters@318
|
13 // distributed under the License is distributed on an "AS IS" BASIS,
|
tomwalters@318
|
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
tomwalters@318
|
15 // See the License for the specific language governing permissions and
|
tomwalters@318
|
16 // limitations under the License.
|
tomwalters@268
|
17
|
tomwalters@268
|
18 /*! \file
|
tomwalters@268
|
19 * \brief Base class for all AIM-C modules.
|
tomwalters@268
|
20 */
|
tomwalters@268
|
21
|
tomwalters@268
|
22 /*! \author: Thomas Walters <tom@acousticscale.org>
|
tomwalters@268
|
23 * \date 2010/01/23
|
tomwalters@296
|
24 * \version \$Id$
|
tomwalters@268
|
25 */
|
tomwalters@268
|
26
|
tomwalters@283
|
27 #ifndef AIMC_SUPPORT_MODULE_H_
|
tomwalters@283
|
28 #define AIMC_SUPPORT_MODULE_H_
|
tomwalters@268
|
29
|
tomwalters@330
|
30 // Several modules expect the M_PI macro and isnan() to be defined
|
tomwalters@330
|
31 #ifdef _MSC_VER
|
tomwalters@330
|
32 #define M_PI 3.14159265359
|
tomwalters@330
|
33 #define isnan _isnan
|
tomwalters@330
|
34 #define isinf _isinf
|
tomwalters@330
|
35 #endif
|
tomwalters@330
|
36
|
tomwalters@323
|
37 #include <iostream>
|
tomwalters@268
|
38 #include <set>
|
tomwalters@268
|
39 #include <string>
|
tomwalters@268
|
40
|
tomwalters@268
|
41 #include "Support/Common.h"
|
tomwalters@268
|
42 #include "Support/Parameters.h"
|
tomwalters@268
|
43 #include "Support/SignalBank.h"
|
tomwalters@268
|
44
|
tomwalters@268
|
45 namespace aimc {
|
tomwalters@323
|
46 using std::ostream;
|
tomwalters@268
|
47 using std::set;
|
tomwalters@268
|
48 using std::string;
|
tomwalters@281
|
49
|
tomwalters@281
|
50 /*! \brief Base class for all AIM-C modules.
|
tomwalters@281
|
51 *
|
tomwalters@281
|
52 * Module() is a base class, from which all AIM-C modules are derived.
|
tomwalters@281
|
53 * Classes deriving from module need to implement, at minimum, the pure
|
tomwalters@281
|
54 * virtual public function Module::Process() and the pure virtual private
|
tomwalters@281
|
55 * functions Module::InitializeInternal() and Module::ResetInternal().
|
tomwalters@281
|
56 * (Note: this is in contravention of
|
tomwalters@281
|
57 * <a href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml?showone=Inheritance#Inheritance">
|
tomwalters@281
|
58 * this rule on inheritance</a> in the Google style guide, but it is designed
|
tomwalters@281
|
59 * to make the implementation of modules as simple as possible.)
|
tomwalters@281
|
60 *
|
tomwalters@281
|
61 * The module constructor is called with a pointer to a set of Parameters.
|
tomwalters@281
|
62 * In the constructor, the module sets the defaults for its various
|
tomwalters@281
|
63 * parameters.
|
tomwalters@281
|
64 * A module is initialized with a reference to a valid SignalBank. After the
|
tomwalters@281
|
65 * Initialize(SignalBank*) function has been called, a call to GetOutputBank()
|
tomwalters@281
|
66 * returns a pointer to a SignalBank in which the results
|
tomwalters@281
|
67 * of the module's processing will be placed. Modules can use the output_
|
tomwalters@281
|
68 * SignalBank to store their output, or leave it uninitialized if they do not
|
tomwalters@281
|
69 * produce an output.
|
tomwalters@281
|
70 * At each call to Process(input), the module takes the
|
tomwalters@281
|
71 * SignalBank 'input' (which must, unless otherwise specified, have the same
|
tomwalters@281
|
72 * number of channels, sample rate, buffer size and centre frequencies as the
|
tomwalters@281
|
73 * SignalBank which was passed to Initialize()), processes it, and places the
|
tomwalters@281
|
74 * output in the internal SignalBank output_.
|
tomwalters@281
|
75 * Modules can have an arbitrary number of unique targets. Each
|
tomwalters@281
|
76 * completed output frame is 'pushed' to all of the targets of the module
|
tomwalters@281
|
77 * in turn when PushOutput() is called. To achieve this, after each complete
|
tomwalters@281
|
78 * output SignalBank is filled, the module calls the Process() function of
|
tomwalters@281
|
79 * each of its targets in turn.
|
tomwalters@281
|
80 * When Initialize() is first called. The module Initialize()s all of its
|
tomwalters@281
|
81 * targets with its ouptut_ SignalBank, if its output bank has been set up.
|
tomwalters@281
|
82 *
|
tomwalters@281
|
83 */
|
tomwalters@268
|
84 class Module {
|
tomwalters@268
|
85 public:
|
tomwalters@268
|
86 explicit Module(Parameters *parameters);
|
tomwalters@268
|
87
|
tomwalters@268
|
88 virtual ~Module();
|
tomwalters@268
|
89
|
tomwalters@281
|
90 /* \brief Initialize the module, including calling InitializeInternal().
|
tomwalters@281
|
91 * Validate this module's output SignalBank, and initialize
|
tomwalters@268
|
92 * any targets of the module if necessary.
|
tomwalters@268
|
93 * \param input Input SignalBank.
|
tomwalters@281
|
94 * \return true on success, false on failure.
|
tomwalters@275
|
95 *
|
tomwalters@281
|
96 * A call to Initialize() will first validate the input SignalBank passed to
|
tomwalters@281
|
97 * it. If this SignalBank is valid, then it will call the
|
tomwalters@281
|
98 * InitializeInternal() function of the child class; this will set up the
|
tomwalters@281
|
99 * child class, and may, if the module produces an output, initialize the
|
tomwalters@281
|
100 * member variable SignalBank output_. If output_ is initialized after the
|
tomwalters@281
|
101 * call to InitializeInternal(), the module will Initialize its targets with
|
tomwalters@281
|
102 * the output. In this way, it is possible to initialize an entire module
|
tomwalters@281
|
103 * tree with a single call to the Initialize() function of the root.
|
tomwalters@281
|
104 *
|
tomwalters@281
|
105 * This function is declared virtual in order to deal with the edge case of
|
tomwalters@281
|
106 * input modules which do not take a SignalBank as input, but rather
|
tomwalters@281
|
107 * generate their own input. In this case, it is better to be able to
|
tomwalters@281
|
108 * override the default Initialize function. When creating a new module, do
|
tomwalters@281
|
109 * not create a new version of Initialize uness you're sure you know what
|
tomwalters@281
|
110 * you're doing!
|
tomwalters@401
|
111 *
|
tomwalters@401
|
112 * global_parameters stores things like the input filename, output filenames
|
tomwalters@401
|
113 * and any other metadata that modules might want to share. If present, it
|
tomwalters@401
|
114 * is propagated to all children. These parameters are mutable and may
|
tomwalters@401
|
115 * change.
|
tomwalters@268
|
116 */
|
tomwalters@401
|
117 virtual bool Initialize(const SignalBank &input,
|
tomwalters@401
|
118 Parameters *global_parameters);
|
tomwalters@268
|
119
|
tomwalters@281
|
120 /*! \brief Returns true if the module has been correctly initialized
|
tomwalters@281
|
121 * \return true if module has been initialized, false otherwise
|
tomwalters@268
|
122 */
|
tomwalters@268
|
123 bool initialized() const;
|
tomwalters@268
|
124
|
tomwalters@268
|
125 /* \brief Add a target to this module. Whenever it generates a new
|
tomwalters@268
|
126 * output, this module will push its output to all its targets.
|
tomwalters@281
|
127 * \param target_module Pointer to a target Module to add.
|
tomwalters@281
|
128 * \return true on success, false on failure.
|
tomwalters@281
|
129 *
|
tomwalters@281
|
130 * When a pointer is passed as a target to the module, the caller retains
|
tomwalters@281
|
131 * ownership of the module that it points to. The pointed-to module must
|
tomwalters@281
|
132 * continue to exist until it is deleted from the target list by a call
|
tomwalters@281
|
133 * to DeleteTarget() or DeleteAllTargets(), or the current module is
|
tomwalters@281
|
134 * destroyed. Bad things will happen if the Module pointed to is deleted
|
tomwalters@281
|
135 * and Initialize(), Reset() or Process() is subsequently called.
|
tomwalters@268
|
136 */
|
tomwalters@268
|
137 bool AddTarget(Module* target_module);
|
tomwalters@268
|
138
|
tomwalters@281
|
139 /*! \brief Remove a previously added target module from the list of targets
|
tomwalters@281
|
140 * for this module.
|
tomwalters@281
|
141 * \param target_module Pointer to the module to remove. This must be a
|
tomwalters@281
|
142 * pointer that was previously passed to AddTarget()
|
tomwalters@281
|
143 * \return true on success, false on failure.
|
tomwalters@268
|
144 */
|
tomwalters@281
|
145 bool RemoveTarget(Module* target_module);
|
tomwalters@268
|
146
|
tomwalters@281
|
147 /*! \brief Remove all previously added target modules from the list of
|
tomwalters@281
|
148 * targets for this module.
|
tomwalters@268
|
149 */
|
tomwalters@281
|
150 void RemoveAllTargets();
|
tomwalters@268
|
151
|
tomwalters@281
|
152 /*! \brief Process a buffer.
|
tomwalters@281
|
153 * \param input SignalBank of the form which was passed to Initialize()
|
tomwalters@281
|
154 *
|
tomwalters@281
|
155 * Process is called once for each input SignalBank. When implemented in
|
tomwalters@281
|
156 * classes inheriting from aimc::Module, P
|
tomwalters@281
|
157 * this SignalBank contains the (read-only) input to the module. It is
|
tomwalters@281
|
158 * expected that the input SignalBank will have the same number of channels,
|
tomwalters@281
|
159 * buffer length and sample rate as the SignalBank passed to Initialize.
|
tomwalters@268
|
160 */
|
tomwalters@268
|
161 virtual void Process(const SignalBank &input) = 0;
|
tomwalters@268
|
162
|
tomwalters@275
|
163 /*! \brief Reset the internal state of this module and all its children to
|
tomwalters@275
|
164 * their initial state.
|
tomwalters@281
|
165 *
|
tomwalters@281
|
166 * Like a call to Initialize() will cause all target modules to be
|
tomwalters@281
|
167 * initialized, a call to Reset() will cause all target modules to be reset.
|
tomwalters@268
|
168 */
|
tomwalters@280
|
169 void Reset();
|
tomwalters@268
|
170
|
tomwalters@281
|
171 /*! \brief Return a pointer to the output SignalBank_ for this class.
|
tomwalters@281
|
172 * \return pointer to the SignalBank that this module uses to store its
|
tomwalters@281
|
173 * output.
|
tomwalters@268
|
174 */
|
tomwalters@268
|
175 const SignalBank* GetOutputBank() const;
|
tomwalters@268
|
176
|
tomwalters@323
|
177 void PrintTargets(ostream &out);
|
tomwalters@402
|
178 void PrintTargetsForDot(ostream &out);
|
tomwalters@402
|
179 void PrintConfiguration(ostream &out);
|
tomwalters@323
|
180
|
tomwalters@296
|
181 string version() const {
|
tomwalters@296
|
182 return module_version_;
|
tomwalters@296
|
183 }
|
tomwalters@296
|
184
|
tomwalters@296
|
185 string id() const {
|
tomwalters@296
|
186 return module_identifier_;
|
tomwalters@296
|
187 }
|
tomwalters@296
|
188
|
tomwalters@296
|
189 string description() const {
|
tomwalters@296
|
190 return module_description_;
|
tomwalters@296
|
191 }
|
tomwalters@296
|
192
|
tomwalters@296
|
193 string type() const {
|
tomwalters@296
|
194 return module_type_;
|
tomwalters@296
|
195 }
|
tomwalters@402
|
196
|
tomwalters@402
|
197 bool done() {
|
tomwalters@402
|
198 return done_;
|
tomwalters@402
|
199 }
|
tomwalters@402
|
200
|
tomwalters@402
|
201 void set_instance_name(string instance_name) {
|
tomwalters@402
|
202 instance_name_ = instance_name;
|
tomwalters@402
|
203 }
|
tomwalters@402
|
204
|
tomwalters@402
|
205 string instance_name() {
|
tomwalters@402
|
206 return instance_name_;
|
tomwalters@402
|
207 }
|
tomwalters@296
|
208
|
tomwalters@268
|
209 protected:
|
tomwalters@268
|
210 void PushOutput();
|
tomwalters@268
|
211
|
tomwalters@275
|
212 virtual void ResetInternal() = 0;
|
tomwalters@275
|
213
|
tomwalters@268
|
214 virtual bool InitializeInternal(const SignalBank &input) = 0;
|
tomwalters@268
|
215
|
tomwalters@268
|
216 bool initialized_;
|
tomwalters@402
|
217 bool done_;
|
tomwalters@268
|
218 set<Module*> targets_;
|
tomwalters@268
|
219 SignalBank output_;
|
tomwalters@268
|
220 Parameters* parameters_;
|
tomwalters@401
|
221 Parameters* global_parameters_;
|
tomwalters@268
|
222
|
tomwalters@268
|
223 string module_identifier_;
|
tomwalters@268
|
224 string module_type_;
|
tomwalters@268
|
225 string module_description_;
|
tomwalters@268
|
226 string module_version_;
|
tomwalters@402
|
227
|
tomwalters@402
|
228 string instance_name_;
|
tomwalters@268
|
229
|
tomwalters@268
|
230 private:
|
tomwalters@268
|
231 DISALLOW_COPY_AND_ASSIGN(Module);
|
tomwalters@268
|
232 };
|
tomwalters@268
|
233 }
|
tomwalters@268
|
234
|
tomwalters@283
|
235 #endif // AIMC_SUPPORT_MODULE_H_
|