diff --git a/.clang-format b/.clang-format index 7f67d64..1c54d5d 100644 --- a/.clang-format +++ b/.clang-format @@ -1,10 +1,109 @@ ---- -BasedOnStyle: Mozilla -AccessModifierOffset: '-4' + +--- +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true BinPackArguments: true BinPackParameters: true -IndentWidth: '4' +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: false +#BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentGotoLabels: false +IndentPPDirectives: None +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +# Taken from git's rules +PenaltyBreakAssignment: 10 +PenaltyBreakBeforeFirstCallParameter: 30 +PenaltyBreakComment: 10 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakString: 10 +PenaltyExcessCharacter: 100 +PenaltyReturnTypeOnItsOwnLine: 60 + +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatementsExceptControlMacros +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: c++20 +TabWidth: 4 +#UseTab: Always ... diff --git a/.github/workflows/cmake-single-platform.yml b/.github/workflows/cmake-single-platform.yml index 80bfbce..905c241 100644 --- a/.github/workflows/cmake-single-platform.yml +++ b/.github/workflows/cmake-single-platform.yml @@ -26,6 +26,15 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Install clang format + run: | + sudo apt-get update + sudo apt-get install clang-format + + - name: Check format + run: | + find ./ -type f \( -iname \*.h -o -iname \*.cpp \) | xargs clang-format --dry-run -Werror + - name: Install Conan id: conan uses: turtlebrowser/get-conan@main diff --git a/include/sdsp/FilterType.h b/include/sdsp/FilterType.h index c2a175b..25ac4a8 100644 --- a/include/sdsp/FilterType.h +++ b/include/sdsp/FilterType.h @@ -3,10 +3,5 @@ namespace sdsp { - enum class FilterType { - None = 0, - LowPass = 1, - HighPass = 2, - BandPass = 3 - }; +enum class FilterType { None = 0, LowPass = 1, HighPass = 2, BandPass = 3 }; } \ No newline at end of file diff --git a/include/sdsp/casc2orderIIR.h b/include/sdsp/casc2orderIIR.h index cca977a..d2b00eb 100644 --- a/include/sdsp/casc2orderIIR.h +++ b/include/sdsp/casc2orderIIR.h @@ -3,10 +3,10 @@ #include #include -namespace sdsp { -template -class casc2orderIIR +namespace sdsp { +template +class casc2orderIIR { private: int pos{ 0 }; @@ -18,9 +18,12 @@ class casc2orderIIR FilterType fType{ FilterType::None }; public: - casc2orderIIR() { static_assert(M % 2 == 0, "M must be even!"); } + casc2orderIIR() + { + static_assert(M % 2 == 0, "M must be even!"); + } - template + template void Process(Iter begin, Iter end) { constexpr int order{ 2 }; @@ -51,10 +54,8 @@ class casc2orderIIR for (j = 0; j < M; j++) { y.at(j + 1).at(p) = y.at(j).at(p) * b.at(j).at(0); - y.at(j + 1).at(p) += y.at(j).at(d1) * b.at(j).at(j1) - - y.at(j + 1).at(d1) * a.at(j).at(j1); - y.at(j + 1).at(p) += y.at(j).at(d2) * b.at(j).at(j2) - - y.at(j + 1).at(d2) * a.at(j).at(j2); + y.at(j + 1).at(p) += y.at(j).at(d1) * b.at(j).at(j1) - y.at(j + 1).at(d1) * a.at(j).at(j1); + y.at(j + 1).at(p) += y.at(j).at(d2) * b.at(j).at(j2) - y.at(j + 1).at(d2) * a.at(j).at(j2); } *begin = y.at(j).at(p); @@ -191,9 +192,8 @@ class casc2orderIIR } }; -template -class casc_2o_IIR -{ +template +class casc_2o_IIR { protected: int pos{ 0 }; @@ -203,7 +203,7 @@ class casc_2o_IIR std::array, M> aCoeff{ 0 }; - template + template void process_base(Iter begin, Iter end) { constexpr int order{ 2 }; @@ -241,29 +241,28 @@ class casc_2o_IIR } }; -template -class casc_2o_IIR_lp : casc_2o_IIR -{ +template +class casc_2o_IIR_lp : casc_2o_IIR { public: - casc_2o_IIR_lp() { static_assert(M % 2 == 0, "M must be even!"); } + casc_2o_IIR_lp() + { + static_assert(M % 2 == 0, "M must be even!"); + } - template + template void process(Iter begin, Iter end) { this->template process_base>(begin, end); } - static void process_spec(std::array, M + 1>& y, - const std::array, M>& a, + static void process_spec(std::array, M + 1> &y, const std::array, M> &a, int p, int d1, int d2) { for (uint j = 0; j < M; j++) { y.at(j + 1).at(p) = y.at(j).at(p); - y.at(j + 1).at(p) += y.at(j).at(d1) + y.at(j).at(d1) - - y.at(j + 1).at(d1) * a.at(j).at(1); - y.at(j + 1).at(p) += - y.at(j).at(d2) - y.at(j + 1).at(d2) * a.at(j).at(2); + y.at(j + 1).at(p) += y.at(j).at(d1) + y.at(j).at(d1) - y.at(j + 1).at(d1) * a.at(j).at(1); + y.at(j + 1).at(p) += y.at(j).at(d2) - y.at(j + 1).at(d2) * a.at(j).at(2); } } @@ -294,29 +293,28 @@ class casc_2o_IIR_lp : casc_2o_IIR } }; -template -class casc_2o_IIR_hp : casc_2o_IIR -{ +template +class casc_2o_IIR_hp : casc_2o_IIR { public: - casc_2o_IIR_hp() { static_assert(M % 2 == 0, "M must be even!"); } + casc_2o_IIR_hp() + { + static_assert(M % 2 == 0, "M must be even!"); + } - template + template void process(Iter begin, Iter end) { this->template process_base>(begin, end); } - static void process_spec(std::array, M + 1>& y, - const std::array, M>& a, + static void process_spec(std::array, M + 1> &y, const std::array, M> &a, int p, int d1, int d2) { for (uint j = 0; j < M; j++) { y.at(j + 1).at(p) = y.at(j).at(p); - y.at(j + 1).at(p) += -y.at(j).at(d1) - y.at(j).at(d1) - - y.at(j + 1).at(d1) * a.at(j).at(1); - y.at(j + 1).at(p) += - y.at(j).at(d2) - y.at(j + 1).at(d2) * a.at(j).at(2); + y.at(j + 1).at(p) += -y.at(j).at(d1) - y.at(j).at(d1) - y.at(j + 1).at(d1) * a.at(j).at(1); + y.at(j + 1).at(p) += y.at(j).at(d2) - y.at(j + 1).at(d2) * a.at(j).at(2); } } @@ -347,28 +345,28 @@ class casc_2o_IIR_hp : casc_2o_IIR } }; -template -class casc_2o_IIR_bp : casc_2o_IIR -{ +template +class casc_2o_IIR_bp : casc_2o_IIR { public: - casc_2o_IIR_bp() { static_assert(M % 2 == 0, "M must be even!"); } + casc_2o_IIR_bp() + { + static_assert(M % 2 == 0, "M must be even!"); + } - template + template void process(Iter begin, Iter end) { this->template process_base>(begin, end); } - static void process_spec(std::array, M + 1>& y, - const std::array, M>& a, + static void process_spec(std::array, M + 1> &y, const std::array, M> &a, int p, int d1, int d2) { for (uint j = 0; j < M; j++) { y.at(j + 1).at(p) = y.at(j).at(p); y.at(j + 1).at(p) += -y.at(j + 1).at(d1) * a.at(j).at(1); - y.at(j + 1).at(p) += - -y.at(j).at(d2) - y.at(j + 1).at(d2) * a.at(j).at(2); + y.at(j + 1).at(p) += -y.at(j).at(d2) - y.at(j + 1).at(d2) * a.at(j).at(2); } } diff --git a/include/sdsp/fft.h b/include/sdsp/fft.h index 9540de0..0997218 100644 --- a/include/sdsp/fft.h +++ b/include/sdsp/fft.h @@ -7,316 +7,355 @@ namespace sdsp { - //determine highest bit and return its position - //std method is not constexpr so thats why this was created - constexpr uint log2(uint num) - { - uint retValue {0}; - while( (num = num >> 1) > 0u) { - retValue++; - } - return retValue; +//determine highest bit and return its position +//std method is not constexpr so thats why this was created +constexpr uint log2(uint num) +{ + uint retValue{ 0 }; + while ((num = num >> 1) > 0u) { + retValue++; } + return retValue; +} - constexpr uint log4(uint num) - { - uint retValue {0}; - while( (num = num >> 2) > 0u) { - retValue++; - } - return retValue; +constexpr uint log4(uint num) +{ + uint retValue{ 0 }; + while ((num = num >> 2) > 0u) { + retValue++; } + return retValue; +} - //determine if num is a power of 2 - constexpr bool isPowerOf2(uint num) - { - if (num == 0) - return false; - else - return (num & (num - 1)) == 0; - } +//determine if num is a power of 2 +constexpr bool isPowerOf2(uint num) +{ + if (num == 0) + return false; + else + return (num & (num - 1)) == 0; +} - //determine if num is a power of 4 - constexpr bool isPowerOf4(uint num) - { - return isPowerOf2(num) && (log2(num) % 2 == 0); - } +//determine if num is a power of 4 +constexpr bool isPowerOf4(uint num) +{ + return isPowerOf2(num) && (log2(num) % 2 == 0); +} - template - using trig_array = std::array, log2(N)>; +template +using trig_array = std::array, log2(N)>; - template - using coeff_array = std::array, N>, log2(N)>; +template +using coeff_array = std::array, N>, log2(N)>; - template - using complex_array = std::array, N>; +template +using complex_array = std::array, N>; - template - constexpr trig_array calc_trigs_naive() - { - trig_array trigs {0}; - for (size_t i {0}; i < trigs.size(); i++) { - uint pow2 {1u << (i + 1u)}; - for (size_t j {0}; j < trigs.at(i).size(); j++) { - trigs.at(i).at(j) = T::Value(2 * M_PI * j / pow2); - } +template +constexpr trig_array calc_trigs_naive() +{ + trig_array trigs{ 0 }; + for (size_t i{ 0 }; i < trigs.size(); i++) { + uint pow2{ 1u << (i + 1u) }; + for (size_t j{ 0 }; j < trigs.at(i).size(); j++) { + trigs.at(i).at(j) = T::Value(2 * M_PI * j / pow2); } - return trigs; } + return trigs; +} - class sine_calculator +class sine_calculator { +public: + constexpr static double Value0() { - public: - constexpr static double Value0() { return 0.0; } - constexpr static double Value90() { return 1.0; } - constexpr static double Value(double rad) { return std::sin(rad); }; - - //symmetry sign changes - //return either +1 or -1 to indicate sign change - constexpr static double Sym0() { return -1.0; } - constexpr static double Sym90() { return 1.0; } + return 0.0; + } + constexpr static double Value90() + { + return 1.0; + } + constexpr static double Value(double rad) + { + return std::sin(rad); }; - class cosine_calculator + //symmetry sign changes + //return either +1 or -1 to indicate sign change + constexpr static double Sym0() + { + return -1.0; + } + constexpr static double Sym90() + { + return 1.0; + } +}; + +class cosine_calculator { +public: + constexpr static double Value0() { - public: - constexpr static double Value0() { return 1.0; } - constexpr static double Value90() { return 0.0; } - constexpr static double Value(double rad) { return std::cos(rad); }; - - //symmetry sign changes - //return either +1 or -1 to indicate sign change - constexpr static double Sym0() { return 1.0; } - constexpr static double Sym90() { return -1.0; } + return 1.0; + } + constexpr static double Value90() + { + return 0.0; + } + constexpr static double Value(double rad) + { + return std::cos(rad); }; - class reverse_fft + //symmetry sign changes + //return either +1 or -1 to indicate sign change + constexpr static double Sym0() + { + return 1.0; + } + constexpr static double Sym90() { - public: - constexpr static double Sign() { return -1.0; } + return -1.0; + } +}; - template - constexpr static void ScaleValues(complex_array & data) - { - std::for_each(data.begin(), data.end(), [](auto &n) { n *= (1.0 / N); }); - } - }; +class reverse_fft { +public: + constexpr static double Sign() + { + return -1.0; + } - class forward_fft + template + constexpr static void ScaleValues(complex_array &data) { - public: - constexpr static double Sign() { return 1.0; } + std::for_each(data.begin(), data.end(), [](auto &n) { n *= (1.0 / N); }); + } +}; - template - constexpr static void ScaleValues(complex_array &) { } - }; +class forward_fft { +public: + constexpr static double Sign() + { + return 1.0; + } - template - constexpr trig_array calc_trigs() + template + constexpr static void ScaleValues(complex_array &) { - trig_array values {0}; - size_t i {0}; - for ( auto& value : values ) { - uint pow2 {1u << (i + 1u)}; - - //first element at 0 deg - value.at(0) = T::Value0(); - - //i = 0 is special - //just alternate +1 and -1 - if (i == 0) { - for (size_t j {1}; j < value.size(); j++) { - value.at(j) = value.at(j-1) * -1.0; - } - } else { - //calculate up to but not including 90 deg - uint num {1u << (i - 1u)}; - for (uint j {1}; j < num; j++) { - value.at(j) = T::Value(2 * M_PI * j / pow2); - } - //next element is 90 deg - value.at(num) = T::Value90(); - - //now use symmetry to get the rest of the values - int dir {-1}; - double sign {T::Sym90()}; - uint bouncyIndex {num}; - - for (size_t j {num + 1}; j < value.size(); j++) { - bouncyIndex += dir; - value.at(j) = value.at(bouncyIndex) * sign; - if (bouncyIndex == 0) { - dir = 1; - sign *= T::Sym0(); - } else if (bouncyIndex == num) { - dir = -1; - sign *= T::Sym90(); - } + } +}; + +template +constexpr trig_array calc_trigs() +{ + trig_array values{ 0 }; + size_t i{ 0 }; + for (auto &value : values) { + uint pow2{ 1u << (i + 1u) }; + + //first element at 0 deg + value.at(0) = T::Value0(); + + //i = 0 is special + //just alternate +1 and -1 + if (i == 0) { + for (size_t j{ 1 }; j < value.size(); j++) { + value.at(j) = value.at(j - 1) * -1.0; + } + } else { + //calculate up to but not including 90 deg + uint num{ 1u << (i - 1u) }; + for (uint j{ 1 }; j < num; j++) { + value.at(j) = T::Value(2 * M_PI * j / pow2); + } + //next element is 90 deg + value.at(num) = T::Value90(); + + //now use symmetry to get the rest of the values + int dir{ -1 }; + double sign{ T::Sym90() }; + uint bouncyIndex{ num }; + + for (size_t j{ num + 1 }; j < value.size(); j++) { + bouncyIndex += dir; + value.at(j) = value.at(bouncyIndex) * sign; + if (bouncyIndex == 0) { + dir = 1; + sign *= T::Sym0(); + } else if (bouncyIndex == num) { + dir = -1; + sign *= T::Sym90(); } } - i++; } - return values; + i++; } + return values; +} - //form the W coefficients from the cosines and sines arrays - template - constexpr coeff_array calc_wCoeffs() - { - //auto cosines {calc_trigs_naive()}; - auto cosines {calc_trigs()}; - - //auto sines = calc_trigs_naive(); - auto sines {calc_trigs()}; - - coeff_array wCoeffs {0}; +//form the W coefficients from the cosines and sines arrays +template +constexpr coeff_array calc_wCoeffs() +{ + //auto cosines {calc_trigs_naive()}; + auto cosines{ calc_trigs() }; - for (size_t i {0}; i < cosines.size(); i++) { + //auto sines = calc_trigs_naive(); + auto sines{ calc_trigs() }; - for (size_t j {0}; j < cosines.at(i).size(); j++) { - wCoeffs.at(i).at(j) = std::complex(cosines.at(i).at(j), T::Sign() * -1.0 * sines.at(i).at(j)); - } - } - return wCoeffs; - } + coeff_array wCoeffs{ 0 }; - //reverse the order of bits/digits - template - constexpr uint digit_reverse(uint n) - { - constexpr uint numBits {log2(base)}; - uint retValue {0}; - uint shift {log2(N) - numBits}; - uint upperBits {(base - 1) << shift}; - uint lowerBits {base - 1}; - while (upperBits > lowerBits) { - retValue |= (n & upperBits) >> shift; - retValue |= (n & lowerBits) << shift; - upperBits = upperBits >> numBits; - lowerBits = lowerBits << numBits; - shift -= numBits * 2; - } - if (upperBits == lowerBits) { - retValue |= n & upperBits; + for (size_t i{ 0 }; i < cosines.size(); i++) { + for (size_t j{ 0 }; j < cosines.at(i).size(); j++) { + wCoeffs.at(i).at(j) = std::complex(cosines.at(i).at(j), T::Sign() * -1.0 * sines.at(i).at(j)); } - return retValue; } + return wCoeffs; +} - template - constexpr std::array calc_swap_lookup() - { - //first create an array where every element value is reversed bits of the index - std::array swapLookup {0}; - - for (size_t i {0}; i < N; i++) { - swapLookup.at(i) = digit_reverse(static_cast(i)); - } - //then go through one more time and for every pair, unreverse the one with the higher index - //this prevents the swap from occuring twice, which would undo the swap - for (size_t i {1}; i < N - 1; i++) { - uint i2 {swapLookup.at(i)}; - if (i2 != i) { - swapLookup.at(i2) = i2; - } - } - return swapLookup; +//reverse the order of bits/digits +template +constexpr uint digit_reverse(uint n) +{ + constexpr uint numBits{ log2(base) }; + uint retValue{ 0 }; + uint shift{ log2(N) - numBits }; + uint upperBits{ (base - 1) << shift }; + uint lowerBits{ base - 1 }; + while (upperBits > lowerBits) { + retValue |= (n & upperBits) >> shift; + retValue |= (n & lowerBits) << shift; + upperBits = upperBits >> numBits; + lowerBits = lowerBits << numBits; + shift -= numBits * 2; + } + if (upperBits == lowerBits) { + retValue |= n & upperBits; } + return retValue; +} - template - void fft_radix2(complex_array & data) - { - static_assert(isPowerOf2(N), "FFT size must be a power of 2!"); - - //compile time calculations - constexpr static auto wCoeffs {calc_wCoeffs()}; - constexpr static auto swapLookup {calc_swap_lookup()}; - - //decimation in time - //perform swap on inputs - for (uint i {1}; i < N - 1; i++) { - uint i2 {swapLookup.at(i)}; - if (i2 != i) - std::swap(data.at(i), data.at(i2)); +template +constexpr std::array calc_swap_lookup() +{ + //first create an array where every element value is reversed bits of the index + std::array swapLookup{ 0 }; + + for (size_t i{ 0 }; i < N; i++) { + swapLookup.at(i) = digit_reverse(static_cast(i)); + } + //then go through one more time and for every pair, unreverse the one with the higher index + //this prevents the swap from occuring twice, which would undo the swap + for (size_t i{ 1 }; i < N - 1; i++) { + uint i2{ swapLookup.at(i) }; + if (i2 != i) { + swapLookup.at(i2) = i2; } + } + return swapLookup; +} - //outer most loop is the FFT stages - for (uint i {0}; i < log2(N); i++) { - uint two_raised_to_i {1u << i}; +template +void fft_radix2(complex_array &data) +{ + static_assert(isPowerOf2(N), "FFT size must be a power of 2!"); + + //compile time calculations + constexpr static auto wCoeffs{ calc_wCoeffs() }; + constexpr static auto swapLookup{ calc_swap_lookup() }; + + //decimation in time + //perform swap on inputs + for (uint i{ 1 }; i < N - 1; i++) { + uint i2{ swapLookup.at(i) }; + if (i2 != i) + std::swap(data.at(i), data.at(i2)); + } - //the inside 2 loops perform the butterfly pattern - for (uint j = 0; j < N; j += (two_raised_to_i << 1)) { + //outer most loop is the FFT stages + for (uint i{ 0 }; i < log2(N); i++) { + uint two_raised_to_i{ 1u << i }; - for (uint k {0}; k < two_raised_to_i; k++) { - uint index1 {j + k}; - uint index2 {j + k + two_raised_to_i}; + //the inside 2 loops perform the butterfly pattern + for (uint j = 0; j < N; j += (two_raised_to_i << 1)) { + for (uint k{ 0 }; k < two_raised_to_i; k++) { + uint index1{ j + k }; + uint index2{ j + k + two_raised_to_i }; - //optimization from page 145 - std::complex temp {data.at(index2) * wCoeffs.at(i).at(index1)}; - std::complex val1 {data.at(index1) + temp}; - std::complex val2 {data.at(index1) - temp}; + //optimization from page 145 + std::complex temp{ data.at(index2) * wCoeffs.at(i).at(index1) }; + std::complex val1{ data.at(index1) + temp }; + std::complex val2{ data.at(index1) - temp }; - data.at(index1) = val1; - data.at(index2) = val2; - } + data.at(index1) = val1; + data.at(index2) = val2; } } - - //if reverse, scale the data by 1/N - //if forward, does nothing - T::ScaleValues(data); } - template - void fft_radix4(complex_array & data) - { - static_assert(isPowerOf4(N), "FFT radix 4 size must be a power of 4!"); - - //compile time calculations - constexpr static auto wCoeffs {calc_wCoeffs()}; - constexpr static auto swapLookup {calc_swap_lookup()}; - constexpr static uint coeff_subscript {log2(N) - 1}; - - for (uint i {0}; i < log4(N); i++) { - uint i_group_size {static_cast(N) / (4u << (2u * i))}; - uint four_raised_to_n {i > 0 ? 1u << ((i - 1u) * 2u) : 0}; - - uint j2 {0}; - for (uint j {0}; j < N; j += (i_group_size << 2)) { - - for (uint k {0}; k < i_group_size; k++) { - uint index1 {k + j}; - uint index2 {k + i_group_size + j}; - uint index3 {k + 2 * i_group_size + j}; - uint index4 {k + 3 * i_group_size + j}; - uint coeff_index1 {(index1 - j) * four_raised_to_n * (j2 % 4)}; - uint coeff_index2 {(index2 - j) * four_raised_to_n * (j2 % 4)}; - uint coeff_index3 {(index3 - j) * four_raised_to_n * (j2 % 4)}; - uint coeff_index4 {(index4 - j) * four_raised_to_n * (j2 % 4)}; - - std::complex temp1 {coeff_index1 > 0 ? data.at(index1) * wCoeffs.at(coeff_subscript).at(coeff_index1):data.at(index1)}; - std::complex temp2 {coeff_index2 > 0 ? data.at(index2) * wCoeffs.at(coeff_subscript).at(coeff_index2):data.at(index2)}; - std::complex temp3 {coeff_index3 > 0 ? data.at(index3) * wCoeffs.at(coeff_subscript).at(coeff_index3):data.at(index3)}; - std::complex temp4 {coeff_index4 > 0 ? data.at(index4) * wCoeffs.at(coeff_subscript).at(coeff_index4):data.at(index4)}; - std::complex temp2_timesi {T::Sign() * std::complex(-temp2.imag(), temp2.real())}; - std::complex temp4_timesi {T::Sign() * std::complex(-temp4.imag(), temp4.real())}; - - data.at(index1) = temp1 + temp2 + temp3 + temp4; - data.at(index2) = temp1 - temp2_timesi - temp3 + temp4_timesi; - data.at(index3) = temp1 - temp2 + temp3 - temp4; - data.at(index4) = temp1 + temp2_timesi - temp3 - temp4_timesi; - } - j2++; - } - } + //if reverse, scale the data by 1/N + //if forward, does nothing + T::ScaleValues(data); +} - for (uint i {1}; i < N - 1; i++) { - uint i2 {swapLookup.at(i)}; - if (i2 != i) - std::swap(data.at(i), data.at(i2)); +template +void fft_radix4(complex_array &data) +{ + static_assert(isPowerOf4(N), "FFT radix 4 size must be a power of 4!"); + + //compile time calculations + constexpr static auto wCoeffs{ calc_wCoeffs() }; + constexpr static auto swapLookup{ calc_swap_lookup() }; + constexpr static uint coeff_subscript{ log2(N) - 1 }; + + for (uint i{ 0 }; i < log4(N); i++) { + uint i_group_size{ static_cast(N) / (4u << (2u * i)) }; + uint four_raised_to_n{ i > 0 ? 1u << ((i - 1u) * 2u) : 0 }; + + uint j2{ 0 }; + for (uint j{ 0 }; j < N; j += (i_group_size << 2)) { + for (uint k{ 0 }; k < i_group_size; k++) { + uint index1{ k + j }; + uint index2{ k + i_group_size + j }; + uint index3{ k + 2 * i_group_size + j }; + uint index4{ k + 3 * i_group_size + j }; + uint coeff_index1{ (index1 - j) * four_raised_to_n * (j2 % 4) }; + uint coeff_index2{ (index2 - j) * four_raised_to_n * (j2 % 4) }; + uint coeff_index3{ (index3 - j) * four_raised_to_n * (j2 % 4) }; + uint coeff_index4{ (index4 - j) * four_raised_to_n * (j2 % 4) }; + + std::complex temp1{ coeff_index1 > 0 ? + data.at(index1) * wCoeffs.at(coeff_subscript).at(coeff_index1) : + data.at(index1) }; + std::complex temp2{ coeff_index2 > 0 ? + data.at(index2) * wCoeffs.at(coeff_subscript).at(coeff_index2) : + data.at(index2) }; + std::complex temp3{ coeff_index3 > 0 ? + data.at(index3) * wCoeffs.at(coeff_subscript).at(coeff_index3) : + data.at(index3) }; + std::complex temp4{ coeff_index4 > 0 ? + data.at(index4) * wCoeffs.at(coeff_subscript).at(coeff_index4) : + data.at(index4) }; + std::complex temp2_timesi{ T::Sign() * std::complex(-temp2.imag(), temp2.real()) }; + std::complex temp4_timesi{ T::Sign() * std::complex(-temp4.imag(), temp4.real()) }; + + data.at(index1) = temp1 + temp2 + temp3 + temp4; + data.at(index2) = temp1 - temp2_timesi - temp3 + temp4_timesi; + data.at(index3) = temp1 - temp2 + temp3 - temp4; + data.at(index4) = temp1 + temp2_timesi - temp3 - temp4_timesi; + } + j2++; } + } - //if reverse, scale the data by 1/N - //if forward, does nothing - T::ScaleValues(data); + for (uint i{ 1 }; i < N - 1; i++) { + uint i2{ swapLookup.at(i) }; + if (i2 != i) + std::swap(data.at(i), data.at(i2)); } + + //if reverse, scale the data by 1/N + //if forward, does nothing + T::ScaleValues(data); +} } diff --git a/test/testFFT.cpp b/test/testFFT.cpp index 5e72d63..57583b5 100644 --- a/test/testFFT.cpp +++ b/test/testFFT.cpp @@ -5,9 +5,9 @@ template double calc_max_error(const sdsp::complex_array &observed, const sdsp::complex_array &expected) { - std::array error {0}; + std::array error{ 0 }; - for (size_t i {0}; i < error.size(); i++) { + for (size_t i{ 0 }; i < error.size(); i++) { error.at(i) = std::abs(observed.at(i) - expected.at(i)); } @@ -16,15 +16,15 @@ double calc_max_error(const sdsp::complex_array &observed, const sdsp::comple TEST_CASE("FFT Radix 2 test", "[single-file]") { - constexpr uint N {64}; - constexpr uint n {7}; - sdsp::complex_array s {0}; - + constexpr uint N{ 64 }; + constexpr uint n{ 7 }; + sdsp::complex_array s{ 0 }; + for (size_t i = 0; i < s.size(); i++) { s.at(i) = std::cos(n * 2 * M_PI * static_cast(i) / N); } - sdsp::complex_array S {0}; + sdsp::complex_array S{ 0 }; S.at(n) = N / 2; S.at(N - n) = N / 2; @@ -32,16 +32,16 @@ TEST_CASE("FFT Radix 2 test", "[single-file]") { sdsp::fft_radix2(s); - double max_error {calc_max_error(S, s)}; + double max_error{ calc_max_error(S, s) }; REQUIRE(max_error < 4 * N * std::numeric_limits::epsilon()); } SECTION("FFT Reverse Test") - { + { sdsp::fft_radix2(S); - double max_error {calc_max_error(S, s)}; + double max_error{ calc_max_error(S, s) }; REQUIRE(max_error < 4 * N * std::numeric_limits::epsilon()); } @@ -49,92 +49,92 @@ TEST_CASE("FFT Radix 2 test", "[single-file]") SECTION("FFT Time shift test") { //s2 shifted 90 degrees from s - sdsp::complex_array s2 {0}; - - for (size_t i {0}; i < s2.size(); i++) { + sdsp::complex_array s2{ 0 }; + + for (size_t i{ 0 }; i < s2.size(); i++) { s2.at(i) = std::cos(n * 2 * M_PI * static_cast(i) / N + (M_PI / 2.0)); } sdsp::fft_radix2(s); sdsp::fft_radix2(s2); - sdsp::complex_array S2 {0}; + sdsp::complex_array S2{ 0 }; S2.at(n) = std::complex(0, N / 2); S2.at(N - n) = std::complex(0, -(N / 2.0)); - double max_error {calc_max_error(S2, s2)}; + double max_error{ calc_max_error(S2, s2) }; REQUIRE(max_error < 4 * N * std::numeric_limits::epsilon()); } } TEST_CASE("FFT Radix 2 linearity", "[single-file]") { - constexpr double freq1 {1000.0}; - constexpr double freq2 {500.0}; - constexpr double fs {8000.0}; - constexpr double a1 {1.5}; - constexpr double a2 {2.5}; - constexpr uint N {256}; + constexpr double freq1{ 1000.0 }; + constexpr double freq2{ 500.0 }; + constexpr double fs{ 8000.0 }; + constexpr double a1{ 1.5 }; + constexpr double a2{ 2.5 }; + constexpr uint N{ 256 }; //test linearity //FFT(a1x1[n]+a2x2[n])=a1FFT(x1[n])+a2FFT(x2[n]) - sdsp::complex_array x1 {0}; - sdsp::complex_array x2 {0}; - for (size_t i {0}; i < x1.size(); i++) { - double value {std::sin(2.0 * M_PI * freq1 * (1.0 / fs) * static_cast(i))}; + sdsp::complex_array x1{ 0 }; + sdsp::complex_array x2{ 0 }; + for (size_t i{ 0 }; i < x1.size(); i++) { + double value{ std::sin(2.0 * M_PI * freq1 * (1.0 / fs) * static_cast(i)) }; x1.at(i) = std::complex(value, 0); - - double value2 {std::sin(2.0 * M_PI * freq2 * (1.0 / fs) * static_cast(i))}; + + double value2{ std::sin(2.0 * M_PI * freq2 * (1.0 / fs) * static_cast(i)) }; x2.at(i) = std::complex(value2, 0); } - sdsp::complex_array a1x1 {x1}; + sdsp::complex_array a1x1{ x1 }; std::for_each(a1x1.begin(), a1x1.end(), [a1](auto &n) { n *= a1; }); - sdsp::complex_array a2x2 {x2}; + sdsp::complex_array a2x2{ x2 }; std::for_each(a2x2.begin(), a2x2.end(), [a2](auto &n) { n *= a2; }); - sdsp::complex_array a1x1_plus_a2x2 {0}; - for (size_t i {0}; i < a1x1_plus_a2x2.size(); i++) { + sdsp::complex_array a1x1_plus_a2x2{ 0 }; + for (size_t i{ 0 }; i < a1x1_plus_a2x2.size(); i++) { a1x1_plus_a2x2.at(i) = a1x1.at(i) + a2x2.at(i); } - sdsp::complex_array fft_data1 {a1x1_plus_a2x2}; + sdsp::complex_array fft_data1{ a1x1_plus_a2x2 }; sdsp::fft_radix2(fft_data1); - sdsp::complex_array fft_data2 {x1}; - sdsp::complex_array fft_data3 {x2}; + sdsp::complex_array fft_data2{ x1 }; + sdsp::complex_array fft_data3{ x2 }; sdsp::fft_radix2(fft_data2); sdsp::fft_radix2(fft_data3); - sdsp::complex_array a1_fft_data2 {fft_data2}; + sdsp::complex_array a1_fft_data2{ fft_data2 }; std::for_each(a1_fft_data2.begin(), a1_fft_data2.end(), [a1](auto &n) { n *= a1; }); - sdsp::complex_array a2_fft_data3 {fft_data3}; + sdsp::complex_array a2_fft_data3{ fft_data3 }; std::for_each(a2_fft_data3.begin(), a2_fft_data3.end(), [a2](auto &n) { n *= a2; }); - sdsp::complex_array a1_fft_data2_plus_a2_fft_data3 {0}; - for (size_t i {0}; i < a1_fft_data2_plus_a2_fft_data3.size(); i++) { + sdsp::complex_array a1_fft_data2_plus_a2_fft_data3{ 0 }; + for (size_t i{ 0 }; i < a1_fft_data2_plus_a2_fft_data3.size(); i++) { a1_fft_data2_plus_a2_fft_data3.at(i) = a1_fft_data2.at(i) + a2_fft_data3.at(i); } //difference should be very close to 0 - double max_error {calc_max_error(fft_data1, a1_fft_data2_plus_a2_fft_data3)}; + double max_error{ calc_max_error(fft_data1, a1_fft_data2_plus_a2_fft_data3) }; REQUIRE(max_error < 4 * N * std::numeric_limits::epsilon()); } TEST_CASE("FFT Radix 4 test", "[single-file]") { - constexpr uint N {64}; - constexpr uint n {7}; - sdsp::complex_array s {0}; - - for (size_t i {0}; i < s.size(); i++) { + constexpr uint N{ 64 }; + constexpr uint n{ 7 }; + sdsp::complex_array s{ 0 }; + + for (size_t i{ 0 }; i < s.size(); i++) { s.at(i) = std::cos(n * 2 * M_PI * static_cast(i) / N); } - sdsp::complex_array S {0}; + sdsp::complex_array S{ 0 }; S.at(n) = N / 2; S.at(N - n) = N / 2; @@ -142,16 +142,16 @@ TEST_CASE("FFT Radix 4 test", "[single-file]") { sdsp::fft_radix4(s); - double max_error {calc_max_error(S, s)}; + double max_error{ calc_max_error(S, s) }; REQUIRE(max_error < 4 * N * std::numeric_limits::epsilon()); } SECTION("FFT Reverse Test") - { + { sdsp::fft_radix4(S); - double max_error {calc_max_error(S, s)}; + double max_error{ calc_max_error(S, s) }; REQUIRE(max_error < 4 * N * std::numeric_limits::epsilon()); } @@ -159,84 +159,84 @@ TEST_CASE("FFT Radix 4 test", "[single-file]") SECTION("FFT Time shift test") { //s2 shifted 90 degrees from s - sdsp::complex_array s2 {0}; - - for (size_t i {0}; i < s2.size(); i++) { + sdsp::complex_array s2{ 0 }; + + for (size_t i{ 0 }; i < s2.size(); i++) { s2.at(i) = std::cos(n * 2 * M_PI * static_cast(i) / N + (M_PI / 2.0)); } sdsp::fft_radix4(s); sdsp::fft_radix4(s2); - sdsp::complex_array S2 {0}; + sdsp::complex_array S2{ 0 }; S2.at(n) = std::complex(0, N / 2); S2.at(N - n) = std::complex(0, -(N / 2.0)); - double max_error {calc_max_error(S2, s2)}; + double max_error{ calc_max_error(S2, s2) }; REQUIRE(max_error < 4 * N * std::numeric_limits::epsilon()); } } TEST_CASE("FFT Radix 4 linearity", "[single-file]") { - constexpr double freq1 {1000.0}; - constexpr double freq2 {500.0}; - constexpr double fs {8000.0}; - constexpr double a1 {1.5}; - constexpr double a2 {2.5}; - constexpr uint N {256}; + constexpr double freq1{ 1000.0 }; + constexpr double freq2{ 500.0 }; + constexpr double fs{ 8000.0 }; + constexpr double a1{ 1.5 }; + constexpr double a2{ 2.5 }; + constexpr uint N{ 256 }; //test linearity //FFT(a1x1[n]+a2x2[n])=a1FFT(x1[n])+a2FFT(x2[n]) - sdsp::complex_array x1 {0}; - sdsp::complex_array x2 {0}; - for (size_t i {0}; i < x1.size(); i++) { - double value {std::sin(2.0 * M_PI * freq1 * (1.0 / fs) * static_cast(i))}; + sdsp::complex_array x1{ 0 }; + sdsp::complex_array x2{ 0 }; + for (size_t i{ 0 }; i < x1.size(); i++) { + double value{ std::sin(2.0 * M_PI * freq1 * (1.0 / fs) * static_cast(i)) }; x1.at(i) = std::complex(value, 0); - - double value2 {std::sin(2.0 * M_PI * freq2 * (1.0 / fs) * static_cast(i))}; + + double value2{ std::sin(2.0 * M_PI * freq2 * (1.0 / fs) * static_cast(i)) }; x2.at(i) = std::complex(value2, 0); } - sdsp::complex_array a1x1 {x1}; + sdsp::complex_array a1x1{ x1 }; std::for_each(a1x1.begin(), a1x1.end(), [a1](auto &n) { n *= a1; }); - sdsp::complex_array a2x2 {x2}; + sdsp::complex_array a2x2{ x2 }; std::for_each(a2x2.begin(), a2x2.end(), [a2](auto &n) { n *= a2; }); - sdsp::complex_array a1x1_plus_a2x2 {0}; - for (size_t i {0}; i < a1x1_plus_a2x2.size(); i++) { + sdsp::complex_array a1x1_plus_a2x2{ 0 }; + for (size_t i{ 0 }; i < a1x1_plus_a2x2.size(); i++) { a1x1_plus_a2x2.at(i) = a1x1.at(i) + a2x2.at(i); } - sdsp::complex_array fft_data1 {a1x1_plus_a2x2}; + sdsp::complex_array fft_data1{ a1x1_plus_a2x2 }; sdsp::fft_radix4(fft_data1); - sdsp::complex_array fft_data2 {x1}; - sdsp::complex_array fft_data3 {x2}; + sdsp::complex_array fft_data2{ x1 }; + sdsp::complex_array fft_data3{ x2 }; sdsp::fft_radix4(fft_data2); sdsp::fft_radix4(fft_data3); - sdsp::complex_array a1_fft_data2 {fft_data2}; + sdsp::complex_array a1_fft_data2{ fft_data2 }; std::for_each(a1_fft_data2.begin(), a1_fft_data2.end(), [a1](auto &n) { n *= a1; }); - sdsp::complex_array a2_fft_data3 {fft_data3}; + sdsp::complex_array a2_fft_data3{ fft_data3 }; std::for_each(a2_fft_data3.begin(), a2_fft_data3.end(), [a2](auto &n) { n *= a2; }); - sdsp::complex_array a1_fft_data2_plus_a2_fft_data3 {0}; + sdsp::complex_array a1_fft_data2_plus_a2_fft_data3{ 0 }; for (size_t i = 0; i < a1_fft_data2_plus_a2_fft_data3.size(); i++) { a1_fft_data2_plus_a2_fft_data3.at(i) = a1_fft_data2.at(i) + a2_fft_data3.at(i); } //difference should be very close to 0 - double max_error {calc_max_error(fft_data1, a1_fft_data2_plus_a2_fft_data3)}; + double max_error{ calc_max_error(fft_data1, a1_fft_data2_plus_a2_fft_data3) }; REQUIRE(max_error < 4 * N * std::numeric_limits::epsilon()); } TEST_CASE("FFT benchmark", "[single-file]") { - sdsp::complex_array<1024> complexValues {0.3535, 0.3535, 0.6464, 1.0607, 0.3535, -1.0607, -1.3535, -0.3535}; + sdsp::complex_array<1024> complexValues{ 0.3535, 0.3535, 0.6464, 1.0607, 0.3535, -1.0607, -1.3535, -0.3535 }; BENCHMARK("Radix2 FFT") { @@ -250,6 +250,5 @@ TEST_CASE("FFT benchmark", "[single-file]") return complexValues; }; - SUCCEED( "Benchmark placeholder assertion" ); - + SUCCEED("Benchmark placeholder assertion"); } diff --git a/test/testIIR.cpp b/test/testIIR.cpp index 2d52348..195c9a7 100644 --- a/test/testIIR.cpp +++ b/test/testIIR.cpp @@ -4,8 +4,7 @@ #include #include -std::tuple, sdsp::FilterType, double, double, double> -csvreadImpulse2(const std::string& filename) +std::tuple, sdsp::FilterType, double, double, double> csvreadImpulse2(const std::string &filename) { std::ifstream myfile; myfile.open(filename); @@ -16,8 +15,7 @@ csvreadImpulse2(const std::string& filename) double fs_out{ 0.0 }; double f0_out{ 0.0 }; double Q_out{ 0.0 }; - myfile >> fType >> comma >> fs_out >> comma >> f0_out >> comma >> Q_out >> - comma >> n >> comma; + myfile >> fType >> comma >> fs_out >> comma >> f0_out >> comma >> Q_out >> comma >> n >> comma; fType_out = static_cast(fType); std::vector impulse(n); @@ -34,10 +32,8 @@ TEST_CASE("Filter test") SECTION("Test impulse response") { std::string path = "../../../test_data/impulse_response"; - for (const auto& entry : std::filesystem::directory_iterator(path)) { - - auto [readImpulse, fType, fs, f0, Q] = - csvreadImpulse2(entry.path().string()); + for (const auto &entry : std::filesystem::directory_iterator(path)) { + auto [readImpulse, fType, fs, f0, Q] = csvreadImpulse2(entry.path().string()); sdsp::casc2orderIIR<4> df; if (fType == sdsp::FilterType::LowPass) { @@ -68,10 +64,8 @@ TEST_CASE("Filter test") constexpr unsigned int blockSize{ 32 }; unsigned int index{ 0 }; - for (index = 0; index <= data2.size() - blockSize; - index += blockSize) { - df2.Process(std::next(data2.begin(), index), - std::next(data2.begin(), index + blockSize)); + for (index = 0; index <= data2.size() - blockSize; index += blockSize) { + df2.Process(std::next(data2.begin(), index), std::next(data2.begin(), index + blockSize)); } if (index < data2.size()) { @@ -96,12 +90,9 @@ TEST_CASE("Filter test") lpFilter.SetLPCoeff(f0, fs); lpFilter.PreloadFilter(steadyValue); lpFilter.Process(steadyLP.begin(), steadyLP.end()); - auto calcError = [steadyValue](double& n) { - n = std::abs(n - steadyValue); - }; + auto calcError = [steadyValue](double &n) { n = std::abs(n - steadyValue); }; std::for_each(steadyLP.begin(), steadyLP.end(), calcError); - double maxErrorLP = - *std::max_element(steadyLP.begin(), steadyLP.end()); + double maxErrorLP = *std::max_element(steadyLP.begin(), steadyLP.end()); REQUIRE(maxErrorLP < 1e-12); } @@ -112,10 +103,9 @@ TEST_CASE("Filter test") hpFilter.SetHPCoeff(f0, fs); hpFilter.PreloadFilter(steadyValue); hpFilter.Process(steadyHP.begin(), steadyHP.end()); - auto calcError = [](double& n) { n = std::abs(n); }; + auto calcError = [](double &n) { n = std::abs(n); }; std::for_each(steadyHP.begin(), steadyHP.end(), calcError); - double maxErrorHP = - *std::max_element(steadyHP.begin(), steadyHP.end()); + double maxErrorHP = *std::max_element(steadyHP.begin(), steadyHP.end()); REQUIRE(maxErrorHP < 1e-12); } @@ -126,10 +116,9 @@ TEST_CASE("Filter test") bpFilter.SetBPCoeff(f0, fs, Q); bpFilter.PreloadFilter(steadyValue); bpFilter.Process(steadyBP.begin(), steadyBP.end()); - auto calcError = [](double& n) { n = std::abs(n); }; + auto calcError = [](double &n) { n = std::abs(n); }; std::for_each(steadyBP.begin(), steadyBP.end(), calcError); - double maxErrorBP = - *std::max_element(steadyBP.begin(), steadyBP.end()); + double maxErrorBP = *std::max_element(steadyBP.begin(), steadyBP.end()); REQUIRE(maxErrorBP < 1e-12); } } @@ -140,14 +129,12 @@ TEST_CASE("LP compile time filter test") SECTION("Test impulse response of LP specialized") { std::string path = "../../../test_data/impulse_response"; - for (const auto& entry : std::filesystem::directory_iterator(path)) { - + for (const auto &entry : std::filesystem::directory_iterator(path)) { //check that filename starts with LP if (entry.path().filename().string().rfind("LP", 0) != 0) continue; - auto [readImpulse, fType, fs, f0, Q] = - csvreadImpulse2(entry.path().string()); + auto [readImpulse, fType, fs, f0, Q] = csvreadImpulse2(entry.path().string()); sdsp::casc_2o_IIR_lp<4> df; if (fType == sdsp::FilterType::LowPass) { @@ -174,10 +161,8 @@ TEST_CASE("LP compile time filter test") constexpr unsigned int blockSize{ 32 }; unsigned int index{ 0 }; - for (index = 0; index <= data2.size() - blockSize; - index += blockSize) { - df2.process(std::next(data2.begin(), index), - std::next(data2.begin(), index + blockSize)); + for (index = 0; index <= data2.size() - blockSize; index += blockSize) { + df2.process(std::next(data2.begin(), index), std::next(data2.begin(), index + blockSize)); } if (index < data2.size()) { @@ -207,7 +192,7 @@ TEST_CASE("LP compile time filter test") df.process(impulse1.begin(), impulse1.end()); df2.process(impulse2.begin(), impulse2.end()); - auto times_two = [](double& n) { n = 2.0 * n; }; + auto times_two = [](double &n) { n = 2.0 * n; }; std::for_each(impulse1.begin(), impulse1.end(), times_two); std::array error{ 0 }; @@ -225,14 +210,12 @@ TEST_CASE("HP compile time filter test") SECTION("Test impulse response of HP specialized") { std::string path = "../../../test_data/impulse_response"; - for (const auto& entry : std::filesystem::directory_iterator(path)) { - + for (const auto &entry : std::filesystem::directory_iterator(path)) { //check that filename starts with HP if (entry.path().filename().string().rfind("HP", 0) != 0) continue; - auto [readImpulse, fType, fs, f0, Q] = - csvreadImpulse2(entry.path().string()); + auto [readImpulse, fType, fs, f0, Q] = csvreadImpulse2(entry.path().string()); sdsp::casc_2o_IIR_hp<4> df; if (fType == sdsp::FilterType::HighPass) { @@ -259,10 +242,8 @@ TEST_CASE("HP compile time filter test") constexpr unsigned int blockSize{ 32 }; unsigned int index{ 0 }; - for (index = 0; index <= data2.size() - blockSize; - index += blockSize) { - df2.process(std::next(data2.begin(), index), - std::next(data2.begin(), index + blockSize)); + for (index = 0; index <= data2.size() - blockSize; index += blockSize) { + df2.process(std::next(data2.begin(), index), std::next(data2.begin(), index + blockSize)); } if (index < data2.size()) { @@ -292,7 +273,7 @@ TEST_CASE("HP compile time filter test") df.process(impulse1.begin(), impulse1.end()); df2.process(impulse2.begin(), impulse2.end()); - auto times_two = [](double& n) { n = 2.0 * n; }; + auto times_two = [](double &n) { n = 2.0 * n; }; std::for_each(impulse1.begin(), impulse1.end(), times_two); std::array error{ 0 }; @@ -310,14 +291,12 @@ TEST_CASE("BP compile time filter test") SECTION("Test impulse response of BP specialized") { std::string path = "../../../test_data/impulse_response"; - for (const auto& entry : std::filesystem::directory_iterator(path)) { - + for (const auto &entry : std::filesystem::directory_iterator(path)) { //check that filename starts with BP if (entry.path().filename().string().rfind("BP", 0) != 0) continue; - auto [readImpulse, fType, fs, f0, Q] = - csvreadImpulse2(entry.path().string()); + auto [readImpulse, fType, fs, f0, Q] = csvreadImpulse2(entry.path().string()); sdsp::casc_2o_IIR_bp<4> df; if (fType == sdsp::FilterType::BandPass) { @@ -344,10 +323,8 @@ TEST_CASE("BP compile time filter test") constexpr unsigned int blockSize{ 32 }; unsigned int index{ 0 }; - for (index = 0; index <= data2.size() - blockSize; - index += blockSize) { - df2.process(std::next(data2.begin(), index), - std::next(data2.begin(), index + blockSize)); + for (index = 0; index <= data2.size() - blockSize; index += blockSize) { + df2.process(std::next(data2.begin(), index), std::next(data2.begin(), index + blockSize)); } if (index < data2.size()) { @@ -378,7 +355,7 @@ TEST_CASE("BP compile time filter test") df.process(impulse1.begin(), impulse1.end()); df2.process(impulse2.begin(), impulse2.end()); - auto times_two = [](double& n) { n = 2.0 * n; }; + auto times_two = [](double &n) { n = 2.0 * n; }; std::for_each(impulse1.begin(), impulse1.end(), times_two); std::array error{ 0 };