// file: $isip/class/dstr/CircularDelayLine/CircularDelayLine.h // version: $Id: CircularDelayLine.h 7353 2001-09-02 16:57:24Z jelinek $ // // make sure definitions are made only once // #ifndef ISIP_CIRCULAR_DELAY_LINE #define ISIP_CIRCULAR_DELAY_LINE // isip include files // #ifndef ISIP_VECTOR #include #endif // CircularDelayLine: a class that implements a tapped delay line using a // circular buffer. this is a very convenient data structure for many // functions in digital signal processing. hence, the interface is intended // to be simple and easy to use for such applications. // template class CircularDelayLine { //--------------------------------------------------------------------------- // // public constants // //--------------------------------------------------------------------------- public: // define the class name // static const String CLASS_NAME; //---------------------------------------- // // i/o related constants // //---------------------------------------- static const String DEF_PARAM; static const String PARAM_INDEX; static const String PARAM_BUFFER; //---------------------------------------- // // default values and arguments // //---------------------------------------- // define the default value(s) of the class data // static const int32 DEF_LENGTH = 1024; static const int32 DEF_INDEX = 0; // default arguments to methods // static const int32 DEF_INCREMENT = 1; //---------------------------------------- // // error codes // //---------------------------------------- static const int32 ERR = 41900; //--------------------------------------------------------------------------- // // protected data // //--------------------------------------------------------------------------- protected: // allocate internal storage for the buffer // Vector v_d; // allocate a pointer for the current location // Long index_d; // define a static debug level for all objects of this class // static Integral::DEBUG debug_level_d; // define the memory manager // static MemoryManager mgr_d; //--------------------------------------------------------------------------- // // required public methods // //--------------------------------------------------------------------------- public: // static methods: // diagnose method is moved outside the class header file and // defined in the CircularDelayLineDiagnose.h in order to avoid // issues related to preprocessing of the diagnose code. // static const String& name(); // method: setDebug // static bool8 setDebug(Integral::DEBUG debug_level) { debug_level_d = debug_level; return true; } // other debug methods // bool8 debug(const unichar* message) const; // method: destructor // ~CircularDelayLine() {} // default constructor // CircularDelayLine(int32 length = DEF_LENGTH); // method: copy constructor // CircularDelayLine(const CircularDelayLine& arg) { assign(arg); } // assign methods // bool8 assign(const CircularDelayLine& arg); // method: operator= // CircularDelayLine& operator= (const CircularDelayLine& arg) { assign(arg); return *this; } // equality methods // bool8 eq(const CircularDelayLine& arg) const; // method: sofSize // int32 sofSize() const { int32 bytes = index_d.sofSize(); bytes += v_d.sofSize(); return bytes; } // method: read // bool8 read(Sof& sof, int32 tag) { return read(sof, tag, name()); } // method: write // bool8 write(Sof& sof, int32 tag) const { return write(sof, tag, name()); } // other io methods // bool8 read(Sof& sof, int32 tag, const String& name); bool8 write(Sof& sof, int32 tag, const String& name) const; bool8 readData(Sof& sof, const String& pname = DEF_PARAM, int32 size = SofParser::FULL_OBJECT, bool8 param = true, bool8 nested = false); bool8 writeData(Sof& sof, const String& pname = DEF_PARAM) const; // method: new // static void* operator new(size_t size) { return mgr_d.get(); } // method: new[] // static void* operator new[](size_t size) { return mgr_d.getBlock(size); } // method: delete // static void operator delete(void* ptr) { mgr_d.release(ptr); } // method: delete[] // static void operator delete[](void* ptr) { mgr_d.releaseBlock(ptr); } // method: setGrowSize // static bool8 setGrowSize(int32 grow_size) { return mgr_d.setGrow(grow_size); } // method: clear // bool8 clear(Integral::CMODE cmode = Integral::DEF_CMODE) { // call the vector clear // v_d.clear(cmode); // clear the index in any case // index_d = DEF_INDEX; return true; } //--------------------------------------------------------------------------- // // class-specific public methods: // extensions to required methods // //--------------------------------------------------------------------------- // method: assign // bool8 assign(const TObject& arg) { v_d(index_d) = arg; return true; } // method: operator= // TObject& operator= (const TObject& arg) { assign(arg); return *this; } //--------------------------------------------------------------------------- // // class-specific public methods: // indexing methods // //--------------------------------------------------------------------------- // method: operator() // TObject& operator() (int32 index) { int32 tmp_index = index_d + index; tmp_index = wrap(tmp_index); return v_d(tmp_index); } // method: operator() // const TObject& operator() (int32 index) const { int32 tmp_index = index_d + index; tmp_index = wrap(tmp_index); return v_d(tmp_index); } //--------------------------------------------------------------------------- // // class-specific public methods: // size-related methods // //--------------------------------------------------------------------------- // method: setLength // bool8 setLength(int32 length) { return v_d.setLength(length); } // method: length // int32 length() const { return v_d.length(); } //--------------------------------------------------------------------------- // // class-specific public methods: // core data manipulation methods // //--------------------------------------------------------------------------- // method: advance // bool8 advance(int32 increment = DEF_INCREMENT) { index_d += increment; index_d = wrap(index_d); return true; } // method: advanceAndAssign // bool8 advanceAndAssign(const TObject& input, int32 increment = DEF_INCREMENT) { bool8 status = advance(increment); v_d(index_d) = input; return status; } // method: assignAndAdvance // bool8 assignAndAdvance(const TObject& input, int32 increment = DEF_INCREMENT) { v_d(index_d) = input; return advance(increment); } //--------------------------------------------------------------------------- // // private methods // //--------------------------------------------------------------------------- private: // pointer manipulation methods // int32 wrap(int32 value) const; }; //----------------------------------------------------------------------------- // // we define non-integral constants at the end of class definition for // templates (for non-templates these are defined in the default constructor) // //----------------------------------------------------------------------------- // constants: required constants such as the class name // template const String CircularDelayLine::CLASS_NAME(L"CircularDelayLine"); // constants: define non-integral constants in the default constructor // template const String CircularDelayLine::DEF_PARAM(L""); template const String CircularDelayLine::PARAM_INDEX(L"index"); template const String CircularDelayLine::PARAM_BUFFER(L"buffer"); // static instantiations: debug level // template Integral::DEBUG CircularDelayLine::debug_level_d = Integral::NONE; template MemoryManager CircularDelayLine::mgr_d(sizeof(CircularDelayLine), CLASS_NAME); // below are all the methods for the CircularDelayLine template class // //----------------------------------------------------------------------------- // // required static methods // //----------------------------------------------------------------------------- // method: name // // arguments: none // // return: a static String& containing the class name // // this method returns the class name // template const String& CircularDelayLine::name() { // create the static name string for this class and return it // static String cname(CLASS_NAME); cname.clear(); cname.concat(CLASS_NAME); cname.concat(L"<"); cname.concat(TObject::name()); cname.concat(L">"); // return the name // return cname; } //--------------------------------------------------------------------- // // required debug methods // //---------------------------------------------------------------------- // method: debug // // arguments: // const unichar* message: (input) information message // // return: a bool8 value indicating status // // this method dumps the contents of an object to the console // template bool8 CircularDelayLine::debug(const unichar* message_a) const { // local variables // String output; String value; String param; // output the current position // value.assign(index_d); output.debugStr(name(), message_a, L"index_d", value); Console::put(output); // output the debug level // value.assign(debug_level_d); output.debugStr(name(), message_a, L"debug_level_d", value); Console::put(output); // output a label // output.assign(L"delay line:"); Console::put(output); // increment the indention level in the console // Console::increaseIndention(); // output the delay line // v_d.debug(L"v_d"); // decrement the indention level in the console // Console::decreaseIndention(); // exit gracefully // return true; } //----------------------------------------------------------------------- // // default constructor // //----------------------------------------------------------------------- // method: default constructor // // arguments: // int32 length: (input) the length of the buffer // // return: none // // note that the "capacity" and length are the same for this class. // template CircularDelayLine::CircularDelayLine(int32 length_a) { // initialize the stored item // v_d.setLength(length_a); // initialize the position indices // index_d = DEF_INDEX; // exit gracefully // } //----------------------------------------------------------------------- // // required assign method(s) // //----------------------------------------------------------------------- // method: assign // // arguments: // const CircularDelayLine& arg: (input) the object to copy // // return: a bool8 value indicating status // template bool8 CircularDelayLine::assign(const CircularDelayLine& arg_a) { // assign the scalar data // index_d = arg_a.index_d; // assign the vector data // return v_d.assign(arg_a.v_d); } //----------------------------------------------------------------------- // // required i/o methods // //----------------------------------------------------------------------- // method: read // // arguments: // Sof& sof: (input) sof file object // int32 tag: (input) sof object instance tag // const String& name: (input) sof object instance name // // return: a bool8 value indicating status // // this method has the object read itself from an Sof file // template bool8 CircularDelayLine::read(Sof& sof_a, int32 tag_a, const String& name_a) { // get the instance of the object from the Sof file // if (!sof_a.find(name_a, tag_a)) { return false; } // read the actual data from the sof file // if (!readData(sof_a)) { return false; } // exit gracefully // return true; } // method: write // // arguments: // Sof& sof: (input) sof file object // int32 tag: (input) sof object instance tag // const String& name: (input) sof object instance name // // return: a bool8 value indicating status // // this method has the object write itself to an Sof file // template bool8 CircularDelayLine::write(Sof& sof_a, int32 tag_a, const String& name_a) const { // declare a temporary size variable // int32 obj_size; // switch on ascii or binary mode // if (sof_a.isText()) { // set the size to be dynamic // obj_size = Sof::ANY_SIZE; } else { // the size of the binary data to write // obj_size = sofSize(); } // put the object into the sof file's index // if (!sof_a.put(name_a, tag_a, obj_size)) { return false; } // exit gracefully // return writeData(sof_a); } // method: readData // // arguments: // Sof& sof: (input) sof file object // const String& pname: (input) parameter name // int32 size: (input) size of the object // bool8 param: (input) is the parameter specified? // bool8 nested: (input) is this nested? // // return: a bool8 value indicating status // // this method has the object read itself from an Sof file. it assumes // that the Sof file is already positioned correctly. // template bool8 CircularDelayLine::readData(Sof& sof_a, const String& pname_a, int32 size_a, bool8 param_a, bool8 nested_a) { // declare local variable // SofParser parser; parser.setDebug(debug_level_d); // ignore implicit parameter setting // // configure the parser to read a nested object // if (nested_a) { parser.setNest(); } // load the parse // if (!parser.load(sof_a, size_a)) { return Error::handle(name(), L"readData", Error::READ, __FILE__, __LINE__, Error::WARNING); } // get the index // if (parser.isPresent(sof_a, PARAM_INDEX)) { if (!index_d.readData(sof_a, PARAM_INDEX, parser.getEntry(sof_a, PARAM_INDEX), false, false)) { return Error::handle(name(), L"readData", Error::READ, __FILE__, __LINE__, Error::WARNING); } } else { index_d = DEF_INDEX; } // get the buffer // if (parser.isPresent(sof_a, PARAM_BUFFER)) { if (!v_d.readData(sof_a, PARAM_BUFFER, parser.getEntry(sof_a, PARAM_BUFFER), false, false)) { return Error::handle(name(), L"readData", Error::READ, __FILE__, __LINE__, Error::WARNING); } } else { v_d.clear(); } // exit gracefully // return true; } // method: writeData // // arguments: // Sof& sof: (input) sof file object // const String& pname: (input) parameter name // // return: a bool8 value indicating status // // this method writes the object to the Sof file. it assumes that the // Sof file is already positioned correctly. // template bool8 CircularDelayLine::writeData(Sof& sof_a, const String& pname_a) const { // write a start string if necessary // sof_a.writeLabelPrefix(pname_a); // write the index // index_d.writeData(sof_a, PARAM_INDEX); // write the buffer // v_d.writeData(sof_a, PARAM_BUFFER); // put an end string if necessary // sof_a.writeLabelSuffix(pname_a); // exit gracefully // return true; } //------------------------------------------------------------------------ // // required equality methods // //------------------------------------------------------------------------ // method: eq // // arguments: // const CircularDelayLine& arg: (input) the object to compare // // return: bool8 value indicating status // // this method compares two CircularDelayLines for equivalence. two // CircularDelayLines are equivalent if all corresponding valid items are // equivalent // template bool8 CircularDelayLine::eq(const CircularDelayLine& arg_a) const { // compare positions // if (index_d != arg_a.index_d) { return false; } // loop over all elements // int32 i_end = v_d.length(); for (int32 i = 0; i < i_end; i++) { if (v_d(i) != arg_a.v_d(i)) { return false; } } // equal, exit gracefully // return true; } //--------------------------------------------------------------------------- // // private methods // //--------------------------------------------------------------------------- // method: wrap // // arguments: // int32 value: (input) unwrapped location // // return: a int32 value containing the wrapped pointer // // this method limits a location to the range [0, length] // template int32 CircularDelayLine::wrap(const int32 value_a) const { // fetch the length // int32 len = v_d.length(); // compute the modulus // int32 tmp = value_a % len; // also wrap negative values // if (tmp < 0) { tmp += len; } // exit gracefully // return tmp; } // end of include file // #endif