Coverage Report

Created: 2025-12-18 07:52

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
956
    : LoaderPlugin(move(stream))
22
956
{
23
956
}
24
25
MaybeLoaderError MP3LoaderPlugin::skip_id3(SeekableStream& stream)
26
956
{
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
956
    char identifier_buffer[3] = { 0, 0, 0 };
30
956
    auto read_identifier = StringView(TRY(stream.read_some({ &identifier_buffer[0], sizeof(identifier_buffer) })));
31
956
    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
956
    } else if (read_identifier != "TAG"sv) {
44
917
        MUST(stream.seek(-static_cast<int>(read_identifier.length()), SeekMode::FromCurrentPosition));
45
917
    }
46
956
    return {};
47
956
}
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
956
{
59
956
    auto loader = make<MP3LoaderPlugin>(move(stream));
60
956
    TRY(loader->initialize());
61
842
    return loader;
62
956
}
63
64
MaybeLoaderError MP3LoaderPlugin::initialize()
65
956
{
66
956
    TRY(build_seek_table());
67
68
867
    TRY(seek(0));
69
867
    auto header = TRY(synchronize_and_read_header());
70
71
842
    m_sample_rate = header.samplerate;
72
842
    m_num_channels = header.channel_count();
73
842
    m_loaded_samples = 0;
74
75
842
    TRY(seek(0));
76
77
842
    return {};
78
842
}
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.70k
{
91
1.70k
    auto seek_entry = m_seek_table.seek_point_before(position);
92
1.70k
    if (seek_entry.has_value()) {
93
1.68k
        TRY(m_stream->seek(seek_entry->byte_offset, SeekMode::SetPosition));
94
1.68k
        m_loaded_samples = seek_entry->sample_index;
95
1.68k
    }
96
1.70k
    m_synthesis_buffer = {};
97
1.70k
    TRY(m_bit_reservoir.discard(m_bit_reservoir.used_buffer_size()));
98
1.70k
    return {};
99
1.70k
}
100
101
ErrorOr<Vector<FixedArray<Sample>>, LoaderError> MP3LoaderPlugin::load_chunks(size_t samples_to_read_from_input)
102
8.09k
{
103
8.09k
    int samples_to_read = samples_to_read_from_input;
104
8.09k
    Vector<FixedArray<Sample>> frames;
105
37.9k
    while (samples_to_read > 0) {
106
30.6k
        FixedArray<Sample> samples = TRY(FixedArray<Sample>::create(MP3::frame_size));
107
108
30.6k
        auto maybe_frame = read_next_frame();
109
30.6k
        if (maybe_frame.is_error()) {
110
842
            if (m_stream->is_eof())
111
674
                return Vector<FixedArray<Sample>> {};
112
168
            return maybe_frame.release_error();
113
842
        }
114
29.8k
        auto frame = maybe_frame.release_value();
115
116
29.8k
        bool const is_stereo = frame.header.channel_count() == 2;
117
29.8k
        size_t current_frame_read = 0;
118
17.2M
        for (; current_frame_read < MP3::granule_size; current_frame_read++) {
119
17.1M
            auto const left_sample = frame.channels[0].granules[0].pcm[current_frame_read / 32][current_frame_read % 32];
120
17.1M
            auto const right_sample = is_stereo ? frame.channels[1].granules[0].pcm[current_frame_read / 32][current_frame_read % 32] : left_sample;
121
17.1M
            samples[current_frame_read] = Sample { left_sample, right_sample };
122
17.1M
            samples_to_read--;
123
17.1M
        }
124
17.2M
        for (; current_frame_read < MP3::frame_size; current_frame_read++) {
125
17.1M
            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
17.1M
            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
17.1M
            samples[current_frame_read] = Sample { left_sample, right_sample };
128
17.1M
            samples_to_read--;
129
17.1M
        }
130
29.8k
        m_loaded_samples += samples.size();
131
29.8k
        TRY(frames.try_append(move(samples)));
132
29.8k
    }
133
134
7.24k
    return frames;
135
8.09k
}
136
137
MaybeLoaderError MP3LoaderPlugin::build_seek_table()
138
956
{
139
956
    VERIFY(MUST(m_stream->tell()) == 0);
140
1.91k
    TRY(skip_id3(*m_stream));
141
142
1.91k
    int sample_count = 0;
143
1.91k
    size_t frame_count = 0;
144
1.91k
    m_seek_table = {};
145
146
257k
    while (true) {
147
257k
        auto error_or_header = synchronize_and_read_header();
148
257k
        if (error_or_header.is_error())
149
867
            break;
150
151
256k
        if (frame_count % 10 == 0) {
152
26.3k
            auto frame_pos = TRY(m_stream->tell()) - error_or_header.value().header_size;
153
26.3k
            TRY(m_seek_table.insert_seek_point({ static_cast<u64>(sample_count), frame_pos }));
154
26.3k
        }
155
156
256k
        frame_count++;
157
256k
        sample_count += MP3::frame_size;
158
159
256k
        TRY(m_stream->seek(error_or_header.value().frame_size - error_or_header.value().header_size, SeekMode::FromCurrentPosition));
160
256k
    }
161
867
    m_total_samples = sample_count;
162
867
    return {};
163
1.91k
}
164
165
ErrorOr<MP3::Header, LoaderError> MP3LoaderPlugin::read_header(SeekableStream& stream, size_t sample_index)
166
1.40M
{
167
1.40M
    auto bitstream = BigEndianInputBitStream(MaybeOwned<Stream>(stream));
168
2.80M
    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.40M
    MP3::Header header;
171
1.40M
    header.id = TRY(bitstream.read_bit());
172
1.40M
    header.layer = MP3::Tables::LayerNumberLookup[TRY(bitstream.read_bits(2))];
173
1.40M
    if (header.layer <= 0)
174
461
        return LoaderError { LoaderError::Category::Format, sample_index, "Frame header contains invalid layer number."_fly_string };
175
1.40M
    header.protection_bit = TRY(bitstream.read_bit());
176
1.40M
    header.bitrate = MP3::Tables::BitratesPerLayerLookup[header.layer - 1][TRY(bitstream.read_bits(4))];
177
1.40M
    if (header.bitrate <= 0)
178
295k
        return LoaderError { LoaderError::Category::Format, sample_index, "Frame header contains invalid bitrate."_fly_string };
179
1.10M
    header.samplerate = MP3::Tables::SampleratesLookup[TRY(bitstream.read_bits(2))];
180
1.10M
    if (header.samplerate <= 0)
181
792k
        return LoaderError { LoaderError::Category::Format, sample_index, "Frame header contains invalid samplerate."_fly_string };
182
313k
    header.padding_bit = TRY(bitstream.read_bit());
183
313k
    header.private_bit = TRY(bitstream.read_bit());
184
313k
    header.mode = static_cast<MP3::Mode>(TRY(bitstream.read_bits(2)));
185
313k
    header.mode_extension = static_cast<MP3::ModeExtension>(TRY(bitstream.read_bits(2)));
186
313k
    header.copyright_bit = TRY(bitstream.read_bit());
187
313k
    header.original_bit = TRY(bitstream.read_bit());
188
313k
    header.emphasis = static_cast<MP3::Emphasis>(TRY(bitstream.read_bits(2)));
189
313k
    header.header_size = 4;
190
313k
    if (!header.protection_bit) {
191
86.2k
        header.crc16 = TRY(bitstream.read_bits<u16>(16));
192
86.2k
        header.header_size += 2;
193
86.2k
    }
194
313k
    header.frame_size = 144 * header.bitrate * 1000 / header.samplerate + header.padding_bit;
195
313k
    header.slot_count = header.frame_size - ((header.channel_count() == 2 ? 32 : 17) + header.header_size);
196
313k
    return header;
197
313k
}
198
199
ErrorOr<MP3::Header, LoaderError> MP3LoaderPlugin::synchronize_and_read_header(SeekableStream& stream, size_t sample_index)
200
289k
{
201
1.40M
    while (!stream.is_eof()) {
202
1.40M
        bool last_was_all_set = false;
203
204
18.1M
        while (!stream.is_eof()) {
205
18.1M
            u8 byte = TRY(stream.read_value<u8>());
206
18.1M
            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.40M
                TRY(stream.seek(-1, SeekMode::FromCurrentPosition));
211
1.40M
                break;
212
1.40M
            }
213
16.7M
            last_was_all_set = byte == 0xFF;
214
16.7M
        }
215
216
1.40M
        auto header_start = TRY(stream.tell());
217
1.40M
        auto header_result = read_header(stream, sample_index);
218
1.40M
        if (header_result.is_error() || header_result.value().id != 1 || header_result.value().layer != 3) {
219
1.11M
            TRY(stream.seek(header_start, SeekMode::SetPosition));
220
1.11M
            continue;
221
1.11M
        }
222
287k
        return header_result.value();
223
1.40M
    }
