BTK2.0 Development guideline
Design for block processing
In order to achieve a low latency, many signal processing
applications prefer block-unit processing, returning a
block of samples (feature) at each frame. BTK2.0 has a
basic C++ class for such a block process as follows.
template <typename Type, typename ItemType> class FeatureStream : public Countable { public: virtual ~FeatureStream(); const String& name() const { return name_; } unsigned size() const { return size_; } // process a block at a current frame virtual const Type* next(int frame_no = -5) = 0; // return the feature at a current frame const Type* current() { if (frame_no_ < 0) throw jconsistency_error("Frame index (%d) < 0.", frame_no_); return next(frame_no_); } // reset the internal parameters virtual void reset() { frame_no_ = initial_frame_no_; } virtual int frame_no() const { return frame_no_; } protected: FeatureStream(unsigned sz, const String& nm); void set_vector_value(Type *vector, int index, ItemType value); size_t itemsize() { return sizeof(ItemType); }; void increment() { frame_no_++; } const int initial_frame_no_; const unsigned size_; int frame_no_; Type* vector_; private: const String name_; // name of this instance }; |
As shown above,the basic block processing class has the
data, "vector_". The class method, next(),
should update the "vector_" at each frame. The
current frame's data should be accessible via current().
At python level, the "FeatureStream" class works as
an iterator. The "next" method is called at each iteration
of a for-loop and generate the updated data.
C++ coding style guide
We basically follow Bjarne Stroustrup’s and STL's coding styles with several exceptions: Class, Enum and typename.
Naming convention
We should not wast time for "my style is better than your style" arguments. Here, we list basic naming rules from C++ Core Editor Guideline.
Items |
Recommendation |
File names |
C++ header files and source files are named *.h and
*.cc, respectively. The swig wrapper file should be
named *.i.
|
Macros and all the names | Use ALL_CAPS for macro names only |
Classes and enums |
Capitalize the
first letter of each compound word or phrase
and all the letters of the acronym (CapWord)
unless there is a special reason. class MVDRBeamformer { // not MvdrBeamformer ... }; enum FilterType { .... }; |
Class methods |
Start with lower case letters and separate each compound word or phrase with an underscore. |
Class member fields |
End with an
underscore and follow snake case. |
Class instance |
Follow mixedCase (differs from CapWord by initial lowercase character ) |
Constant |
Use same naming convention as for usual variables, no ALL_CAPS, but avoid the constant as much as possible. |
Setter methods |
Start with "set_"
and name it after the variable that will be set
unless there is a special reason. class Subbandeamformer { public: void set_look_direction(float azimuth, float polar_angle); }; |
Getter methods |
Should name the
getter method after the variable that you return,
but do not always need to start with "get_". Getter
methods do not accept any parameters |
Typename |
Names of type
variables should use CapWords preferring short
names: T, AnyStr, Num. template <typename Type, typename ItemType> |
Exceptions of snake case rule | May use camel case
flexibly, for example, for the following case: - number of elements in an array (framesN), - length or size of a block (fftLen), - index number of an array (frameX), and - mathematical symbols for an matrix or vector (Rxx or invR). |
Swig coding style guide
The BTK2.0 implements computationally intensive functions
in C++ and bind them with python modules. We generate the
python binding with Swig.
The relationship between the C++ and python libraries is
specified in *.i files. The names of python components
should follow the PEP8
guideline.