tomwalters@268: // Copyright 2010, Thomas Walters tomwalters@268: // tomwalters@268: // AIM-C: A C++ implementation of the Auditory Image Model tomwalters@268: // http://www.acousticscale.org/AIMC tomwalters@268: // tomwalters@318: // Licensed under the Apache License, Version 2.0 (the "License"); tomwalters@318: // you may not use this file except in compliance with the License. tomwalters@318: // You may obtain a copy of the License at tomwalters@268: // tomwalters@318: // http://www.apache.org/licenses/LICENSE-2.0 tomwalters@268: // tomwalters@318: // Unless required by applicable law or agreed to in writing, software tomwalters@318: // distributed under the License is distributed on an "AS IS" BASIS, tomwalters@318: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. tomwalters@318: // See the License for the specific language governing permissions and tomwalters@318: // limitations under the License. tomwalters@268: tomwalters@268: /*! \file tomwalters@268: * \brief Base class for all AIM-C modules. tomwalters@268: */ tomwalters@268: tomwalters@268: /*! \author: Thomas Walters tomwalters@268: * \date 2010/01/23 tomwalters@296: * \version \$Id$ tomwalters@268: */ tomwalters@268: tomwalters@283: #ifndef AIMC_SUPPORT_MODULE_H_ tomwalters@283: #define AIMC_SUPPORT_MODULE_H_ tomwalters@268: tomwalters@323: #include tomwalters@268: #include tomwalters@268: #include tomwalters@268: tomwalters@268: #include "Support/Common.h" tomwalters@268: #include "Support/Parameters.h" tomwalters@268: #include "Support/SignalBank.h" tomwalters@268: tomwalters@268: namespace aimc { tomwalters@323: using std::ostream; tomwalters@268: using std::set; tomwalters@268: using std::string; tomwalters@281: tomwalters@281: /*! \brief Base class for all AIM-C modules. tomwalters@281: * tomwalters@281: * Module() is a base class, from which all AIM-C modules are derived. tomwalters@281: * Classes deriving from module need to implement, at minimum, the pure tomwalters@281: * virtual public function Module::Process() and the pure virtual private tomwalters@281: * functions Module::InitializeInternal() and Module::ResetInternal(). tomwalters@281: * (Note: this is in contravention of tomwalters@281: * tomwalters@281: * this rule on inheritance in the Google style guide, but it is designed tomwalters@281: * to make the implementation of modules as simple as possible.) tomwalters@281: * tomwalters@281: * The module constructor is called with a pointer to a set of Parameters. tomwalters@281: * In the constructor, the module sets the defaults for its various tomwalters@281: * parameters. tomwalters@281: * A module is initialized with a reference to a valid SignalBank. After the tomwalters@281: * Initialize(SignalBank*) function has been called, a call to GetOutputBank() tomwalters@281: * returns a pointer to a SignalBank in which the results tomwalters@281: * of the module's processing will be placed. Modules can use the output_ tomwalters@281: * SignalBank to store their output, or leave it uninitialized if they do not tomwalters@281: * produce an output. tomwalters@281: * At each call to Process(input), the module takes the tomwalters@281: * SignalBank 'input' (which must, unless otherwise specified, have the same tomwalters@281: * number of channels, sample rate, buffer size and centre frequencies as the tomwalters@281: * SignalBank which was passed to Initialize()), processes it, and places the tomwalters@281: * output in the internal SignalBank output_. tomwalters@281: * Modules can have an arbitrary number of unique targets. Each tomwalters@281: * completed output frame is 'pushed' to all of the targets of the module tomwalters@281: * in turn when PushOutput() is called. To achieve this, after each complete tomwalters@281: * output SignalBank is filled, the module calls the Process() function of tomwalters@281: * each of its targets in turn. tomwalters@281: * When Initialize() is first called. The module Initialize()s all of its tomwalters@281: * targets with its ouptut_ SignalBank, if its output bank has been set up. tomwalters@281: * tomwalters@281: */ tomwalters@268: class Module { tomwalters@268: public: tomwalters@268: explicit Module(Parameters *parameters); tomwalters@268: tomwalters@268: virtual ~Module(); tomwalters@268: tomwalters@281: /* \brief Initialize the module, including calling InitializeInternal(). tomwalters@281: * Validate this module's output SignalBank, and initialize tomwalters@268: * any targets of the module if necessary. tomwalters@268: * \param input Input SignalBank. tomwalters@281: * \return true on success, false on failure. tomwalters@275: * tomwalters@281: * A call to Initialize() will first validate the input SignalBank passed to tomwalters@281: * it. If this SignalBank is valid, then it will call the tomwalters@281: * InitializeInternal() function of the child class; this will set up the tomwalters@281: * child class, and may, if the module produces an output, initialize the tomwalters@281: * member variable SignalBank output_. If output_ is initialized after the tomwalters@281: * call to InitializeInternal(), the module will Initialize its targets with tomwalters@281: * the output. In this way, it is possible to initialize an entire module tomwalters@281: * tree with a single call to the Initialize() function of the root. tomwalters@281: * tomwalters@281: * This function is declared virtual in order to deal with the edge case of tomwalters@281: * input modules which do not take a SignalBank as input, but rather tomwalters@281: * generate their own input. In this case, it is better to be able to tomwalters@281: * override the default Initialize function. When creating a new module, do tomwalters@281: * not create a new version of Initialize uness you're sure you know what tomwalters@281: * you're doing! tomwalters@401: * tomwalters@401: * global_parameters stores things like the input filename, output filenames tomwalters@401: * and any other metadata that modules might want to share. If present, it tomwalters@401: * is propagated to all children. These parameters are mutable and may tomwalters@401: * change. tomwalters@268: */ tomwalters@401: virtual bool Initialize(const SignalBank &input, tomwalters@401: Parameters *global_parameters); tomwalters@268: tomwalters@281: /*! \brief Returns true if the module has been correctly initialized tomwalters@281: * \return true if module has been initialized, false otherwise tomwalters@268: */ tomwalters@268: bool initialized() const; tomwalters@268: tomwalters@268: /* \brief Add a target to this module. Whenever it generates a new tomwalters@268: * output, this module will push its output to all its targets. tomwalters@281: * \param target_module Pointer to a target Module to add. tomwalters@281: * \return true on success, false on failure. tomwalters@281: * tomwalters@281: * When a pointer is passed as a target to the module, the caller retains tomwalters@281: * ownership of the module that it points to. The pointed-to module must tomwalters@281: * continue to exist until it is deleted from the target list by a call tomwalters@281: * to DeleteTarget() or DeleteAllTargets(), or the current module is tomwalters@281: * destroyed. Bad things will happen if the Module pointed to is deleted tomwalters@281: * and Initialize(), Reset() or Process() is subsequently called. tomwalters@268: */ tomwalters@268: bool AddTarget(Module* target_module); tomwalters@268: tomwalters@281: /*! \brief Remove a previously added target module from the list of targets tomwalters@281: * for this module. tomwalters@281: * \param target_module Pointer to the module to remove. This must be a tomwalters@281: * pointer that was previously passed to AddTarget() tomwalters@281: * \return true on success, false on failure. tomwalters@268: */ tomwalters@281: bool RemoveTarget(Module* target_module); tomwalters@268: tomwalters@281: /*! \brief Remove all previously added target modules from the list of tomwalters@281: * targets for this module. tomwalters@268: */ tomwalters@281: void RemoveAllTargets(); tomwalters@268: tomwalters@281: /*! \brief Process a buffer. tomwalters@281: * \param input SignalBank of the form which was passed to Initialize() tomwalters@281: * tomwalters@281: * Process is called once for each input SignalBank. When implemented in tomwalters@281: * classes inheriting from aimc::Module, P tomwalters@281: * this SignalBank contains the (read-only) input to the module. It is tomwalters@281: * expected that the input SignalBank will have the same number of channels, tomwalters@281: * buffer length and sample rate as the SignalBank passed to Initialize. tomwalters@268: */ tomwalters@268: virtual void Process(const SignalBank &input) = 0; tomwalters@268: tomwalters@275: /*! \brief Reset the internal state of this module and all its children to tomwalters@275: * their initial state. tomwalters@281: * tomwalters@281: * Like a call to Initialize() will cause all target modules to be tomwalters@281: * initialized, a call to Reset() will cause all target modules to be reset. tomwalters@268: */ tomwalters@280: void Reset(); tomwalters@268: tomwalters@281: /*! \brief Return a pointer to the output SignalBank_ for this class. tomwalters@281: * \return pointer to the SignalBank that this module uses to store its tomwalters@281: * output. tomwalters@268: */ tomwalters@268: const SignalBank* GetOutputBank() const; tomwalters@268: tomwalters@323: void PrintTargets(ostream &out); tomwalters@402: void PrintTargetsForDot(ostream &out); tomwalters@402: void PrintConfiguration(ostream &out); tomwalters@323: tomwalters@296: string version() const { tomwalters@296: return module_version_; tomwalters@296: } tomwalters@296: tomwalters@296: string id() const { tomwalters@296: return module_identifier_; tomwalters@296: } tomwalters@296: tomwalters@296: string description() const { tomwalters@296: return module_description_; tomwalters@296: } tomwalters@296: tomwalters@296: string type() const { tomwalters@296: return module_type_; tomwalters@296: } tomwalters@402: tomwalters@402: bool done() { tomwalters@402: return done_; tomwalters@402: } tomwalters@402: tomwalters@402: void set_instance_name(string instance_name) { tomwalters@402: instance_name_ = instance_name; tomwalters@402: } tomwalters@402: tomwalters@402: string instance_name() { tomwalters@402: return instance_name_; tomwalters@402: } tomwalters@296: tomwalters@268: protected: tomwalters@268: void PushOutput(); tomwalters@268: tomwalters@275: virtual void ResetInternal() = 0; tomwalters@275: tomwalters@268: virtual bool InitializeInternal(const SignalBank &input) = 0; tomwalters@268: tomwalters@268: bool initialized_; tomwalters@402: bool done_; tomwalters@268: set targets_; tomwalters@268: SignalBank output_; tomwalters@268: Parameters* parameters_; tomwalters@401: Parameters* global_parameters_; tomwalters@268: tomwalters@268: string module_identifier_; tomwalters@268: string module_type_; tomwalters@268: string module_description_; tomwalters@268: string module_version_; tomwalters@402: tomwalters@402: string instance_name_; tomwalters@268: tomwalters@268: private: tomwalters@268: DISALLOW_COPY_AND_ASSIGN(Module); tomwalters@268: }; tomwalters@268: } tomwalters@268: tomwalters@283: #endif // AIMC_SUPPORT_MODULE_H_