224
1.30k
    return LoaderError { LoaderError::Category::Format, sample_index, "Failed to synchronize."_fly_string };
225
289k
}
226
227
ErrorOr<MP3::Header, LoaderError> MP3LoaderPlugin::synchronize_and_read_header()
228
289k
{
229
289k
    return MP3LoaderPlugin::synchronize_and_read_header(*m_stream, m_loaded_samples);
230
289k
}
231
232
ErrorOr<MP3::MP3Frame, LoaderError> MP3LoaderPlugin::read_next_frame()
233
30.6k
{
234
30.6k
    return read_frame_data(TRY(synchronize_and_read_header()));
235
30.6k
}
236
237
ErrorOr<MP3::MP3Frame, LoaderError> MP3LoaderPlugin::read_frame_data(MP3::Header const& header)
238
30.2k
{
239
30.2k
    MP3::MP3Frame frame { header };
240
241
30.2k
    TRY(read_side_information(frame));
242
243
30.2k
    auto maybe_buffer = ByteBuffer::create_uninitialized(header.slot_count);
244
30.2k
    if (maybe_buffer.is_error())
245
0
        return LoaderError { LoaderError::Category::IO, m_loaded_samples, "Out of memory"_fly_string };
246
30.2k
    auto& buffer = maybe_buffer.value();
247
248
30.2k
    size_t old_reservoir_size = m_bit_reservoir.used_buffer_size();
249
30.2k
    TRY(m_stream->read_until_filled(buffer));
250
30.2k
    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
30.2k
    if (old_reservoir_size < static_cast<size_t>(frame.main_data_begin))
254
1.63k
        return frame;
255
256
57.2k
    TRY(m_bit_reservoir.discard(old_reservoir_size - frame.main_data_begin));
257
258
57.2k
    BigEndianInputBitStream reservoir_stream { MaybeOwned<Stream>(m_bit_reservoir) };
259
260
85.3k
    for (size_t granule_index = 0; granule_index < 2; granule_index++) {
261
169k
        for (size_t channel_index = 0; channel_index < header.channel_count(); channel_index++) {
262
112k
            size_t scale_factor_size = TRY(read_scale_factors(frame, reservoir_stream, granule_index, channel_index));
263
112k
            TRY(read_huffman_data(frame, reservoir_stream, granule_index, channel_index, scale_factor_size));
264
112k
            if (frame.channels[channel_index].granules[granule_index].block_type == MP3::BlockType::Short) {
265
11.2k
                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.2k
                if (frame.channels[channel_index].granules[granule_index].mixed_block_flag)
271
6.42k
                    reduce_alias(frame.channels[channel_index].granules[granule_index], 36);
272
100k
            } else {
273
100k
                reduce_alias(frame.channels[channel_index].granules[granule_index]);
274
100k
            }
275
112k
        }
276
277
57.1k
        if (header.mode == MP3::Mode::JointStereo) {
278
31.9k
            process_stereo(frame, granule_index);
279
31.9k
        }
280
56.6k
    }
281
282
84.6k
    for (size_t granule_index = 0; granule_index < 2; granule_index++) {
283
167k
        for (size_t channel_index = 0; channel_index < header.channel_count(); channel_index++) {
284
111k
            auto& granule = frame.channels[channel_index].granules[granule_index];
285
286
3.67M
            for (size_t i = 0; i < MP3::granule_size; i += 18) {
287
3.56M
                MP3::BlockType block_type = granule.block_type;
288
3.56M
                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
19.6k
                    block_type = MP3::BlockType::Normal;
291
19.6k
                }
292
293
3.56M
                Array<float, 36> output;
294
3.56M
                transform_samples_to_time(granule.samples, i, output, block_type);
295
296
3.56M
                int const subband_index = i / 18;
297
67.7M
                for (size_t sample_index = 0; sample_index < 18; sample_index++) {
298
                    // overlap add
299
64.1M
                    granule.filter_bank_input[subband_index][sample_index] = output[sample_index] + m_last_values[channel_index][subband_index][sample_index];
300
64.1M
                    m_last_values[channel_index][subband_index][sample_index] = output[sample_index + 18];
301
302
                    // frequency inversion
303
64.1M
                    if (subband_index % 2 == 1 && sample_index % 2 == 1)
304
16.0M
                        granule.filter_bank_input[subband_index][sample_index] *= -1;
305
64.1M
                }
306
3.56M
            }
307
111k
        }
308
56.4k
    }
