hark-lib (Quick Start Guide)

Usage in Python language

0. Introduction

This tutorial covers some basic usage patterns and best practices to help you get started with HARK.

  • How to import the HARK modules
  • #!/usr/bin/env python3
    
    import hark
    
  • A simple example
  • #!/usr/bin/env python3
    
    import soundfile
    import hark
    
    ## 0. Read the audio file in float format (-1.0 to 1.0). Then convert it to a float in the
    ##    integer range that HARK handles. The example matches the range (-32768.0 to 32768.0)
    ##    close to the 16bit signed integer range (-32768 to 32767).
    ## -----------------------------------------------------------------------------------------
    audio, rate = soundfile.read('input.wav', dtype=numpy.float32)
    audio *= 2**15
    
    ## 1. Set the number of channels (nch) of the audio file, the window size (length) and the
    ##    shift width (advance) for framenized processing.
    ## -----------------------------------------------------------------------------------------
    nch = audio.shape[1]
    length = 512
    advance = 160
    
    ## 2. Frame it using Python's numpy module.
    ## -----------------------------------------------------------------------------------------
    frames = numpy.lib.stride_tricks.sliding_window_view(audio, length, axis=0)[::advance, :, :]
    
    ## [0.], [1.] and [2.] above corresponds to the processing of the AudioStreamFromWave node,
    ## and the frames variable corresponds to the output of the AudioStreamFromWave node.
    ## The hark-lib is designed to seamlessly connect with HARK even for data created using
    ## Python modules.
    
    ## 3. FFT multi-channel audio data with the MultiFFT node. Usage is simple. Just define a
    ##    node with hark.node."NodeName"() and give inputs and parameters to the node arguments.
    ##    The variables name of the argument is the name of the input terminal, and INPUT=frames
    ##    simply passes the data frames to the input terminal named INPUT. 
    ## -----------------------------------------------------------------------------------------
    multifft_node = hark.node.MultiFFT()
    multifft_out = multifft_node(INPUT=frames)
    
    ## 4. Getting the result of the MultiFFT node is easy. It is stored with the output
    ##    terminal name OUTPUT in the namespace of the output variable.
    ##    This is true even if there are multiple outputs of the node.
    ## -----------------------------------------------------------------------------------------
    print(multifft_out.OUTPUT)
    
  • Let’s change the type of window function when performing the Fourier transform.
  • It just gives the parameters of the MultiFFT node as arguments as same as the input terminals as shown below. This alone will change the default CONJ window function to the HAMMING window function.

    multifft_out = multifft_node(INPUT=frames, WINDOW="HAMMING")
    
  • How to access special types supported by HARK (eg Source type)?
  • The interfaces are provided so that it can be handled transparently and directly from Python. Check the following example.
    HARK-specific special object type instantiations can be created from the Python side as hark.harklib.”TypeName”(). Normally you would want to get and process the results output by the node. Even in that case, you can access the member variables directly.

    #!/usr/bin/env python3
    
    import numpy
    import hark
    
    src_object = hark.harklib.Source()
    src_object.id = 1
    src_object.x = [1.0000, 0.0000, 0.0000]
    src_object.power = 37.0
    
    ## If it's a std::vector on C++, it supports both list and numpy.array(list(), dtype.numpy.float32) types.
    src_object.x = numpy.array([0.0000, 0.0000, 1.0000], dtype=numpy.float32)
    
    print(src_object.id)
    print(src_object.x)
    print(src_object.power)
    
  • How to access C++ native container types supported by HARK (eg std::vector, hark::Matrix, hark::Tensor() and std::map > type)?
  • C++ Python
    std::vector<float> vector = {1.0f, 0.0f, 0.0f};
    vector = [1.0, 0.0, 0.0]

    or

    vector = numpy.array(
    [1.0, 0.0, 0.0],
    dtype=numpy.float32)
    hark::Matrix<float> matrix;
    matrix.noalias() = Eigen::Matrix<float, 2, 2,
    Eigen::RowMajor>::Identity();
    matrix = numpy.array(
    [[1 0], [0, 1]],
    dtype=numpy.float32)
    hark::Tensor<float> tensor;
    tensor.data.resize(8);
    for(size_t i=0; i<tensor.data.size(); i++){
    tensor.data[i] = static_cast<float>(i);
    }
    std::vector<float> shape = {2, 2, 2};
    std::swap(tensor.vsize, shape);
    tensor = numpy.array(
    [[[1.0, 2.0], [3.0, 4.0]],
    [[5.0, 6.0], [7.0, 8.0]]],
    dtype=numpy.float32)
    std::map<int, std::vector<float> > map_i_vf;
    map_i_vf[0] = std::vector<float>(3);
    map_i_vf = {0: [0.0, 0.0, 0.0]}

1. Offline processing

2. Online processing

Back to Top