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@268: // This program is free software: you can redistribute it and/or modify
tomwalters@268: // it under the terms of the GNU General Public License as published by
tomwalters@268: // the Free Software Foundation, either version 3 of the License, or
tomwalters@268: // (at your option) any later version.
tomwalters@268: //
tomwalters@268: // This program is distributed in the hope that it will be useful,
tomwalters@268: // but WITHOUT ANY WARRANTY; without even the implied warranty of
tomwalters@268: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
tomwalters@268: // GNU General Public License for more details.
tomwalters@268: //
tomwalters@268: // You should have received a copy of the GNU General Public License
tomwalters@268: // along with this program. If not, see .
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@268: * \version \$Id: Module.h 4 2010-02-03 18:44:58Z tcw $
tomwalters@268: */
tomwalters@268:
tomwalters@283: #ifndef AIMC_SUPPORT_MODULE_H_
tomwalters@283: #define AIMC_SUPPORT_MODULE_H_
tomwalters@268:
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@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@268: */
tomwalters@275: virtual bool Initialize(const SignalBank &input);
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@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@268: set targets_;
tomwalters@268: SignalBank output_;
tomwalters@268: Parameters* parameters_;
tomwalters@268:
tomwalters@268: string module_identifier_;
tomwalters@268: string module_type_;
tomwalters@268: string module_description_;
tomwalters@268: string module_version_;
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_