/* ============================================================================== This file is part of the JUCE library. Copyright (c) 2022 - Raw Material Software Limited JUCE is an open source library subject to commercial or open-source licensing. By using JUCE, you agree to the terms of both the JUCE 7 End-User License Agreement and JUCE Privacy Policy. End User License Agreement: www.juce.com/juce-7-licence Privacy Policy: www.juce.com/juce-privacy-policy Or: You may also use this code under the terms of the GPL v3 (see www.gnu.org/licenses). JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE DISCLAIMED. ============================================================================== */ namespace juce { namespace dsp { template static FloatType ncos (size_t order, size_t i, size_t size) noexcept { return std::cos (static_cast (order * i) * MathConstants::pi / static_cast (size - 1)); } template WindowingFunction::WindowingFunction (size_t size, WindowingMethod type, bool normalise, FloatType beta) { fillWindowingTables (size, type, normalise, beta); } template void WindowingFunction::fillWindowingTables (size_t size, WindowingMethod type, bool normalise, FloatType beta) noexcept { windowTable.resize (static_cast (size)); fillWindowingTables (windowTable.getRawDataPointer(), size, type, normalise, beta); } template void WindowingFunction::fillWindowingTables (FloatType* samples, size_t size, WindowingMethod type, bool normalise, FloatType beta) noexcept { switch (type) { case rectangular: { for (size_t i = 0; i < size; ++i) samples[i] = static_cast (1); } break; case triangular: { auto halfSlots = static_cast (0.5) * static_cast (size - 1); for (size_t i = 0; i < size; ++i) samples[i] = static_cast (1.0) - std::abs ((static_cast (i) - halfSlots) / halfSlots); } break; case hann: { for (size_t i = 0; i < size; ++i) { auto cos2 = ncos (2, i, size); samples[i] = static_cast (0.5 - 0.5 * cos2); } } break; case hamming: { for (size_t i = 0; i < size; ++i) { auto cos2 = ncos (2, i, size); samples[i] = static_cast (0.54 - 0.46 * cos2); } } break; case blackman: { constexpr FloatType alpha = 0.16f; for (size_t i = 0; i < size; ++i) { auto cos2 = ncos (2, i, size); auto cos4 = ncos (4, i, size); samples[i] = static_cast (0.5 * (1 - alpha) - 0.5 * cos2 + 0.5 * alpha * cos4); } } break; case blackmanHarris: { for (size_t i = 0; i < size; ++i) { auto cos2 = ncos (2, i, size); auto cos4 = ncos (4, i, size); auto cos6 = ncos (6, i, size); samples[i] = static_cast (0.35875 - 0.48829 * cos2 + 0.14128 * cos4 - 0.01168 * cos6); } } break; case flatTop: { for (size_t i = 0; i < size; ++i) { auto cos2 = ncos (2, i, size); auto cos4 = ncos (4, i, size); auto cos6 = ncos (6, i, size); auto cos8 = ncos (8, i, size); samples[i] = static_cast (1.0 - 1.93 * cos2 + 1.29 * cos4 - 0.388 * cos6 + 0.028 * cos8); } } break; case kaiser: { const double factor = 1.0 / SpecialFunctions::besselI0 (beta); const auto doubleSize = (double) size; for (size_t i = 0; i < size; ++i) samples[i] = static_cast (SpecialFunctions::besselI0 (beta * std::sqrt (1.0 - std::pow (((double) i - 0.5 * (doubleSize - 1.0)) / ( 0.5 * (doubleSize - 1.0)), 2.0))) * factor); } break; case numWindowingMethods: default: jassertfalse; break; } // DC frequency amplitude must be one if (normalise) { FloatType sum (0); for (size_t i = 0; i < size; ++i) sum += samples[i]; auto factor = static_cast (size) / sum; FloatVectorOperations::multiply (samples, factor, static_cast (size)); } } template void WindowingFunction::multiplyWithWindowingTable (FloatType* samples, size_t size) noexcept { FloatVectorOperations::multiply (samples, windowTable.getRawDataPointer(), jmin (static_cast (size), windowTable.size())); } template const char* WindowingFunction::getWindowingMethodName (WindowingMethod type) noexcept { switch (type) { case rectangular: return "Rectangular"; case triangular: return "Triangular"; case hann: return "Hann"; case hamming: return "Hamming"; case blackman: return "Blackman"; case blackmanHarris: return "Blackman-Harris"; case flatTop: return "Flat Top"; case kaiser: return "Kaiser"; case numWindowingMethods: default: jassertfalse; return ""; } } template class WindowingFunction; template class WindowingFunction; } // namespace dsp } // namespace juce