~aleteoryx/muditaos

ref: b00548440b4d37ee2806f0760a949b23b7e14aa8 muditaos/module-audio/Audio/transcode/BasicInterpolator.hpp -rw-r--r-- 3.1 KiB
b0054844 — Lefucjusz [BH-2020] Fix double-free in DecoderMP3 1 year, 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// 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 <integer.hpp>

#include <type_traits>

#include <cassert>
#include <cstdint>

namespace audio::transcode
{
    /**
     * @brief Basic interpolation transformation - for every Ratio samples it repeats
     * Ratio - 1 samples. The transformation is performed using basic integer type
     * to allow compiler to perform loop optimizations. The transformation is performed
     * in-place. The transformed signal is not filtered with a low-pass filter.
     *
     * @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 interpolator; e.g.: for Ratio = 4 repeats first sample 3
     * times for each block of 4 increasing sample rate by the factor of 4.
     */
    template <typename SampleType, unsigned int Channels, unsigned int Ratio>
    class BasicInterpolator : public Transform
    {
        static_assert(Channels == 1 || Channels == 2);
        static_assert(std::is_integral<SampleType>::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<sizeof(SampleType) * utils::integer::BitsInByte *
                                                             Channels>())::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<IntegerType *>(inputSpan.data);
            IntegerType *output = reinterpret_cast<IntegerType *>(outputSpan.data);

            assert(outputSpan.dataSize <= transformSpace.dataSize);

            for (unsigned i = inputSpan.dataSize / sizeof(IntegerType); i > 0; i--) {
                for (unsigned j = 1; j <= Ratio; j++) {
                    output[i * Ratio - j] = input[i - 1];
                }
            }

            return outputSpan;
        }
    };

} // namespace audio::transcode