309
310
28.2k
    Array<float, 32> in_samples;
311
83.9k
    for (size_t channel_index = 0; channel_index < frame.header.channel_count(); channel_index++) {
312
167k
        for (size_t granule_index = 0; granule_index < 2; granule_index++) {
313
111k
            auto& granule = frame.channels[channel_index].granules[granule_index];
314
2.11M
            for (size_t sample_index = 0; sample_index < 18; sample_index++) {
315
66.1M
                for (size_t band_index = 0; band_index < 32; band_index++) {
316
64.1M
                    in_samples[band_index] = granule.filter_bank_input[band_index][sample_index];
317
64.1M
                }
318
2.00M
                synthesis(m_synthesis_buffer[channel_index], in_samples, granule.pcm[sample_index]);
319
2.00M
            }
320
111k
        }
321
55.7k
    }
322
323
28.2k
    return frame;
324
57.2k
}
325
326
MaybeLoaderError MP3LoaderPlugin::read_side_information(MP3::MP3Frame& frame)
327
30.2k
{
328
30.2k
    auto bitstream = BigEndianInputBitStream(MaybeOwned<Stream>(*m_stream));
329
330
30.2k
    frame.main_data_begin = TRY(bitstream.read_bits(9));
331
332
30.2k
    if (frame.header.channel_count() == 1) {
333
1.32k
        frame.private_bits = TRY(bitstream.read_bits(5));
334
28.9k
    } else {
335
28.9k
        frame.private_bits = TRY(bitstream.read_bits(3));
336
28.9k
    }
337
338
89.5k
    for (size_t channel_index = 0; channel_index < frame.header.channel_count(); channel_index++) {
339
296k
        for (size_t scale_factor_selection_info_band = 0; scale_factor_selection_info_band < 4; scale_factor_selection_info_band++) {
340
236k
            frame.channels[channel_index].scale_factor_selection_info[scale_factor_selection_info_band] = TRY(bitstream.read_bit());
341
236k
        }
342
59.2k
    }
343
344
90.8k
    for (size_t granule_index = 0; granule_index < 2; granule_index++) {
345
179k
        for (size_t channel_index = 0; channel_index < frame.header.channel_count(); channel_index++) {
346
118k
            auto& granule = frame.channels[channel_index].granules[granule_index];
347
118k
            granule.part_2_3_length = TRY(bitstream.read_bits(12));
348
118k
            granule.big_values = TRY(bitstream.read_bits(9));
349
118k
            granule.global_gain = TRY(bitstream.read_bits(8));
350
118k
            granule.scalefac_compress = TRY(bitstream.read_bits(4));
351
118k
            granule.window_switching_flag = TRY(bitstream.read_bit());
352
118k
            if (granule.window_switching_flag) {
353
22.1k
                granule.block_type = static_cast<MP3::BlockType>(TRY(bitstream.read_bits(2)));
354
22.1k
                granule.mixed_block_flag = TRY(bitstream.read_bit());
355
66.3k
                for (size_t region = 0; region < 2; region++)
356
44.2k
                    granule.table_select[region] = TRY(bitstream.read_bits(5));
357
88.5k
                for (size_t window = 0; window < 3; window++)
358
66.3k
                    granule.sub_block_gain[window] = TRY(bitstream.read_bits(3));
359
22.1k
                granule.region0_count = (granule.block_type == MP3::BlockType::Short && !granule.mixed_block_flag) ? 8 : 7;
360
22.1k
                granule.region1_count = 36;
361
96.3k
            } else {
362
385k
                for (size_t region = 0; region < 3; region++)
363
289k
                    granule.table_select[region] = TRY(bitstream.read_bits(5));
364
96.3k
                granule.region0_count = TRY(bitstream.read_bits(4));
365
96.3k
                granule.region1_count = TRY(bitstream.read_bits(3));
366
96.3k
            }
367
118k
            granule.preflag = TRY(bitstream.read_bit());
368
118k
            granule.scalefac_scale = TRY(bitstream.read_bit());
369
118k
            granule.count1table_select = TRY(bitstream.read_bit());
370
118k
        }
371
60.5k
    }
372
30.2k
    return {};
373
30.2k
}
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
112k
{
378
112k
    Array<float, MP3::granule_size> exponents;
379
380
2.65M
    auto fill_band = [&exponents](float exponent, size_t start, size_t end) {
381
67.4M
        for (size_t j = start; j <= end; j++) {
382
64.7M
            exponents[j] = exponent;
383
64.7M
        }
384
2.65M
    };
385
386
112k
    auto const& channel = frame.channels[channel_index];
387
112k
    auto const& granule = frame.channels[channel_index].granules[granule_index];
388
389
112k
    auto const scale_factor_bands = get_scalefactor_bands(granule, frame.header.samplerate);
390
112k
    float const scale_factor_multiplier = granule.scalefac_scale ? 1 : 0.5;
391
112k
    int const gain = granule.global_gain - 210;
392
393
112k
    if (granule.block_type != MP3::BlockType::Short) {
394
2.32M
        for (size_t band_index = 0; band_index < 22; band_index++) {
395
2.22M
            float const exponent = gain / 4.0f - (scale_factor_multiplier * (channel.scale_factors[band_index] + granule.preflag * MP3::Tables::Pretab[band_index]));
396
2.22M
            fill_band(AK::pow<float>(2.0, exponent), scale_factor_bands[band_index].start, scale_factor_bands[band_index].end);
397
2.22M
        }
398
101k
    } else {
399
11.2k
        size_t band_index = 0;
400
11.2k
        size_t sample_count = 0;
401
402
11.2k
        if (granule.mixed_block_flag) {
403
58.2k
            while (sample_count < 36) {
404
51.7k
                float const exponent = gain / 4.0f - (scale_factor_multiplier * (channel.scale_factors[band_index] + granule.preflag * MP3::Tables::Pretab[band_index]));
405
51.7k
                fill_band(AK::pow<float>(2.0, exponent), scale_factor_bands[band_index].start, scale_factor_bands[band_index].end);
406
51.7k
                sample_count += scale_factor_bands[band_index].width;
407
51.7k
                band_index++;
408
51.7k
            }
409
6.47k
        }
410
411
11.2k
        float const gain0 = (gain - 8 * granule.sub_block_gain[0]) / 4.0;
412
11.2k
        float const gain1 = (gain - 8 * granule.sub_block_gain[1]) / 4.0;
413
11.2k
        float const gain2 = (gain - 8 * granule.sub_block_gain[2]) / 4.0;
414
415
138k
        while (sample_count < MP3::granule_size && band_index < scale_factor_bands.size()) {
416
127k
            float const exponent0 = gain0 - (scale_factor_multiplier * channel.scale_factors[band_index + 0]);
417
127k
            float const exponent1 = gain1 - (scale_factor_multiplier * channel.scale_factors[band_index + 1]);
418
127k
            float const exponent2 = gain2 - (scale_factor_multiplier * channel.scale_factors[band_index + 2]);
419
420
127k
            fill_band(AK::pow<float>(2.0, exponent0), scale_factor_bands[band_index + 0].start, scale_factor_bands[band_index + 0].end);
421
127k
            sample_count += scale_factor_bands[band_index + 0].width;
422
127k
            fill_band(AK::pow<float>(2.0, exponent1), scale_factor_bands[band_index + 1].start, scale_factor_bands[band_index + 1].end);
423
127k
            sample_count += scale_factor_bands[band_index + 1].width;
424
127k
            fill_band(AK::pow<float>(2.0, exponent2), scale_factor_bands[band_index + 2].start, scale_factor_bands[band_index + 2].end);
425
127k
            sample_count += scale_factor_bands[band_index + 2].width;
426
427
127k
            band_index += 3;
428
127k
        }
429
430
11.2k
        while (sample_count < MP3::granule_size)
431
0
            exponents[sample_count++] = 0;
432
11.2k
    }
433
112k
    return exponents;
434
112k
}
435
436
ErrorOr<size_t, LoaderError> MP3LoaderPlugin::read_scale_factors(MP3::MP3Frame& frame, BigEndianInputBitStream& reservoir, size_t granule_index, size_t channel_index)
437
112k
{
438
112k
    auto& channel = frame.channels[channel_index];
439
112k
    auto const& granule = channel.granules[granule_index];
440
112k
    size_t band_index = 0;
441
112k
    size_t bits_read = 0;
442
443
112k
    if (granule.window_switching_flag && granule.block_type == MP3::BlockType::Short) {
444
11.2k
        if (granule.mixed_block_flag) {
445
58.3k
            for (size_t i = 0; i < 8; i++) {
446
51.8k
                auto const bits = MP3::Tables::ScalefacCompressSlen1[granule.scalefac_compress];
447
51.8k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
448
51.8k
                bits_read += bits;
449
51.8k
            }
450
64.7k
            for (size_t i = 3; i < 12; i++) {
451
58.2k
                auto const bits = i <= 5 ? MP3::Tables::ScalefacCompressSlen1[granule.scalefac_compress] : MP3::Tables::ScalefacCompressSlen2[granule.scalefac_compress];
452
58.2k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
453
58.2k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
454
58.2k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
455
58.2k
                bits_read += 3 * bits;
456
58.2k
            }
457
6.47k
        } else {
458
62.5k
            for (size_t i = 0; i < 12; i++) {
459
57.7k
                auto const bits = i <= 5 ? MP3::Tables::ScalefacCompressSlen1[granule.scalefac_compress] : MP3::Tables::ScalefacCompressSlen2[granule.scalefac_compress];
460
57.7k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
461
57.7k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
462
57.7k
                channel.scale_factors[band_index++] = TRY(reservoir.read_bits(bits));
463
57.7k
                bits_read += 3 * bits;
464
57.7k
            }
465
4.81k
        }
466
11.2k
        channel.scale_factors[band_index++] = 0;
467
11.2k
        channel.scale_factors[band_index++] = 0;
468
11.2k
        channel.scale_factors[band_index++] = 0;
469
101k
    } else {
470
101k
        if ((channel.scale_factor_selection_info[0] == 0) || (granule_index == 0)) {
471
679k
            for (band_index = 0; band_index < 6; band_index++) {
472
582k
                auto const bits = MP3::Tables::ScalefacCompressSlen1[granule.scalefac_compress];
473
582k
                channel.scale_factors[band_index] = TRY(reservoir.read_bits(bits));
474
582k
                bits_read += bits;
475
582k
            }
476
97.0k
        }
477
101k
        if ((channel.scale_factor_selection_info[1] == 0) || (granule_index == 0)) {
478
581k
            for (band_index = 6; band_index < 11; band_index++) {
479
484k
                auto const bits = MP3::Tables::ScalefacCompressSlen1[granule.scalefac_compress];
480
484k
                channel.scale_factors[band_index] = TRY(reservoir.read_bits(bits));
481
484k
                bits_read += bits;
482
484k
            }
483
96.8k
        }
484
101k
        if ((channel.scale_factor_selection_info[2] == 0) || (granule_index == 0)) {
485
569k
            for (band_index = 11; band_index < 16; band_index++) {
486
474k
                auto const bits = MP3::Tables::ScalefacCompressSlen2[granule.scalefac_compress];
487
474k
                channel.scale_factors[band_index] = TRY(reservoir.read_bits(bits));
488
474k
                bits_read += bits;
489
474k
            }
490
94.9k
        }
491
101k
        if ((channel.scale_factor_selection_info[3] == 0) || (granule_index == 0)) {
492
549k
            for (band_index = 16; band_index < 21; band_index++) {
493
457k
                auto const bits = MP3::Tables::ScalefacCompressSlen2[granule.scalefac_compress];
494
457k
                channel.scale_factors[band_index] = TRY(reservoir.read_bits(bits));
495
457k
                bits_read += bits;
496
457k
            }
497
91.5k
        }
498
101k
        channel.scale_factors[21] = 0;
499
101k
    }
500
501
112k
    return bits_read;
502
112k
}
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
112k
{
506
112k
    auto const exponents = calculate_frame_exponents(frame, granule_index, channel_index);
507
112k
    auto& granule = frame.channels[channel_index].granules[granule_index];
508
509
112k
    auto const scale_factor_bands = get_scalefactor_bands(granule, frame.header.samplerate);
510
112k
    size_t const scale_factor_band_index1 = granule.region0_count + 1;
511
112k
    size_t const scale_factor_band_index2 = min(scale_factor_bands.size() - 1, scale_factor_band_index1 + granule.region1_count + 1);
512
513
112k
    bool const is_short_granule = granule.window_switching_flag && granule.block_type == MP3::BlockType::Short;
514
112k
    size_t const region1_start = is_short_granule ? 36 : scale_factor_bands[scale_factor_band_index1].start;
515
112k
    size_t const region2_start = is_short_granule ? MP3::granule_size : scale_factor_bands[scale_factor_band_index2].start;
516
517
14.4M
    auto requantize = [](int const sample, float const exponent) -> float {
518
14.4M
        int const sign = sample < 0 ? -1 : 1;
519
14.4M
        int const magnitude = AK::abs(sample);
520
14.4M
        return sign * AK::pow<float>(static_cast<float>(magnitude), 4 / 3.0) * exponent;
521
14.4M
    };
522
523
112k
    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
112k
    auto max_count = min(granule.big_values * 2, MP3::granule_size);
529
530
5.96M
    for (; count < max_count; count += 2) {
531
5.84M
        MP3::Tables::Huffman::HuffmanTreeXY const* tree = nullptr;
532
533
5.84M
        if (count < region1_start) {
534
416k
            tree = &MP3::Tables::Huffman::HuffmanTreesXY[granule.table_select[0]];
535
5.43M
        } else if (count < region2_start) {
536
1.97M
            tree = &MP3::Tables::Huffman::HuffmanTreesXY[granule.table_select[1]];
537
3.45M
        } else {
538
3.45M
            tree = &MP3::Tables::Huffman::HuffmanTreesXY[granule.table_select[2]];
539
3.45M
        }
540
541
5.84M
        if (!tree || tree->nodes.is_empty()) {
542
11
            return LoaderError { LoaderError::Category::Format, m_loaded_samples, "Frame references invalid huffman table."_fly_string };
543
11
        }
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.84M
        auto const entry = MP3::Tables::Huffman::huffman_decode(reservoir, tree->nodes, 32);
548
5.84M
        granule_bits_read += entry.bits_read;
549
5.84M
        if (!entry.code.has_value())
550
88
            return LoaderError { LoaderError::Category::Format, m_loaded_samples, "Frame contains invalid huffman data."_fly_string };
551
5.84M
        int x = entry.code->symbol.x;
552
5.84M
        int y = entry.code->symbol.y;
553
554
5.84M
        if (x == 15 && tree->linbits > 0) {
555
35.6k
            x += TRY(reservoir.read_bits(tree->linbits));
556
35.6k
            granule_bits_read += tree->linbits;
557
35.6k
        }
558
5.84M
        if (x != 0) {
559
451k
            if (TRY(reservoir.read_bit()))
560
94.8k
                x = -x;
561
451k
            granule_bits_read++;
562
451k
        }
563
564
5.84M
        if (y == 15 && tree->linbits > 0) {
565
74.2k
            y += TRY(reservoir.read_bits(tree->linbits));
566
74.1k
            granule_bits_read += tree->linbits;
567
74.1k
        }
568
5.84M
        if (y != 0) {
569
449k
            if (TRY(reservoir.read_bit()))
570
113k
                y = -y;
571
449k
            granule_bits_read++;
572
449k
        }
573
574
5.84M
        granule.samples[count + 0] = requantize(x, exponents[count + 0]);
575
5.84M
        granule.samples[count + 1] = requantize(y, exponents[count + 1]);
576
5.84M
    }
577
578
112k
    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
789k
    while (granule_bits_read < granule.part_2_3_length && count <= MP3::granule_size - 4) {
585
683k
        auto const entry = MP3::Tables::Huffman::huffman_decode(reservoir, count1table, granule.part_2_3_length - granule_bits_read);
586
683k
        granule_bits_read += entry.bits_read;
587
683k
        if (!entry.code.has_value())
588
67
            return LoaderError { LoaderError::Category::Format, m_loaded_samples, "Frame contains invalid huffman data."_fly_string };
589
683k
        int v = entry.code->symbol.v;
590
683k
        if (v != 0) {
591
254k
            if (granule_bits_read >= granule.part_2_3_length)
592
1.27k
                break;
593
253k
            if (TRY(reservoir.read_bit()))
594
37.8k
                v = -v;
595
253k
            granule_bits_read++;
596
253k
        }
597
682k
        int w = entry.code->symbol.w;
598
682k
        if (w != 0) {
599
83.0k
            if (granule_bits_read >= granule.part_2_3_length)
600
659
                break;
601
82.3k
            if (TRY(reservoir.read_bit()))
602
50.1k
                w = -w;
603
82.3k
            granule_bits_read++;
604
82.3k
        }
605
681k
        int x = entry.code->symbol.x;
606
681k
        if (x != 0) {
607
247k
            if (granule_bits_read >= granule.part_2_3_length)
608
3.90k
                break;
609
243k
            if (TRY(reservoir.read_bit()))
610
24.0k
                x = -x;
611
243k
            granule_bits_read++;
612
243k
        }
613
678k
        int y = entry.code->symbol.y;
614
678k
        if (y != 0) {
615
273k
            if (granule_bits_read >= granule.part_2_3_length)
616
1.15k
                break;
617
272k
            if (TRY(reservoir.read_bit()))
618
58.7k
                y = -y;
619
272k
            granule_bits_read++;
620
272k
        }
621
622
676k
        granule.samples[count + 0] = requantize(v, exponents[count + 0]);
623
676k
        granule.samples[count + 1] = requantize(w, exponents[count + 1]);
624
676k
        granule.samples[count + 2] = requantize(x, exponents[count + 2]);
625
676k
        granule.samples[count + 3] = requantize(y, exponents[count + 3]);
626
627
676k
        count += 4;
628
676k
    }
629
630
112k
    if (granule_bits_read > granule.part_2_3_length) {
631
90
        return LoaderError { LoaderError::Category::Format, m_loaded_samples, "Read too many bits from bit reservoir."_fly_string };
632
90
    }
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
8.92M
    for (size_t i = granule_bits_read; i < granule.part_2_3_length; i++) {
637
8.80M
        TRY(reservoir.read_bit());
638
8.80M
    }
639
640
112k
    return {};
641
112k
}
642
643
void MP3LoaderPlugin::reorder_samples(MP3::Granule& granule, u32 sample_rate)
644
11.2k
{
645
11.2k
    float tmp[MP3::granule_size] = {};
646
11.2k
    size_t band_index = 0;
647
11.2k
    size_t subband_index = 0;
648
649
11.2k
    auto scale_factor_bands = get_scalefactor_bands(granule, sample_rate);
650
651
11.2k
    if (granule.mixed_block_flag) {
652
57.8k
        while (subband_index < 36) {
653
282k
            for (size_t frequency_line_index = 0; frequency_line_index < scale_factor_bands[band_index].width; frequency_line_index++) {
654
231k
                tmp[subband_index] = granule.samples[subband_index];
655
231k
                subband_index++;
656
231k
            }
657
51.4k
            band_index++;
658
51.4k
        }
659
6.42k
    }
660
661
137k
    while (subband_index < MP3::granule_size && band_index <= 36) {
662
2.20M
        for (size_t frequency_line_index = 0; frequency_line_index < scale_factor_bands[band_index].width; frequency_line_index++) {
663
2.07M
            tmp[subband_index++] = granule.samples[scale_factor_bands[band_index + 0].start + frequency_line_index];
664
2.07M
            tmp[subband_index++] = granule.samples[scale_factor_bands[band_index + 1].start + frequency_line_index];
665
2.07M
            tmp[subband_index++] = granule.samples[scale_factor_bands[band_index + 2].start + frequency_line_index];
666
2.07M
        }
667
126k
        band_index += 3;
668
126k
    }
669
670
6.46M
    for (size_t i = 0; i < MP3::granule_size; i++)
671
6.45M
        granule.samples[i] = tmp[i];
672
11.2k
}
673
674
void MP3LoaderPlugin::reduce_alias(MP3::Granule& granule, size_t max_subband_index)
675
107k
{
676
3.24M
    for (size_t subband = 0; subband < max_subband_index - 18; subband += 18) {
677
28.2M
        for (size_t i = 0; i < 8; i++) {
678
25.0M
            size_t const idx1 = subband + 17 - i;
679
25.0M
            size_t const idx2 = subband + 18 + i;
680
25.0M
            auto const d1 = granule.samples[idx1];
681
25.0M
            auto const d2 = granule.samples[idx2];
682
25.0M
            granule.samples[idx1] = d1 * MP3::Tables::AliasReductionCs[i] - d2 * MP3::Tables::AliasReductionCa[i];
683
25.0M
            granule.samples[idx2] = d2 * MP3::Tables::AliasReductionCs[i] + d1 * MP3::Tables::AliasReductionCa[i];
684
25.0M
        }
685
3.13M
    }
686
107k
}
687
688
void MP3LoaderPlugin::process_stereo(MP3::MP3Frame& frame, size_t granule_index)
689
31.9k
{
690
31.9k
    size_t band_index_ms_start = 0;
691
31.9k
    size_t band_index_ms_end = 0;
692
31.9k
    size_t band_index_intensity_start = 0;
693
31.9k
    size_t band_index_intensity_end = 0;
694
31.9k
    auto& granule_left = frame.channels[0].granules[granule_index];
695
31.9k
    auto& granule_right = frame.channels[1].granules[granule_index];
696
697
31.9k
    auto get_last_nonempty_band = [](Span<float> samples, ReadonlySpan<MP3::Tables::ScaleFactorBand> bands) -> size_t {
698
8.59k
        size_t last_nonempty_band = 0;
699
700
233k
        for (size_t i = 0; i < bands.size(); i++) {
701
225k
            bool is_empty = true;
702
4.74M
            for (size_t l = bands[i].start; l < bands[i].end; l++) {
703
4.54M
                if (samples[l] != 0) {
704
16.3k
                    is_empty = false;
705
16.3k
                    break;
706
16.3k
                }
707
4.54M
            }
708
225k
            if (!is_empty)
709
16.3k
                last_nonempty_band = i;
710
225k
        }
711
712
8.59k
        return last_nonempty_band;
713
8.59k
    };
714
715
360k
    auto process_ms_stereo = [&](MP3::Tables::ScaleFactorBand const& band) {
716
360k
        float const SQRT_2 = AK::sqrt(2.0);
717
8.62M
        for (size_t i = band.start; i <= band.end; i++) {
718
8.26M
            float const m = granule_left.samples[i];
719
8.26M
            float const s = granule_right.samples[i];
720
8.26M
            granule_left.samples[i] = (m + s) / SQRT_2;
721
8.26M
            granule_right.samples[i] = (m - s) / SQRT_2;
722
8.26M
        }
723
360k
    };
724
725
182k
    auto process_intensity_stereo = [&](MP3::Tables::ScaleFactorBand const& band, float intensity_stereo_ratio) {
726
4.60M
        for (size_t i = band.start; i <= band.end; i++) {
727
            // Superflous empty scale factor band.
728
4.42M
            if (i >= MP3::granule_size)
729
605
                continue;
730
4.42M
            float const sample_left = granule_left.samples[i];
731
4.42M
            float const coeff_l = intensity_stereo_ratio / (1 + intensity_stereo_ratio);
732
4.42M
            float const coeff_r = 1 / (1 + intensity_stereo_ratio);
733
4.42M
            granule_left.samples[i] = sample_left * coeff_l;
734
4.42M
            granule_right.samples[i] = sample_left * coeff_r;
735
4.42M
        }
736
182k
    };
737
738
31.9k
    auto scale_factor_bands = get_scalefactor_bands(granule_right, frame.header.samplerate);
739
740
31.9k
    if (has_flag(frame.header.mode_extension, MP3::ModeExtension::MsStereo)) {
741
18.0k
        band_index_ms_start = 0;
742
18.0k
        band_index_ms_end = scale_factor_bands.size();
743
18.0k
    }
744
745
31.9k
    if (has_flag(frame.header.mode_extension, MP3::ModeExtension::IntensityStereo)) {
746
8.59k
        band_index_intensity_start = get_last_nonempty_band(granule_right.samples, scale_factor_bands);
747
8.59k
        band_index_intensity_end = scale_factor_bands.size();
748
8.59k
        band_index_ms_end = band_index_intensity_start;
749
8.59k
    }
750
751
380k
    for (size_t band_index = band_index_ms_start; band_index < band_index_ms_end; band_index++) {
752
348k
        process_ms_stereo(scale_factor_bands[band_index]);
753
348k
    }
754
755
226k
    for (size_t band_index = band_index_intensity_start; band_index < band_index_intensity_end; band_index++) {
756
194k
        auto const intensity_stereo_position = frame.channels[1].scale_factors[band_index];
757
194k
        if (intensity_stereo_position == 7) {
758
12.0k
            if (has_flag(frame.header.mode_extension, MP3::ModeExtension::MsStereo))
759
11.7k
                process_ms_stereo(scale_factor_bands[band_index]);
760
12.0k
            continue;
761
12.0k
        }
762
182k
        float const intensity_stereo_ratio = AK::tan(intensity_stereo_position * AK::Pi<float> / 12);
763
182k
        process_intensity_stereo(scale_factor_bands[band_index], intensity_stereo_ratio);
764
182k
    }
765
31.9k
}
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.56M
{
769
3.56M
    if (block_type == MP3::BlockType::Short) {
770
340k
        size_t const N = 12;
771
340k
        Array<float, N * 3> temp_out;
772
340k
        Array<float, N / 2> temp_in;
773
774
2.38M
        for (size_t k = 0; k < N / 2; k++)
775
2.04M
            temp_in[k] = input[input_offset + 3 * k + 0];
776
340k
        s_mdct_12.transform(temp_in, Span<float>(temp_out).slice(0, N));
777
4.42M
        for (size_t i = 0; i < N; i++)
778
4.08M
            temp_out[i + 0] *= MP3::Tables::WindowBlockTypeShort[i];
779
780
2.38M
        for (size_t k = 0; k < N / 2; k++)
781
2.04M
            temp_in[k] = input[input_offset + 3 * k + 1];
782
340k
        s_mdct_12.transform(temp_in, Span<float>(temp_out).slice(12, N));
783
4.42M
        for (size_t i = 0; i < N; i++)
784
4.08M
            temp_out[i + 12] *= MP3::Tables::WindowBlockTypeShort[i];
785
786
2.38M
        for (size_t k = 0; k < N / 2; k++)
787
2.04M
            temp_in[k] = input[input_offset + 3 * k + 2];
788
340k
        s_mdct_12.transform(temp_in, Span<float>(temp_out).slice(24, N));
789
4.42M
        for (size_t i = 0; i < N; i++)
790
4.08M
            temp_out[i + 24] *= MP3::Tables::WindowBlockTypeShort[i];
791
792
340k
        Span<float> idmct1 = Span<float>(temp_out).slice(0, 12);
793
340k
        Span<float> idmct2 = Span<float>(temp_out).slice(12, 12);
794
340k
        Span<float> idmct3 = Span<float>(temp_out).slice(24, 12);
795
2.38M
        for (size_t i = 0; i < 6; i++)
796
2.04M
            output[i] = 0;
797
2.38M
        for (size_t i = 6; i < 12; i++)
798
2.04M
            output[i] = idmct1[i - 6];
799
2.38M
        for (size_t i = 12; i < 18; i++)
800
2.04M
            output[i] = idmct1[i - 6] + idmct2[i - 12];
801
2.38M
        for (size_t i = 18; i < 24; i++)
802
2.04M
            output[i] = idmct2[i - 12] + idmct3[i - 18];
803
2.38M
        for (size_t i = 24; i < 30; i++)
804
2.04M
            output[i] = idmct3[i - 18];
805
2.38M
        for (size_t i = 30; i < 36; i++)
806
2.04M
            output[i] = 0;
807
808
3.22M
    } else {
809
3.22M
        s_mdct_36.transform(ReadonlySpan<float>(input).slice(input_offset, 18), output);
810
119M
        for (size_t i = 0; i < 36; i++) {
811
116M
            switch (block_type) {
812
110M
            case MP3::BlockType::Normal:
813
110M
                output[i] *= MP3::Tables::WindowBlockTypeNormal[i];
814
110M
                break;
815
1.38M
            case MP3::BlockType::Start:
816
1.38M
                output[i] *= MP3::Tables::WindowBlockTypeStart[i];
817
1.38M
                break;
818
3.77M
            case MP3::BlockType::End:
819
3.77M
                output[i] *= MP3::Tables::WindowBlockTypeEnd[i];
820
3.77M
                break;
821
0
            case MP3::BlockType::Short:
822
0
                VERIFY_NOT_REACHED();
823
0
                break;
824
116M
            }
825
116M
        }
826
3.22M
    }
827
3.56M
}
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
2.00M
{
832
1.92G
    for (size_t i = 1023; i >= 64; i--) {
833
1.92G
        V[i] = V[i - 64];
834
1.92G
    }
835
836
130M
    for (size_t i = 0; i < 64; i++) {
837
128M
        V[i] = 0;
838
4.23G
        for (size_t k = 0; k < 32; k++) {
839
4.10G
            float const N = MP3::Tables::SynthesisSubbandFilterCoefficients[i][k];
840
4.10G
            V[i] += N * samples[k];
841
4.10G
        }
842
128M
    }
843
844
2.00M
    Array<float, 512> U;
845
18.0M
    for (size_t i = 0; i < 8; i++) {
846
529M
        for (size_t j = 0; j < 32; j++) {
847
513M
            U[i * 64 + j] = V[i * 128 + j];
848
513M
            U[i * 64 + 32 + j] = V[i * 128 + 96 + j];
849
513M
        }
850
16.0M
    }
851
852
2.00M
    Array<float, 512> W;
853
1.02G
    for (size_t i = 0; i < 512; i++) {
854
1.02G
        W[i] = U[i] * MP3::Tables::WindowSynthesis[i];
855
1.02G
    }
856
857
66.1M
    for (size_t j = 0; j < 32; j++) {
858
64.1M
        result[j] = 0;
859
1.09G
        for (size_t k = 0; k < 16; k++) {
860
1.02G
            result[j] += W[j + 32 * k];
861
1.02G
        }
862
64.1M
    }
863
2.00M
}
864
865
ReadonlySpan<MP3::Tables::ScaleFactorBand> MP3LoaderPlugin::get_scalefactor_bands(MP3::Granule const& granule, int samplerate)
866
268k
{
867
268k
    switch (granule.block_type) {
868
38.5k
    case MP3::BlockType::Short:
869
38.5k
        switch (samplerate) {
870
9.10k
        case 32000:
871
9.10k
            return granule.mixed_block_flag ? MP3::Tables::ScaleFactorBandMixed32000 : MP3::Tables::ScaleFactorBandShort32000;
872
15.4k
        case 44100:
873
15.4k
            return granule.mixed_block_flag ? MP3::Tables::ScaleFactorBandMixed44100 : MP3::Tables::ScaleFactorBandShort44100;
874
14.0k
        case 48000:
875
14.0k
            return granule.mixed_block_flag ? MP3::Tables::ScaleFactorBandMixed48000 : MP3::Tables::ScaleFactorBandShort48000;
876
38.5k
        }
877
0
        break;
878
218k
    case MP3::BlockType::Normal:
879
218k
        [[fallthrough]];
880
221k
    case MP3::BlockType::Start:
881
221k
        [[fallthrough]];
882
229k
    case MP3::BlockType::End:
883
229k
        switch (samplerate) {
884
35.2k
        case 32000:
885
35.2k
            return MP3::Tables::ScaleFactorBandLong32000;
886
22.6k
        case 44100:
887
22.6k
            return MP3::Tables::ScaleFactorBandLong44100;
888
171k
        case 48000:
889
171k
            return MP3::Tables::ScaleFactorBandLong48000;
890
229k
        }
891
268k
    }
892
0
    VERIFY_NOT_REACHED();
893
0
}
894
895
}