summaryrefslogtreecommitdiffstats
path: root/src/atrac/atrac_enc_cache.h
blob: 0a9cdb1ba0074d28a8ec913be8f493246ccf6f3d (plain) (blame)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
#pragma once

/*
 * This file is part of AtracDEnc.
 *
 * AtracDEnc is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * AtracDEnc is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with AtracDEnc; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <cstddef>
#include <cstdint>
#include <memory>
#include <vector>

namespace NAtracDEnc {

// Codec-agnostic base for a single cached encoding unit (BFU / quant unit).
//
// A codec subclasses TUnit and quantizes the scaled spectrum into Mantisas,
// filling the bookkeeping fields needed to later write the unit into the
// stream. The actual computation lives in the user-supplied ProvideUnit
// factory (see TEncCache) so the cached hot path carries no extra virtual
// dispatch. The result is produced once per cache lifetime for a given key
// and then reused across the bit-allocation search.
class TUnit {
public:
    virtual ~TUnit() = default;

    const std::vector<int>& GetMantisas() const { return Mantisas; }
    uint32_t GetWordlen() const { return Wordlen; }
    float GetMultiplier() const { return Multiplier; }
    uint16_t GetConsumedBits() const { return ConsumedBits; }

protected:
    // Info needed to write the unit into the stream after encoding.
    std::vector<int> Mantisas;
    uint32_t Wordlen = 0;
    float Multiplier = 1.0f;
    uint16_t ConsumedBits = 0; // Number of bits consumed by the quantized spectrum
};

// Caches per-unit encoding results during the bit-allocation search.
//
// Within a single frame the scaled spectrum of a given (ch, bfu, wordlen)
// is fixed, so its quantized mantissas and bit consumption are deterministic.
// The binary search requests the same combinations repeatedly; this cache
// computes each one once.
//
// The key space is small and dense, so units are stored in a vector that is
// directly indexed by a user-supplied key function (nullptr slot == not yet
// computed) rather than in a std::map.
class TEncCache {
public:
    // Build the right TUnit subclass for this key and quantize `values` into
    // it. Invoked only on a cache miss. `opaque` carries user context
    // (e.g. scale tables / per-frame data).
    using TProvideUnit = TUnit* (*)(size_t ch, size_t bfu, size_t wordlen,
                                    const float* values, void* opaque);

    // Pack (ch, bfu, wordlen) into a dense vector index. Codec specific.
    using TMakeKey = size_t (*)(size_t ch, size_t bfu, size_t wordlen);

    // `numKeys` is the upper bound on MakeKey() values; the backing vector is
    // sized once to it. ProvideUnit/MakeKey must agree on this bound.
    TEncCache(size_t numKeys, TProvideUnit provideUnit, TMakeKey makeKey, void* opaque = nullptr);

    TEncCache(const TEncCache&) = delete;
    TEncCache& operator=(const TEncCache&) = delete;

    // Return the cached unit for (ch, bfu, wordlen), creating and computing
    // it via ProvideUnit on the first request.
    TUnit* GetOrCompute(size_t ch, size_t bfu, size_t wordlen, const float* values);

    // Drop all cached units. Call at frame boundaries.
    void Reset();

private:
    std::vector<std::unique_ptr<TUnit>> UnitBuffers; // direct-indexed by MakeKey()
    TProvideUnit ProvideUnit;
    TMakeKey MakeKey;
    void* Opaque;
};

} // namespace NAtracDEnc