// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once #include "Transform.hpp" #include #include #include namespace audio::transcode { /** * @brief Basic decimation transformation - for every Ratio samples it drops * Ratio - 1 samples. The transformation is performed using basic integer type * to allow compiler to perform loop optimizations. The transformation is performed * in-place. * * @tparam SampleType - type of a single PCM sample, e.g., std::uint16_t for LPCM16 * @tparam Channels - number of channels; 1 for mono, 2 for stereo * @tparam Ratio - order of the decimator; e.g.: for Ratio = 4 drops 3 sample for each block of 4 * reducing sample rate by the factor of 4. */ template class BasicDecimator : public Transform { static_assert(Channels == 1 || Channels == 2); static_assert(std::is_integral::value); static_assert(Ratio > 0); /** * @brief Integer type to be used to read and write data from/to a buffer. */ using IntegerType = typename decltype(utils::integer::getIntegerType())::type; public: auto transformBlockSize(std::size_t blockSize) const noexcept -> std::size_t override { return blockSize / Ratio; } auto transformBlockSizeInverted(std::size_t blockSize) const noexcept -> std::size_t override { return blockSize * Ratio; } auto transformFormat(const audio::AudioFormat &inputFormat) const noexcept -> audio::AudioFormat override { return audio::AudioFormat{ inputFormat.getSampleRate() / Ratio, inputFormat.getBitWidth(), inputFormat.getChannels()}; } auto validateInputFormat(const audio::AudioFormat &inputFormat) const noexcept -> bool override { return sizeof(SampleType) * utils::integer::BitsInByte == inputFormat.getBitWidth(); } auto transform(const Span &inputSpan, const Span &transformSpace) const -> Span override { auto outputSpan = Span{.data = transformSpace.data, .dataSize = transformBlockSize(inputSpan.dataSize)}; IntegerType *input = reinterpret_cast(inputSpan.data); IntegerType *output = reinterpret_cast(outputSpan.data); for (unsigned i = 0; i < inputSpan.dataSize / sizeof(IntegerType) / Ratio; i++) { output[i] = input[i * Ratio]; } return outputSpan; } }; } // namespace audio::transcode