aboutsummaryrefslogtreecommitdiffstats
path: root/src/atrac/at3p/at3p_tables.cpp
blob: a4d6021667b71fabb579089f8d18a7e117447a98 (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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
 * 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 "at3p_tables.h"
#include "ff/atrac3plus_data.h"

#include <iostream>
#include <sstream>

namespace NAtracDEnc {
namespace NAt3p {

static struct TInvMantTab {
public:
    TInvMantTab() {
        Data[0] = 0.0; //unused (for zero lenght on the decoder)
        for (size_t i = 1; i < 8; i++) {
            Data[i] = 1.0 / atrac3p_mant_tab[i];
        }
    }
    float Data[8];
} InvMantTab_;

float InvMantTab(size_t i) { return InvMantTab_.Data[i]; }

static struct TScaleTableInitializer {
public:
    TScaleTableInitializer() {
        const std::array<float, 64> src = {
            0.027852058,  0.0350914,   0.044212341, 0.055704117,
            0.0701828,    0.088424683, 0.11140823,  0.1403656,
            0.17684937,   0.22281647,  0.2807312,   0.35369873,
            0.44563293,   0.5614624,   0.70739746,  0.89126587,
            1.1229248,    1.4147949,   1.7825317,   2.2458496,
            2.8295898,    3.5650635,   4.4916992,   5.6591797,
            7.130127,     8.9833984,   11.318359,   14.260254,
            17.966797,    22.636719,   28.520508,   35.933594,
            45.273438,    57.041016,   71.867188,   90.546875,
            114.08203,    143.73438,   181.09375,   228.16406,
            287.46875,    362.1875,    456.32812,   574.9375,
            724.375,      912.65625,   1149.875,    1448.75,
            1825.3125,    2299.75,     2897.5,      3650.625,
            4599.5,       5795.0,      7301.25,     9199.0,
            11590.0,      14602.5,     18398.0,     23180.0,
            29205.0,      36796.0,     46360.0,     58410.0
        };

        for (size_t i = 0; i < src.size(); i++) {
            TScaleTable::ScaleTable[i] = src[i] / src.back();
        }
    }
} ScaleTableInitializer_;

float TScaleTable::ScaleTable[64];
constexpr uint32_t TScaleTable::BlocksPerBand[NumQMF + 1];
constexpr uint32_t TScaleTable::SpecsPerBlock[MaxBfus];
constexpr uint32_t TScaleTable::BlockSizeTab[MaxBfus + 1];

static uint16_t __attribute__ ((noinline)) GenHuffmanEncTable(const uint8_t *cb, const uint8_t *xlat, uint16_t outLen, TVlcElement* const out)
{
    uint16_t index = 0;
    uint16_t code = 0;
    for (int b = 1; b <= 12; b++) {
        for (int i = *cb++; i > 0; i--) {
            uint8_t val = xlat[index];
            if (val >= outLen) {
                std::stringstream ss;
                ss << "encoded value out of range, invalid haffman table, got: " << (int)val << " table len: " << (int)outLen;
                throw std::runtime_error(ss.str());
            }
            TVlcElement* cur = out + val;
            cur->Code = code;
            cur->Len = b;
            index++;
            code++;
        }
        code <<= 1;
    }
    return index;
}

template<typename T>
uint16_t GenHuffmanEncTable(const uint8_t *cb, const uint8_t *xlat, T& out)
{
    return GenHuffmanEncTable(cb, xlat, out.size(), out.data());
}

THuffTables::THuffTables()
{
    GenHuffmanEncTable(&atrac3p_tone_cbs[0][0], &atrac3p_tone_xlats[0], NumToneBands);

    for (size_t i = 0; i < VlcSpecs.size(); i++) {
        for (size_t j = 0; j < VlcSpecs[i].size(); j++) {
            VlcSpecs[i][j].Code = 0;
            VlcSpecs[i][j].Len = 0;
        }
    }

    for (int i = 0, x = 0; i < 112; i++) {
        if (atrac3p_spectra_cbs[i][0] >= 0) {
            x += GenHuffmanEncTable((uint8_t*)&atrac3p_spectra_cbs[i][0], &atrac3p_spectra_xlats[x], VlcSpecs[i]);
        } else {
            VlcSpecs[i] = VlcSpecs[-atrac3p_spectra_cbs[i][0]];
        }
    }
}

} // namespace NAt3p
} // namespace NAtracDEnc