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. 

Code. Feature stream class for block processing
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.

Table. Naming policy
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.