Coverage Report

Created: 2026-11-13 08:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibAudio/MP3Loader.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2021, Arne Elster <arne@elster.li>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include "MP3Loader.h"
8
#include "MP3HuffmanTables.h"
9
#include "MP3Tables.h"
10
#include "MP3Types.h"
11
#include <AK/Endian.h>
12
#include <AK/FixedArray.h>
13
#include <LibCore/File.h>
14
15
namespace Audio {
16
17
DSP::MDCT<12> MP3LoaderPlugin::s_mdct_12;
18
DSP::MDCT<36> MP3LoaderPlugin::s_mdct_36;
19
20
MP3LoaderPlugin::MP3LoaderPlugin(NonnullOwnPtr<SeekableStream> stream)
21
967
    : LoaderPlugin(move(stream))
22
967
{
23
967
}
24
25
MaybeLoaderError MP3LoaderPlugin::skip_id3(SeekableStream& stream)
26
967
{
27
    // FIXME: This is a bit of a hack until we have a proper ID3 reader and MP3 demuxer.
28
    // Based on https://mutagen-specs.readthedocs.io/en/latest/id3/id3v2.2.html
29
967
    char identifier_buffer[3] = { 0, 0, 0 };
30
967
    auto read_identifier = StringView(TRY(stream.read_some({ &identifier_buffer[0], sizeof(identifier_buffer) })));
31
967
    if (read_identifier == "ID3"sv) {
32
0
        [[maybe_unused]] auto version = TRY(stream.read_value<u8>());
33
0
        [[maybe_unused]] auto revision = TRY(stream.read_value<u8>());
34
0
        [[maybe_unused]] auto flags = TRY(stream.read_value<u8>());
35
0
        auto size = 0;
36
0
        for (auto i = 0; i < 4; i++) {
37
            // Each byte has a zeroed most significant bit to prevent it from looking like a sync code.
38
0
            auto byte = TRY(stream.read_value<u8>());
39
0
            size <<= 7;
40
0
            size |= byte & 0x7F;
41
0
        }
42
0
        TRY(stream.seek(size, SeekMode::FromCurrentPosition));
43
967
    } else if (read_identifier != "TAG"sv) {
44
927
        MUST(stream.seek(-static_cast<int>(read_identifier.length()), SeekMode::FromCurrentPosition));
45
927
    }
46
967
    return {};
47
967
}
48
49
bool MP3LoaderPlugin::sniff(SeekableStream& stream)
50
0
{
51
0
    auto skip_id3_result = skip_id3(stream);
52
0
    if (skip_id3_result.is_error())
53
0
        return false;
54
0
    return !synchronize_and_read_header(stream, 0).is_error();
55
0
}
56
57
ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> MP3LoaderPlugin::create(NonnullOwnPtr<SeekableStream> stream)
58
967
{
59
967
    auto loader = make<MP3LoaderPlugin>(move(stream));
60
967
    TRY(loader->initialize());
61
845
    return loader;
62
967
}
63
64
MaybeLoaderError MP3LoaderPlugin::initialize()
65
967
{
66
967
    TRY(build_seek_table());
67
68
872
    TRY(seek(0));
69
872
    auto header = TRY(synchronize_and_read_header());
70
71
845
    m_sample_rate = header.samplerate;
72
845
    m_num_channels = header.channel_count();
73
845
    m_loaded_samples = 0;
74
75
845
    TRY(seek(0));
76
77
845
    return {};
78
845
}
79
80
MaybeLoaderError MP3LoaderPlugin::reset()
81
0
{
82
0
    TRY(seek(0));
83
0
    m_synthesis_buffer = {};
84
0
    m_loaded_samples = 0;
85
0
    TRY(m_bit_reservoir.discard(m_bit_reservoir.used_buffer_size()));
86
0
    return {};
87
0
}
88
89
MaybeLoaderError MP3LoaderPlugin::seek(int const position)
90
1.71k
{
91
1.71k
    auto seek_entry = m_seek_table.seek_point_before(position);
92
1.71k
    if (seek_entry.has_value()) {
93
1.69k
        TRY(m_stream->seek(seek_entry->byte_offset, SeekMode::SetPosition));
94
1.69k
        m_loaded_samples = seek_entry->sample_index;
95
1.69k
    }
96
1.71k
    m_synthesis_buffer = {};
97
1.71k
    TRY(m_bit_reservoir.discard(m_bit_reservoir.used_buffer_size()));
98
1.71k
    return {};
99
1.71k
}
100
101
ErrorOr<Vector<FixedArray<Sample>>, LoaderError> MP3LoaderPlugin::load_chunks(size_t samples_to_read_from_input)
102
7.96k
{
103
7.96k
    int samples_to_read = samples_to_read_from_input;
104
7.96k
    Vector<FixedArray<Sample>> frames;
105
37.2k
    while (samples_to_read > 0) {
106
30.1k
        FixedArray<Sample> samples = TRY(FixedArray<Sample>::create(MP3::frame_size));
107
108
30.1k
        auto maybe_frame = read_next_frame();
109
30.1k
        if (maybe_frame.is_error()) {
110
845
            if (m_stream->is_eof())
111
712
                return Vector<FixedArray<Sample>> {};
112
133
            return maybe_frame.release_error();
113
845
        }
114
29.2k
        auto frame = maybe_frame.release_value();
115
116
29.2k
        bool const is_stereo = frame.header.channel_count() == 2;
117
29.2k
        size_t current_frame_read = 0;
118
16.8M
        for (; current_frame_read < MP3::granule_size; current_frame_read++) {
119
16.8M
            auto const left_sample = frame.channels[0].granules[0].pcm[current_frame_read / 32][current_frame_read % 32];
120
16.8M
            auto const right_sample = is_stereo ? frame.channels[1].granules[0].pcm[current_frame_read / 32][current_frame_read % 32] : left_sample;
121
16.8M
            samples[current_frame_read] = Sample { left_sample, right_sample };
122
16.8M
            samples_to_read--;
123
16.8M
        }
124
16.8M
        for (; current_frame_read < MP3::frame_size; current_frame_read++) {
125
16.8M
            auto const left_sample = frame.channels[0].granules[1].pcm[(current_frame_read - MP3::granule_size) / 32][(current_frame_read - MP3::granule_size) % 32];
126
16.8M
            auto const right_sample = is_stereo ? frame.channels[1].granules[1].pcm[(current_frame_read - MP3::granule_size) / 32][(current_frame_read - MP3::granule_size) % 32] : left_sample;
127
16.8M
            samples[current_frame_read] = Sample { left_sample, right_sample };
128
16.8M
            samples_to_read--;
129
16.8M
        }
130
29.2k
        m_loaded_samples += samples.size();
131
29.2k
        TRY(frames.try_append(move(samples)));
132
29.2k
    }
133
134
7.11k
    return frames;
135
7.96k
}
136
137
MaybeLoaderError MP3LoaderPlugin::build_seek_table()
138
967
{
139
967
    VERIFY(MUST(m_stream->tell()) == 0);
140
1.93k
    TRY(skip_id3(*m_stream));
141
142
1.93k
    int sample_count = 0;
143
1.93k
    size_t frame_count = 0;
144
1.93k
    m_seek_table = {};
145
146
280k
    while (true) {
147
280k
        auto error_or_header = synchronize_and_read_header();
148
280k
        if (error_or_header.is_error())
149
872
            break;
150
151
279k
        if (frame_count % 10 == 0) {
152
28.6k
            auto frame_pos = TRY(m_stream->tell()) - error_or_header.value().header_size;
153
28.6k
            TRY(m_seek_table.insert_seek_point({ static_cast<u64>(sample_count), frame_pos }));
154
28.6k
        }
155
156
279k
        frame_count++;
157
279k
        sample_count += MP3::frame_size;
158
159
279k
        TRY(m_stream->seek(error_or_header.value().frame_size - error_or_header.value().header_size, SeekMode::FromCurrentPosition));
160
279k
    }
161
872
    m_total_samples = sample_count;
162
872
    return {};
163
1.93k
}
164
165
ErrorOr<MP3::Header, LoaderError> MP3LoaderPlugin::read_header(SeekableStream& stream, size_t sample_index)
166
1.14M
{
167
1.14M
    auto bitstream = BigEndianInputBitStream(MaybeOwned<Stream>(stream));
168
2.29M
    if (TRY(bitstream.read_bits(4)) != 0xF)
169
0
        return LoaderError { LoaderError::Category::Format, sample_index, "Frame header did not start with sync code."_fly_string };
170
1.14M
    MP3::Header header;
171
1.14M
    header.id = TRY(bitstream.read_bit());
172
1.14M
    header.layer = MP3::Tables::LayerNumberLookup[TRY(bitstream.read_bits(2))];
173
1.14M
    if (header.layer <= 0)
174
505
        return LoaderError { LoaderError::Category::Format, sample_index, "Frame header contains invalid layer number."_fly_string };
175
1.14M
    header.protection_bit = TRY(bitstream.read_bit());
176
1.14M
    header.bitrate = MP3::Tables::BitratesPerLayerLookup[header.layer - 1][TRY(bitstream.read_bits(4))];
177
1.14M
    if (header.bitrate <= 0)
178
274k
        return LoaderError { LoaderError::Category::Format, sample_index, "Frame header contains invalid bitrate."_fly_string };
179
871k
    header.samplerate = MP3::Tables::SampleratesLookup[TRY(bitstream.read_bits(2))];
180
871k
    if (header.samplerate <= 0)
181
530k
        return LoaderError { LoaderError::Category::Format, sample_index, "Frame header contains invalid samplerate."_fly_string };
182
340k
    header.padding_bit = TRY(bitstream.read_bit());
183
340k
    header.private_bit = TRY(bitstream.read_bit());
184
340k
    header.mode = static_cast<MP3::Mode>(TRY(bitstream.read_bits(2)));
185
340k
    header.mode_extension = static_cast<MP3::ModeExtension>(TRY(bitstream.read_bits(2)));
186
340k
    header.copyright_bit = TRY(bitstream.read_bit());
187
340k
    header.original_bit = TRY(bitstream.read_bit());
188
340k
    header.emphasis = static_cast<MP3::Emphasis>(TRY(bitstream.read_bits(2)));
189
340k
    header.header_size = 4;
190
340k
    if (!header.protection_bit) {
191
99.2k
        header.crc16 = TRY(bitstream.read_bits<u16>(16));
192
99.2k
        header.header_size += 2;
193
99.2k
    }
194
340k
    header.frame_size = 144 * header.bitrate * 1000 / header.samplerate + header.padding_bit;
195
340k
    header.slot_count = header.frame_size - ((header.channel_count() == 2 ? 32 : 17) + header.header_size);
196
340k
    return header;
197
340k
}
198
199
ErrorOr<MP3::Header, LoaderError> MP3LoaderPlugin::synchronize_and_read_header(SeekableStream& stream, size_t sample_index)
200
311k
{
201
1.14M
    while (!stream.is_eof()) {
202
1.14M
        bool last_was_all_set = false;
203
204
17.9M
        while (!stream.is_eof()) {
205
17.9M
            u8 byte = TRY(stream.read_value<u8>());
206
17.9M
            if (last_was_all_set && (byte & 0xF0) == 0xF0) {
207
                // Seek back, since there is still data we have not consumed within the current byte.
208
                // read_header() will consume and check these 4 bits itself and then continue reading
209
                // the rest of the data from there.
210
1.14M
                TRY(stream.seek(-1, SeekMode::FromCurrentPosition));
211
1.14M
                break;
212
1.14M
            }
213
16.7M
            last_was_all_set = byte == 0xFF;
214
16.7M
        }
215
216
1.14M
        auto header_start = TRY(stream.tell());
217
1.14M
        auto header_result = read_header(stream, sample_index);
218
1.14M
        if (header_result.is_error() || header_result.value().id != 1 || header_result.value().layer != 3) {
219
835k
            TRY(stream.seek(header_start, SeekMode::SetPosition));
220
835k
            continue;
221
835k
        }
222
310k
        return header_result.value();
223
1.14M
    }
224
1.32k
    return LoaderError { LoaderError::Category::Format, sample_index, "Failed to synchronize."_fly_string };
225
311k
}
226
227
ErrorOr<MP3::Header, LoaderError> MP3LoaderPlugin::synchronize_and_read_header()
228
311k
{
229
311k
    return MP3LoaderPlugin::synchronize_and_read_header(*m_stream, m_loaded_samples);
230
311k
}
231
232
ErrorOr<MP3::MP3Frame, LoaderError> MP3LoaderPlugin::read_next_frame()
233
30.1k
{
234
30.1k
    return read_frame_data(TRY(synchronize_and_read_header()));
235
30.1k
}
236
237
ErrorOr<MP3::MP3Frame, LoaderError> MP3LoaderPlugin::read_frame_data(MP3::Header const& header)
238
29.7k
{
239
29.7k
    MP3::MP3Frame frame { header };
240
241
29.7k
    TRY(read_side_information(frame));
242
243
29.7k
    auto maybe_buffer = ByteBuffer::create_uninitialized(header.slot_count);
244
29.7k
    if (maybe_buffer.is_error())
245
0
        return LoaderError { LoaderError::Category::IO, m_loaded_samples, "Out of memory"_fly_string };
246
29.7k
    auto& buffer = maybe_buffer.value();
247
248
29.7k
    size_t old_reservoir_size = m_bit_reservoir.used_buffer_size();
249
29.7k
    TRY(m_stream->read_until_filled(buffer));
250
29.7k
    TRY(m_bit_reservoir.write_until_depleted(buffer));
251
252
    // If we don't have enough data in the reservoir to process this frame, skip it (but keep the data).
253
29.7k
    if (old_reservoir_size < static_cast<size_t>(frame.main_data_begin))
254
1.44k
        return frame;
255
256
56.5k
    TRY(m_bit_reservoir.discard(old_reservoir_size - frame.main_data_begin));
257
258
56.5k
    BigEndianInputBitStream reservoir_stream { MaybeOwned<Stream>(m_bit_reservoir) };
259
260
84.2k
    for (size_t granule_index = 0; granule_index < 2; granule_index++) {
261
166k
        for (size_t channel_index = 0; channel_index < header.channel_count(); channel_index++) {
262
110k
            size_t scale_factor_size = TRY(read_scale_factors(frame, reservoir_stream, granule_index, channel_index));
263
110k
            TRY(read_huffman_data(frame, reservoir_stream, granule_index, channel_index, scale_factor_size));
264
110k
            if (frame.channels[channel_index].granules[granule_index].block_type == MP3::BlockType::Short) {
265
11.4k
                reorder_samples(frame.channels[channel_index].granules[granule_index], frame.header.samplerate);
266
267
                // Only reduce alias for lowest 2 bands as they're long.
268
                // Afaik this is not mentioned in the ISO spec, but it is addressed in the
269
                // changelog for the ISO compliance tests.
270
11.4k
                if (frame.channels[channel_index].granules[granule_index].mixed_block_flag)
271
6.34k
                    reduce_alias(frame.channels[channel_index].granules[granule_index], 36);
272
98.8k
            } else {
273
98.8k
                reduce_alias(frame.channels[channel_index].granules[granule_index]);
274
98.8k
            }
275
110k
        }
276
277
56.3k
        if (header.mode == MP3::Mode::JointStereo) {
278
32.1k
            process_stereo(frame, granule_index);
279
32.1k
        }
280
55.9k
    }
281
282
83.5k
    for (size_t granule_index = 0; granule_index < 2; granule_index++) {
283
165k
        for (size_t channel_index = 0; channel_index < header.channel_count(); channel_index++) {
284
109k
            auto& granule = frame.channels[channel_index].granules[granule_index];
285
286
3.61M
            for (size_t i = 0; i < MP3::granule_size; i += 18) {
287
3.50M
                MP3::BlockType block_type = granule.block_type;
288
3.50M
                if (i < 36 && granule.mixed_block_flag) {
289
                    // ISO/IEC 11172-3: if mixed_block_flag is set, the lowest two subbands are transformed with normal window.
290
18.7k
                    block_type = MP3::BlockType::Normal;
291
18.7k
                }
292
293
3.50M
                Array<float, 36> output;
294
3.50M
                transform_samples_to_time(granule.samples, i, output, block_type);
295
296
3.50M
                int const subband_index = i / 18;
297
66.6M
                for (size_t sample_index = 0; sample_index < 18; sample_index++) {
298
                    // overlap add
299
63.1M
                    granule.filter_bank_input[subband_index][sample_index] = output[sample_index] + m_last_values[channel_index][subband_index][sample_index];
300
63.1M
                    m_last_values[channel_index][subband_index][sample_index] = output[sample_index + 18];
301
302
                    // frequency inversion
303
63.1M
                    if (subband_index % 2 == 1 && sample_index % 2 == 1)
304
15.7M
                        granule.filter_bank_input[subband_index][sample_index] *= -1;
305
63.1M
                }
306
3.50M
            }
307
109k
        }
308
55.6k
    }
309
310
27.8k
    Array<float, 32> in_samples;
311
82.6k
    for (size_t channel_index = 0; channel_index < frame.header.channel_count(); channel_index++) {
312
164k
        for (size_t granule_index = 0; granule_index < 2; granule_index++) {
313
109k
            auto& granule = frame.channels[channel_index].granules[granule_index];
314
2.08M
            for (size_t sample_index = 0; sample_index < 18; sample_index++) {
315
65.1M
                for (size_t band_index = 0; band_index < 32; band_index++) {
316
63.1M
                    in_samples[band_index] = granule.filter_bank_input[band_index][sample_index];
317
63.1M
                }
318
1.97M
                synthesis(m_synthesis_buffer[channel_index], in_samples, granule.pcm[sample_index]);
319
1.97M
            }
320
109k
        }
321
54.8k
    }
322
323
27.8k
    return frame;
324
56.5k
}
325
326
MaybeLoaderError MP3LoaderPlugin::read_side_information(MP3::MP3Frame& frame)
327
29.7k
{
328
29.7k
    auto bitstream = BigEndianInputBitStream(MaybeOwned<Stream>(*m_stream));
329
330
29.7k
    frame.main_data_begin = TRY(bitstream.read_bits(9));
331
332
29.7k
    if (frame.header.channel_count() == 1) {
333
1.45k
        frame.private_bits = TRY(bitstream.read_bits(5));
334
28.2k
    } else {
335
28.2k
        frame.private_bits = TRY(bitstream.read_bits(3));
336
28.2k
    }
337
338
87.6k
    for (size_t channel_index = 0; channel_index < frame.header.channel_count(); channel_index++) {
339
289k
        for (size_t scale_factor_selection_info_band = 0; scale_factor_selection_info_band < 4; scale_factor_selection_info_band++) {
340
231k
            frame.channels[channel_index].scale_factor_selection_info[scale_factor_selection_info_band] = TRY(bitstream.read_bit());
341
231k
        }
342
57.9k
    }
343
344
89.1k
    for (size_t granule_index = 0; granule_index < 2; granule_index++) {
345
175k
        for (size_t channel_index = 0; channel_index < frame.header.channel_count(); channel_index++) {
346
115k
            auto& granule = frame.channels[channel_index].granules[granule_index];
347
115k
            granule.part_2_3_length = TRY(bitstream.read_bits(12));
348
115k
            granule.big_values = TRY(bitstream.read_bits(9));
349
115k
            granule.global_gain = TRY(bitstream.read_bits(8));
350
115k
            granule.scalefac_compress = TRY(bitstream.read_bits(4));
351
115k
            granule.window_switching_flag = TRY(bitstream.read_bit());
352
115k
            if (granule.window_switching_flag) {
353
22.3k
                granule.block_type = static_cast<MP3::BlockType>(TRY(bitstream.read_bits(2)));
354
22.3k
                granule.mixed_block_flag = TRY(bitstream.read_bit());
355
67.1k
                for (size_t region = 0; region < 2; region++)
356
44.7k
                    granule.table_select[region] = TRY(bitstream.read_bits(5));
357
89.5k
                for (size_t window = 0; window < 3; window++)
358
67.1k
                    granule.sub_block_gain[window] = TRY(bitstream.read_bits(3));
359
22.3k
                granule.region0_count = (granule.block_type == MP3::BlockType::Short && !granule.mixed_block_flag) ? 8 : 7;
360
22.3k
                granule.region1_count = 36;
361
93.5k
            } else {
362
374k
                for (size_t region = 0; region < 3; region++)
363
280k
                    granule.table_select[region] = TRY(bitstream.read_bits(5));
364
93.5k
                granule.region0_count = TRY(bitstream.read_bits(4));
365
93.5k
                granule.region1_count = TRY(bitstream.read_bits(3));
366
93.5k
            }
367
115k
            granule.preflag = TRY(bitstream.read_bit());
368
115k
            granule.scalefac_scale = TRY(bitstream.read_bit());
369
115k
            granule.count1table_select = TRY(bitstream.read_bit());
370
115k
        }
371
59.4k
    }
372
29.7k
    return {};
373
29.7k
}
374
375
// From ISO/IEC 11172-3 (2.4.3.4.7.1)
376
Array<float, MP3::granule_size> MP3LoaderPlugin::calculate_frame_exponents(MP3::MP3Frame const& frame, size_t granule_index, size_t channel_index)
377
110k
{
378
110k
    Array<float, MP3::granule_size> exponents;
379
380
2.62M
    auto fill_band = [&exponents](float exponent, size_t start, size_t end) {
381
66.3M
        for (size_t j = start; j <= end; j++) {
382
63.7M
            exponents[j] = exponent;
383
63.7M
        }
384
2.62M
    };
385
386
110k
    auto const& channel = frame.channels[channel_index];
387
110k
    auto const& granule = frame.channels[channel_index].granules[granule_index];
388
389
110k
    auto const scale_factor_bands = get_scalefactor_bands(granule, frame.header.samplerate);
390
110k
    float const scale_factor_multiplier = granule.scalefac_scale ? 1 : 0.5;
391
110k
    int const gain = granule.global_gain - 210;
392
393
110k
    if (granule.block_type != MP3::BlockType::Short) {
394
2.28M
        for (size_t band_index = 0; band_index < 22; band_index++) {
395
2.18M
            float const exponent = gain / 4.0f - (scale_factor_multiplier * (channel.scale_factors[band_index] + granule.preflag * MP3::Tables::Pretab[band_index]));
396
2.18M
            fill_band(AK::pow<float>(2.0, exponent), scale_factor_bands[band_index].start, scale_factor_bands[band_index].end);
397
2.18M
        }
398
99.1k
    } else {
399
11.4k
        size_t band_index = 0;
400
11.4k
        size_t sample_count = 0;
401
402
11.4k
        if (granule.mixed_block_flag) {
403
57.4k
            while (sample_count < 36) {
404
51.0k
                float const exponent = gain / 4.0f - (scale_factor_multiplier * (channel.scale_factors[band_index] + granule.preflag * MP3::Tables::Pretab[band_index]));
405
51.0k
                fill_band(AK::pow<float>(2.0, exponent), scale_factor_bands[band_index].start, scale_factor_bands[band_index].end);
406
51.0k
                sample_count += scale_factor_bands[band_index].width;
407
51.0k
                band_index++;
408
51.0k
            }
409
6.38k
        }
410
411
11.4k
        float const gain0 = (gain - 8 * granule.sub_block_gain[0]) / 4.0;
412
11.4k
        float const gain1 = (gain - 8 * granule.sub_block_gain[1]) / 4.0;
413
11.4k
        float const gain2 = (gain - 8 * granule.sub_block_gain[2]) / 4.0;
414
415
141k
        while (sample_count < MP3::granule_size && band_index < scale_factor_bands.size()) {
416
130k
            float const exponent0 = gain0 - (scale_factor_multiplier * channel.scale_factors[band_index + 0]);
417
130k
            float const exponent1 = gain1 - (scale_factor_multiplier * channel.scale_factors[band_index + 1]);
418
130k
            float const exponent2 = gain2 - (scale_factor_multiplier * channel.scale_factors[band_index + 2]);
419
420
130k
            fill_band(AK::pow<float>(2.0, exponent0), scale_factor_bands[band_index + 0].start, scale_factor_bands[band_index + 0].end);
421
130k
            sample_count += scale_factor_bands[band_index + 0].width;
422
130k
            fill_band(AK::pow<float>(2.0, exponent1), scale_factor_bands[band_index + 1].start, scale_factor_bands[band_index + 1].end);
423
130k
            sample_count += scale_factor_bands[band_index + 1].width;
424
130k
            fill_band(AK::pow<float>(2.0, exponent2), scale_factor_bands[band_index + 2].start, scale_factor_bands[band_index + 2].end);
425
130k
            sample_count += scale_factor_bands[band_index + 2].width;
426
427
130k
            band_index += 3;
428
130k
        }
429
430
11.4k
        while (sample_count < MP3::granule_size)
431
0
            exponents[sample_count++] = 0;
432
11.4k
    }
433
110k
    return exponents;
434
110k
}
435
436
ErrorOr<size_t, LoaderError> MP3LoaderPlugin::read_scale_factors(MP3::MP3Frame& frame, BigEndianInputBitStream& reservoir, size_t granule_index, size_t channel_index)
437
110k
{
438
110k
    auto& channel = frame.channels[channel_index];
439
110k
    auto const& granule = channel.granules[granule_index];
440
110k
    size_t band_index = 0;
441
110k
    size_t bits_read = 0;
442
443
110k
    if (granule.window_switching_flag && granule.block_type == MP3::BlockType::Short) {
444
11.5k
        if (granule.mixed_block_flag) {
445
57.5k
            for (size_t i = 0; i < 8; i++) {
446
51.1k
                auto const bits = MP3::Tables::ScalefacCompressSlen1[granule.scalefac_compress];
447
51.1k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
448
51.1k
                bits_read += bits;
449
51.1k
            }
450
63.8k
            for (size_t i = 3; i < 12; i++) {
451
57.4k
                auto const bits = i <= 5 ? MP3::Tables::ScalefacCompressSlen1[granule.scalefac_compress] : MP3::Tables::ScalefacCompressSlen2[granule.scalefac_compress];
452
57.4k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
453
57.4k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
454
57.4k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
455
57.4k
                bits_read += 3 * bits;
456
57.4k
            }
457
6.39k
        } else {
458
66.4k
            for (size_t i = 0; i < 12; i++) {
459
61.3k
                auto const bits = i <= 5 ? MP3::Tables::ScalefacCompressSlen1[granule.scalefac_compress] : MP3::Tables::ScalefacCompressSlen2[granule.scalefac_compress];
460
61.3k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
461
61.3k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
462
61.3k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
463
61.3k
                bits_read += 3 * bits;
464
61.3k
            }
465
5.11k
        }
466
11.5k
        channel.scale_factors[band_index++] = 0;
467
11.4k
        channel.scale_factors[band_index++] = 0;
468
11.4k
        channel.scale_factors[band_index++] = 0;
469
99.2k
    } else {
470
99.2k
        if ((channel.scale_factor_selection_info[0] == 0) || (granule_index == 0)) {
471
660k
            for (band_index = 0; band_index < 6; band_index++) {
472
566k
                auto const bits = MP3::Tables::ScalefacCompressSlen1[granule.scalefac_compress];
473
566k
                channel.scale_factors[band_index] = TRY(reservoir.read_bits(bits));
474
566k
                bits_read += bits;
475
566k
            }
476
94.3k
        }
477
99.2k
        if ((channel.scale_factor_selection_info[1] == 0) || (granule_index == 0)) {
478
564k
            for (band_index = 6; band_index < 11; band_index++) {
479
470k
                auto const bits = MP3::Tables::ScalefacCompressSlen1[granule.scalefac_compress];
480
470k
                channel.scale_factors[band_index] = TRY(reservoir.read_bits(bits));
481
470k
                bits_read += bits;
482
470k
            }
483
94.1k
        }
484
99.1k
        if ((channel.scale_factor_selection_info[2] == 0) || (granule_index == 0)) {
485
553k
            for (band_index = 11; band_index < 16; band_index++) {
486
461k
                auto const bits = MP3::Tables::ScalefacCompressSlen2[granule.scalefac_compress];
487
461k
                channel.scale_factors[band_index] = TRY(reservoir.read_bits(bits));
488
461k
                bits_read += bits;
489
461k
            }
490
92.2k
        }
491
99.1k
        if ((channel.scale_factor_selection_info[3] == 0) || (granule_index == 0)) {
492
534k
            for (band_index = 16; band_index < 21; band_index++) {
493
445k
                auto const bits = MP3::Tables::ScalefacCompressSlen2[granule.scalefac_compress];
494
445k
                channel.scale_factors[band_index] = TRY(reservoir.read_bits(bits));
495
445k
                bits_read += bits;
496
445k
            }
497
89.0k
        }
498
99.1k
        channel.scale_factors[21] = 0;
499
99.1k
    }
500
501
110k
    return bits_read;
502
110k
}
503
504
MaybeLoaderError MP3LoaderPlugin::read_huffman_data(MP3::MP3Frame& frame, BigEndianInputBitStream& reservoir, size_t granule_index, size_t channel_index, size_t granule_bits_read)
505
110k
{
506
110k
    auto const exponents = calculate_frame_exponents(frame, granule_index, channel_index);
507
110k
    auto& granule = frame.channels[channel_index].granules[granule_index];
508
509
110k
    auto const scale_factor_bands = get_scalefactor_bands(granule, frame.header.samplerate);
510
110k
    size_t const scale_factor_band_index1 = granule.region0_count + 1;
511
110k
    size_t const scale_factor_band_index2 = min(scale_factor_bands.size() - 1, scale_factor_band_index1 + granule.region1_count + 1);
512
513
110k
    bool const is_short_granule = granule.window_switching_flag && granule.block_type == MP3::BlockType::Short;
514
110k
    size_t const region1_start = is_short_granule ? 36 : scale_factor_bands[scale_factor_band_index1].start;
515
110k
    size_t const region2_start = is_short_granule ? MP3::granule_size : scale_factor_bands[scale_factor_band_index2].start;
516
517
13.5M
    auto requantize = [](int const sample, float const exponent) -> float {
518
13.5M
        int const sign = sample < 0 ? -1 : 1;
519
13.5M
        int const magnitude = AK::abs(sample);
520
13.5M
        return sign * AK::pow<float>(static_cast<float>(magnitude), 4 / 3.0) * exponent;
521
13.5M
    };
522
523
110k
    size_t count = 0;
524
525
    // 2.4.3.4.6: "Decoding is done until all Huffman code bits have been decoded
526
    //             or until quantized values representing 576 frequency lines have been decoded,
527
    //             whichever comes first."
528
110k
    auto max_count = min(granule.big_values * 2, MP3::granule_size);
529
530
5.54M
    for (; count < max_count; count += 2) {
531
5.43M
        MP3::Tables::Huffman::HuffmanTreeXY const* tree = nullptr;
532
533
5.43M
        if (count < region1_start) {
534
366k
            tree = &MP3::Tables::Huffman::HuffmanTreesXY[granule.table_select[0]];
535
5.06M
        } else if (count < region2_start) {
536
1.85M
            tree = &MP3::Tables::Huffman::HuffmanTreesXY[granule.table_select[1]];
537
3.21M
        } else {
538
3.21M
            tree = &MP3::Tables::Huffman::HuffmanTreesXY[granule.table_select[2]];
539
3.21M
        }
540
541
5.43M
        if (!tree || tree->nodes.is_empty()) {
542
21
            return LoaderError { LoaderError::Category::Format, m_loaded_samples, "Frame references invalid huffman table."_fly_string };
543
21
        }
544
545
        // Assumption: There's enough bits to read. 32 is just a placeholder for "unlimited".
546
        // There are no 32 bit long huffman codes in the tables.
547
5.43M
        auto const entry = MP3::Tables::Huffman::huffman_decode(reservoir, tree->nodes, 32);
548
5.43M
        granule_bits_read += entry.bits_read;
549
5.43M
        if (!entry.code.has_value())
550
93
            return LoaderError { LoaderError::Category::Format, m_loaded_samples, "Frame contains invalid huffman data."_fly_string };
551
5.43M
        int x = entry.code->symbol.x;
552
5.43M
        int y = entry.code->symbol.y;
553
554
5.43M
        if (x == 15 && tree->linbits > 0) {
555
28.5k
            x += TRY(reservoir.read_bits(tree->linbits));
556
28.5k
            granule_bits_read += tree->linbits;
557
28.5k
        }
558
5.43M
        if (x != 0) {
559
367k
            if (TRY(reservoir.read_bit()))
560
78.1k
                x = -x;
561
367k
            granule_bits_read++;
562
367k
        }
563
564
5.43M
        if (y == 15 && tree->linbits > 0) {
565
61.1k
            y += TRY(reservoir.read_bits(tree->linbits));
566
61.1k
            granule_bits_read += tree->linbits;
567
61.1k
        }
568
5.43M
        if (y != 0) {
569
365k
            if (TRY(reservoir.read_bit()))
570
93.4k
                y = -y;
571
365k
            granule_bits_read++;
572
365k
        }
573
574
5.43M
        granule.samples[count + 0] = requantize(x, exponents[count + 0]);
575
5.43M
        granule.samples[count + 1] = requantize(y, exponents[count + 1]);
576
5.43M
    }
577
578
110k
    ReadonlySpan<MP3::Tables::Huffman::HuffmanNode<MP3::Tables::Huffman::HuffmanVWXY>> count1table = granule.count1table_select ? MP3::Tables::Huffman::TreeB : MP3::Tables::Huffman::TreeA;
579
580
    // count1 is not known. We have to read huffman encoded values
581
    // until we've exhausted the granule's bits. We know the size of
582
    // the granule from part2_3_length, which is the number of bits
583
    // used for scalefactors and huffman data (in the granule).
584
793k
    while (granule_bits_read < granule.part_2_3_length && count <= MP3::granule_size - 4) {
585
689k
        auto const entry = MP3::Tables::Huffman::huffman_decode(reservoir, count1table, granule.part_2_3_length - granule_bits_read);
586
689k
        granule_bits_read += entry.bits_read;
587
689k
        if (!entry.code.has_value())
588
69
            return LoaderError { LoaderError::Category::Format, m_loaded_samples, "Frame contains invalid huffman data."_fly_string };
589
688k
        int v = entry.code->symbol.v;
590
688k
        if (v != 0) {
591
241k
            if (granule_bits_read >= granule.part_2_3_length)
592
834
                break;
593
240k
            if (TRY(reservoir.read_bit()))
594
39.3k
                v = -v;
595
240k
            granule_bits_read++;
596
240k
        }
597
688k
        int w = entry.code->symbol.w;
598
688k
        if (w != 0) {
599
81.6k
            if (granule_bits_read >= granule.part_2_3_length)
600
440
                break;
601
81.1k
            if (TRY(reservoir.read_bit()))
602
46.8k
                w = -w;
603
81.1k
            granule_bits_read++;
604
81.1k
        }
605
687k
        int x = entry.code->symbol.x;
606
687k
        if (x != 0) {
607
233k
            if (granule_bits_read >= granule.part_2_3_length)
608
3.26k
                break;
609
230k
            if (TRY(reservoir.read_bit()))
610
22.3k
                x = -x;
611
230k
            granule_bits_read++;
612
230k
        }
613
684k
        int y = entry.code->symbol.y;
614
684k
        if (y != 0) {
615
259k
            if (granule_bits_read >= granule.part_2_3_length)
616
1.04k
                break;
617
258k
            if (TRY(reservoir.read_bit()))
618
55.4k
                y = -y;
619
258k
            granule_bits_read++;
620
258k
        }
621
622
683k
        granule.samples[count + 0] = requantize(v, exponents[count + 0]);
623
683k
        granule.samples[count + 1] = requantize(w, exponents[count + 1]);
624
683k
        granule.samples[count + 2] = requantize(x, exponents[count + 2]);
625
683k
        granule.samples[count + 3] = requantize(y, exponents[count + 3]);
626
627
683k
        count += 4;
628
683k
    }
629
630
110k
    if (granule_bits_read > granule.part_2_3_length) {
631
81
        return LoaderError { LoaderError::Category::Format, m_loaded_samples, "Read too many bits from bit reservoir."_fly_string };
632
81
    }
633
634
    // 2.4.3.4.6: "If there are more Huffman code bits than necessary to decode 576 values
635
    //             they are regarded as stuffing bits and discarded."
636
7.88M
    for (size_t i = granule_bits_read; i < granule.part_2_3_length; i++) {
637
7.77M
        TRY(reservoir.read_bit());
638
7.77M
    }
639
640
110k
    return {};
641
110k
}
642
643
void MP3LoaderPlugin::reorder_samples(MP3::Granule& granule, u32 sample_rate)
644
11.4k
{
645
11.4k
    float tmp[MP3::granule_size] = {};
646
11.4k
    size_t band_index = 0;
647
11.4k
    size_t subband_index = 0;
648
649
11.4k
    auto scale_factor_bands = get_scalefactor_bands(granule, sample_rate);
650
651
11.4k
    if (granule.mixed_block_flag) {
652
57.1k
        while (subband_index < 36) {
653
279k
            for (size_t frequency_line_index = 0; frequency_line_index < scale_factor_bands[band_index].width; frequency_line_index++) {
654
228k
                tmp[subband_index] = granule.samples[subband_index];
655
228k
                subband_index++;
656
228k
            }
657
50.7k
            band_index++;
658
50.7k
        }
659
6.34k
    }
660
661
140k
    while (subband_index < MP3::granule_size && band_index <= 36) {
662
2.24M
        for (size_t frequency_line_index = 0; frequency_line_index < scale_factor_bands[band_index].width; frequency_line_index++) {
663
2.11M
            tmp[subband_index++] = granule.samples[scale_factor_bands[band_index + 0].start + frequency_line_index];
664
2.11M
            tmp[subband_index++] = granule.samples[scale_factor_bands[band_index + 1].start + frequency_line_index];
665
2.11M
            tmp[subband_index++] = granule.samples[scale_factor_bands[band_index + 2].start + frequency_line_index];
666
2.11M
        }
667
129k
        band_index += 3;
668
129k
    }
669
670
6.59M
    for (size_t i = 0; i < MP3::granule_size; i++)
671
6.58M
        granule.samples[i] = tmp[i];
672
11.4k
}
673
674
void MP3LoaderPlugin::reduce_alias(MP3::Granule& granule, size_t max_subband_index)
675
105k
{
676
3.17M
    for (size_t subband = 0; subband < max_subband_index - 18; subband += 18) {
677
27.6M
        for (size_t i = 0; i < 8; i++) {
678
24.5M
            size_t const idx1 = subband + 17 - i;
679
24.5M
            size_t const idx2 = subband + 18 + i;
680
24.5M
            auto const d1 = granule.samples[idx1];
681
24.5M
            auto const d2 = granule.samples[idx2];
682
24.5M
            granule.samples[idx1] = d1 * MP3::Tables::AliasReductionCs[i] - d2 * MP3::Tables::AliasReductionCa[i];
683
24.5M
            granule.samples[idx2] = d2 * MP3::Tables::AliasReductionCs[i] + d1 * MP3::Tables::AliasReductionCa[i];
684
24.5M
        }
685
3.07M
    }
686
105k
}
687
688
void MP3LoaderPlugin::process_stereo(MP3::MP3Frame& frame, size_t granule_index)
689
32.1k
{
690
32.1k
    size_t band_index_ms_start = 0;
691
32.1k
    size_t band_index_ms_end = 0;
692
32.1k
    size_t band_index_intensity_start = 0;
693
32.1k
    size_t band_index_intensity_end = 0;
694
32.1k
    auto& granule_left = frame.channels[0].granules[granule_index];
695
32.1k
    auto& granule_right = frame.channels[1].granules[granule_index];
696
697
32.1k
    auto get_last_nonempty_band = [](Span<float> samples, ReadonlySpan<MP3::Tables::ScaleFactorBand> bands) -> size_t {
698
8.81k
        size_t last_nonempty_band = 0;
699
700
235k
        for (size_t i = 0; i < bands.size(); i++) {
701
226k
            bool is_empty = true;
702
4.89M
            for (size_t l = bands[i].start; l < bands[i].end; l++) {
703
4.68M
                if (samples[l] != 0) {
704
13.5k
                    is_empty = false;
705
13.5k
                    break;
706
13.5k
                }
707
4.68M
            }
708
226k
            if (!is_empty)
709
13.5k
                last_nonempty_band = i;
710
226k
        }
711
712
8.81k
        return last_nonempty_band;
713
8.81k
    };
714
715
379k
    auto process_ms_stereo = [&](MP3::Tables::ScaleFactorBand const& band) {
716
379k
        float const SQRT_2 = AK::sqrt(2.0);
717
9.22M
        for (size_t i = band.start; i <= band.end; i++) {
718
8.84M
            float const m = granule_left.samples[i];
719
8.84M
            float const s = granule_right.samples[i];
720
8.84M
            granule_left.samples[i] = (m + s) / SQRT_2;
721
8.84M
            granule_right.samples[i] = (m - s) / SQRT_2;
722
8.84M
        }
723
379k
    };
724
725
190k
    auto process_intensity_stereo = [&](MP3::Tables::ScaleFactorBand const& band, float intensity_stereo_ratio) {
726
4.78M
        for (size_t i = band.start; i <= band.end; i++) {
727
            // Superflous empty scale factor band.
728
4.59M
            if (i >= MP3::granule_size)
729
764
                continue;
730
4.59M
            float const sample_left = granule_left.samples[i];
731
4.59M
            float const coeff_l = intensity_stereo_ratio / (1 + intensity_stereo_ratio);
732
4.59M
            float const coeff_r = 1 / (1 + intensity_stereo_ratio);
733
4.59M
            granule_left.samples[i] = sample_left * coeff_l;
734
4.59M
            granule_right.samples[i] = sample_left * coeff_r;
735
4.59M
        }
736
190k
    };
737
738
32.1k
    auto scale_factor_bands = get_scalefactor_bands(granule_right, frame.header.samplerate);
739
740
32.1k
    if (has_flag(frame.header.mode_extension, MP3::ModeExtension::MsStereo)) {
741
18.5k
        band_index_ms_start = 0;
742
18.5k
        band_index_ms_end = scale_factor_bands.size();
743
18.5k
    }
744
745
32.1k
    if (has_flag(frame.header.mode_extension, MP3::ModeExtension::IntensityStereo)) {
746
8.81k
        band_index_intensity_start = get_last_nonempty_band(granule_right.samples, scale_factor_bands);
747
8.81k
        band_index_intensity_end = scale_factor_bands.size();
748
8.81k
        band_index_ms_end = band_index_intensity_start;
749
8.81k
    }
750
751
401k
    for (size_t band_index = band_index_ms_start; band_index < band_index_ms_end; band_index++) {
752
369k
        process_ms_stereo(scale_factor_bands[band_index]);
753
369k
    }
754
755
233k
    for (size_t band_index = band_index_intensity_start; band_index < band_index_intensity_end; band_index++) {
756
200k
        auto const intensity_stereo_position = frame.channels[1].scale_factors[band_index];
757
200k
        if (intensity_stereo_position == 7) {
758
10.3k
            if (has_flag(frame.header.mode_extension, MP3::ModeExtension::MsStereo))
759
9.94k
                process_ms_stereo(scale_factor_bands[band_index]);
760
10.3k
            continue;
761
10.3k
        }
762
190k
        float const intensity_stereo_ratio = AK::tan(intensity_stereo_position * AK::Pi<float> / 12);
763
190k
        process_intensity_stereo(scale_factor_bands[band_index], intensity_stereo_ratio);
764
190k
    }
765
32.1k
}
766
767
void MP3LoaderPlugin::transform_samples_to_time(Array<float, MP3::granule_size> const& input, size_t input_offset, Array<float, 36>& output, MP3::BlockType block_type)
768
3.50M
{
769
3.50M
    if (block_type == MP3::BlockType::Short) {
770
347k
        size_t const N = 12;
771
347k
        Array<float, N * 3> temp_out;
772
347k
        Array<float, N / 2> temp_in;
773
774
2.43M
        for (size_t k = 0; k < N / 2; k++)
775
2.08M
            temp_in[k] = input[input_offset + 3 * k + 0];
776
347k
        s_mdct_12.transform(temp_in, Span<float>(temp_out).slice(0, N));
777
4.51M
        for (size_t i = 0; i < N; i++)
778
4.17M
            temp_out[i + 0] *= MP3::Tables::WindowBlockTypeShort[i];
779
780
2.43M
        for (size_t k = 0; k < N / 2; k++)
781
2.08M
            temp_in[k] = input[input_offset + 3 * k + 1];
782
347k
        s_mdct_12.transform(temp_in, Span<float>(temp_out).slice(12, N));
783
4.51M
        for (size_t i = 0; i < N; i++)
784
4.17M
            temp_out[i + 12] *= MP3::Tables::WindowBlockTypeShort[i];
785
786
2.43M
        for (size_t k = 0; k < N / 2; k++)
787
2.08M
            temp_in[k] = input[input_offset + 3 * k + 2];
788
347k
        s_mdct_12.transform(temp_in, Span<float>(temp_out).slice(24, N));
789
4.51M
        for (size_t i = 0; i < N; i++)
790
4.17M
            temp_out[i + 24] *= MP3::Tables::WindowBlockTypeShort[i];
791
792
347k
        Span<float> idmct1 = Span<float>(temp_out).slice(0, 12);
793
347k
        Span<float> idmct2 = Span<float>(temp_out).slice(12, 12);
794
347k
        Span<float> idmct3 = Span<float>(temp_out).slice(24, 12);
795
2.43M
        for (size_t i = 0; i < 6; i++)
796
2.08M
            output[i] = 0;
797
2.43M
        for (size_t i = 6; i < 12; i++)
798
2.08M
            output[i] = idmct1[i - 6];
799
2.43M
        for (size_t i = 12; i < 18; i++)
800
2.08M
            output[i] = idmct1[i - 6] + idmct2[i - 12];
801
2.43M
        for (size_t i = 18; i < 24; i++)
802
2.08M
            output[i] = idmct2[i - 12] + idmct3[i - 18];
803
2.43M
        for (size_t i = 24; i < 30; i++)
804
2.08M
            output[i] = idmct3[i - 18];
805
2.43M
        for (size_t i = 30; i < 36; i++)
806
2.08M
            output[i] = 0;
807
808
3.15M
    } else {
809
3.15M
        s_mdct_36.transform(ReadonlySpan<float>(input).slice(input_offset, 18), output);
810
116M
        for (size_t i = 0; i < 36; i++) {
811
113M
            switch (block_type) {
812
108M
            case MP3::BlockType::Normal:
813
108M
                output[i] *= MP3::Tables::WindowBlockTypeNormal[i];
814
108M
                break;
815
1.42M
            case MP3::BlockType::Start:
816
1.42M
                output[i] *= MP3::Tables::WindowBlockTypeStart[i];
817
1.42M
                break;
818
3.42M
            case MP3::BlockType::End:
819
3.42M
                output[i] *= MP3::Tables::WindowBlockTypeEnd[i];
820
3.42M
                break;
821
0
            case MP3::BlockType::Short:
822
0
                VERIFY_NOT_REACHED();
823
0
                break;
824
113M
            }
825
113M
        }
826
3.15M
    }
827
3.50M
}
828
829
// ISO/IEC 11172-3 (Figure A.2)
830
void MP3LoaderPlugin::synthesis(Array<float, 1024>& V, Array<float, 32>& samples, Array<float, 32>& result)
831
1.97M
{
832
1.89G
    for (size_t i = 1023; i >= 64; i--) {
833
1.89G
        V[i] = V[i - 64];
834
1.89G
    }
835
836
128M
    for (size_t i = 0; i < 64; i++) {
837
126M
        V[i] = 0;
838
4.16G
        for (size_t k = 0; k < 32; k++) {
839
4.04G
            float const N = MP3::Tables::SynthesisSubbandFilterCoefficients[i][k];
840
4.04G
            V[i] += N * samples[k];
841
4.04G
        }
842
126M
    }
843
844
1.97M
    Array<float, 512> U;
845
17.7M
    for (size_t i = 0; i < 8; i++) {
846
520M
        for (size_t j = 0; j < 32; j++) {
847
505M
            U[i * 64 + j] = V[i * 128 + j];
848
505M
            U[i * 64 + 32 + j] = V[i * 128 + 96 + j];
849
505M
        }
850
15.7M
    }
851
852
1.97M
    Array<float, 512> W;
853
1.01G
    for (size_t i = 0; i < 512; i++) {
854
1.01G
        W[i] = U[i] * MP3::Tables::WindowSynthesis[i];
855
1.01G
    }
856
857
65.1M
    for (size_t j = 0; j < 32; j++) {
858
63.1M
        result[j] = 0;
859
1.07G
        for (size_t k = 0; k < 16; k++) {
860
1.01G
            result[j] += W[j + 32 * k];
861
1.01G
        }
862
63.1M
    }
863
1.97M
}
864
865
ReadonlySpan<MP3::Tables::ScaleFactorBand> MP3LoaderPlugin::get_scalefactor_bands(MP3::Granule const& granule, int samplerate)
866
264k
{
867
264k
    switch (granule.block_type) {
868
38.9k
    case MP3::BlockType::Short:
869
38.9k
        switch (samplerate) {
870
8.89k
        case 32000:
871
8.89k
            return granule.mixed_block_flag ? MP3::Tables::ScaleFactorBandMixed32000 : MP3::Tables::ScaleFactorBandShort32000;
872
16.8k
        case 44100:
873
16.8k
            return granule.mixed_block_flag ? MP3::Tables::ScaleFactorBandMixed44100 : MP3::Tables::ScaleFactorBandShort44100;
874
13.1k
        case 48000:
875
13.1k
            return granule.mixed_block_flag ? MP3::Tables::ScaleFactorBandMixed48000 : MP3::Tables::ScaleFactorBandShort48000;
876
38.9k
        }
877
0
        break;
878
215k
    case MP3::BlockType::Normal:
879
215k
        [[fallthrough]];
880
218k
    case MP3::BlockType::Start:
881
218k
        [[fallthrough]];
882
226k
    case MP3::BlockType::End:
883
226k
        switch (samplerate) {
884
31.5k
        case 32000:
885
31.5k
            return MP3::Tables::ScaleFactorBandLong32000;
886
27.8k
        case 44100:
887
27.8k
            return MP3::Tables::ScaleFactorBandLong44100;
888
166k
        case 48000:
889
166k
            return MP3::Tables::ScaleFactorBandLong48000;
890
226k
        }
891
264k
    }
892
0
    VERIFY_NOT_REACHED();
893
0
}
894
895
}