diff --git a/CMakeLists.txt b/CMakeLists.txt index ef57dcb..ce5f3e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,7 @@ project(LASP LANGUAGES C CXX VERSION 1.6.3) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED) +# Experimental: support for Raspberry Pi (64-bit architectures) if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64") set(RPI TRUE) else() @@ -55,7 +56,6 @@ cmake_policy(SET CMP0079 NEW) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake") -include_directories(/usr/include/python3.8) include("BuildType") include("QueryPythonForPybind11") diff --git a/cpp_src/CMakeLists.txt b/cpp_src/CMakeLists.txt index 221b58f..2cca995 100644 --- a/cpp_src/CMakeLists.txt +++ b/cpp_src/CMakeLists.txt @@ -60,4 +60,4 @@ if(DEFINED PY_BUILD_CMAKE_MODULE_NAME) COMPONENT python_modules DESTINATION ${PY_BUILD_CMAKE_MODULE_NAME}) -endif() \ No newline at end of file +endif() diff --git a/python_src/lasp/lasp_octavefilter.py b/python_src/lasp/lasp_octavefilter.py index f8aeb43..72c8601 100644 --- a/python_src/lasp/lasp_octavefilter.py +++ b/python_src/lasp/lasp_octavefilter.py @@ -6,12 +6,10 @@ Author: J.A. de Jong - ASCEE Provides the implementations of (fractional) octave filter banks """ -__all__ = ['FirOctaveFilterBank', 'FirThirdOctaveFilterBank', - 'OverallFilterBank', 'SosOctaveFilterBank', - 'SosThirdOctaveFilterBank'] -from .filter.filterbank_design import (OctaveBankDesigner, - ThirdOctaveBankDesigner) +__all__ = ["OverallFilterBank", "SosOctaveFilterBank", "SosThirdOctaveFilterBank"] + +from .filter.filterbank_design import OctaveBankDesigner, ThirdOctaveBankDesigner from .lasp_cpp import BiquadBank import numpy as np @@ -19,7 +17,7 @@ import numpy as np class OverallFilterBank: """ Dummy type filter bank. Does nothing special, only returns output in a - sensible way + way compatible with SosFilterBank. """ def __init__(self, fs): @@ -51,174 +49,13 @@ class OverallFilterBank: t = np.linspace(tstart, tend, Ncur, endpoint=False) self.N += Ncur - output['Overall'] = {'t': t, 'data': data, 'x': 0} + output["Overall"] = {"t": t, "data": data, "x": 0} return output def decimation(self, x): return [1] -class FirFilterBank: - """ - Single channel (fractional) octave filter bank implementation, based on FIR - filters and sample rate decimation. - """ - - def __init__(self, fs, xmin, xmax): - """ - Initialize a OctaveFilterBank object. - - Args: - fs: Sampling frequency of base signal - - """ - assert np.isclose(fs, 48000), "Only sampling frequency" \ - " available is 48 kHz" - - self.fs = fs - self.xs = list(range(xmin, xmax + 1)) - raise RuntimeError('Not working code anymore') - - maxdecimation = self.designer.firDecimation(self.xs[0]) - self.decimators = [] - for dec in maxdecimation: - self.decimators.append(Decimator(1, dec)) - - xs_d1 = [] - xs_d4 = [] - xs_d16 = [] - xs_d64 = [] - xs_d256 = [] - - self.filterbanks = [] - # Sort the x values in categories according to the required decimation - for x in self.xs: - dec = self.designer.firDecimation(x) - if len(dec) == 1 and dec[0] == 1: - xs_d1.append(x) - elif len(dec) == 1 and dec[0] == 4: - xs_d4.append(x) - elif len(dec) == 2: - xs_d16.append(x) - elif len(dec) == 3: - xs_d64.append(x) - elif len(dec) == 4: - xs_d256.append(x) - else: - raise ValueError(f'No decimation found for x={x}') - - xs_all = [xs_d1, xs_d4, xs_d16, xs_d64, xs_d256] - for xs in xs_all: - nominals_txt = [] - if len(xs) > 0: - firs = np.empty((self.designer.firFilterLength, len(xs)), order='F') - for i, x in enumerate(xs): - # These are the filters that do not require lasp_decimation - # prior to filtering - nominals_txt.append(self.designer.nominal_txt(x)) - firs[:, i] = self.designer.createFirFilter(x) - filterbank = {'fb': pyxFilterBank(firs, 1024), - 'xs': xs, - 'nominals': nominals_txt} - self.filterbanks.append(filterbank) - - # Sample input counter. - self.N = 0 - - self.dec = [1, 4, 16, 64, 256] - - # Filter output counters - # These intial delays are found 'experimentally' using a toneburst - # response. - self.Nf = [915, 806, 780, 582, 338] - - def filterd(self, dec_stage, data): - """ - Filter data for a given decimation stage - - Args: - dec_stage: decimation stage - data: Pre-filtered data - """ - output = {} - if data.shape[0] == 0: - return output - - filtered = self.filterbanks[dec_stage]['fb'].filter_(data) - Nf = filtered.shape[0] - if Nf > 0: - dec = self.dec[dec_stage] - fd = self.fs/dec - - oldNf = self.Nf[dec_stage] - tstart = oldNf/fd - tend = tstart + Nf/fd - - t = np.linspace(tstart, tend, Nf, endpoint=False) - self.Nf[dec_stage] += Nf - for i, nom_txt in enumerate(self.filterbanks[dec_stage]['nominals']): - x = self.designer.nominal_txt_tox(nom_txt) - output[nom_txt] = {'t': t, 'data': filtered[:, [i]], 'x': x} - - return output - - def filter_(self, data): - """ - Filter input data - """ - assert data.ndim == 2 - assert data.shape[1] == 1, "invalid number of channels, should be 1" - - if data.shape[0] == 0: - return {} - - # Output given as a dictionary with x as the key - output = {} - output_unsorted = {} - self.N += data.shape[0] - - output_unsorted = {**output_unsorted, **self.filterd(0, data)} - - for i in range(len(self.decimators)): - dec_stage = i+1 - if data.shape[0] > 0: - # Apply a decimation stage - data = self.decimators[i].decimate(data) - output_unsorted = {**output_unsorted, - **self.filterd(dec_stage, data)} - - # Create sorted output - for x in self.xs: - nom_txt = self.designer.nominal_txt(x) - output[nom_txt] = output_unsorted[nom_txt] - - return output - - def decimation(self, x): - return self.designer.firDecimation(x) - - -class FirOctaveFilterBank(FirFilterBank): - """ - Filter bank which uses FIR filtering for each octave frequency band - """ - - def __init__(self, fs, xmin, xmax): - self.designer = OctaveBankDesigner(fs) - FirFilterBank.__init__(self, fs, xmin, xmax) - - -class FirThirdOctaveFilterBank(FirFilterBank): - """ - Filter bank which uses FIR filtering for each one-third octave frequency - band. - """ - - def __init__(self, fs, xmin, xmax): - self.designer = ThirdOctaveBankDesigner(fs) - FirFilterBank.__init__(self, fs, xmin, xmax) - - class SosFilterBank: def __init__(self, fs, xmin, xmax): """ @@ -247,7 +84,7 @@ class SosFilterBank: channel = self.designer.createSOSFilter(x) if sos is None: sos = empty((channel.size, len(self.xs))) - sos[:, i] = channel.flatten() + sos[:, i] = channel.flatten() self._fb = BiquadBank(sos)