/src/serenity/Userland/Libraries/LibAudio/MP3Loader.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021, Arne Elster <arne@elster.li> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #pragma once |
8 | | |
9 | | #include "Loader.h" |
10 | | #include "MP3Types.h" |
11 | | #include <AK/BitStream.h> |
12 | | #include <AK/MemoryStream.h> |
13 | | #include <LibDSP/MDCT.h> |
14 | | |
15 | | namespace Audio { |
16 | | |
17 | | namespace MP3::Tables { |
18 | | struct ScaleFactorBand; |
19 | | } |
20 | | |
21 | | class MP3LoaderPlugin : public LoaderPlugin { |
22 | | public: |
23 | | explicit MP3LoaderPlugin(NonnullOwnPtr<SeekableStream> stream); |
24 | 967 | virtual ~MP3LoaderPlugin() = default; |
25 | | |
26 | | static bool sniff(SeekableStream& stream); |
27 | | static ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> create(NonnullOwnPtr<SeekableStream>); |
28 | | |
29 | | virtual ErrorOr<Vector<FixedArray<Sample>>, LoaderError> load_chunks(size_t samples_to_read_from_input) override; |
30 | | |
31 | | virtual MaybeLoaderError reset() override; |
32 | | virtual MaybeLoaderError seek(int const position) override; |
33 | | |
34 | 0 | virtual int loaded_samples() override { return m_loaded_samples; } |
35 | 0 | virtual int total_samples() override { return m_total_samples; } |
36 | 0 | virtual u32 sample_rate() override { return m_sample_rate; } |
37 | 0 | virtual u16 num_channels() override { return m_num_channels; } |
38 | 0 | virtual PcmSampleFormat pcm_format() override { return m_sample_format; } |
39 | 0 | virtual ByteString format_name() override { return "MP3 (.mp3)"; } |
40 | | |
41 | | private: |
42 | | MaybeLoaderError initialize(); |
43 | | static MaybeLoaderError skip_id3(SeekableStream& stream); |
44 | | static MaybeLoaderError synchronize(SeekableStream& stream, size_t sample_index); |
45 | | static ErrorOr<MP3::Header, LoaderError> read_header(SeekableStream& stream, size_t sample_index); |
46 | | static ErrorOr<MP3::Header, LoaderError> synchronize_and_read_header(SeekableStream& stream, size_t sample_index); |
47 | | ErrorOr<MP3::Header, LoaderError> synchronize_and_read_header(); |
48 | | MaybeLoaderError build_seek_table(); |
49 | | ErrorOr<MP3::MP3Frame, LoaderError> read_next_frame(); |
50 | | ErrorOr<MP3::MP3Frame, LoaderError> read_frame_data(MP3::Header const&); |
51 | | MaybeLoaderError read_side_information(MP3::MP3Frame&); |
52 | | ErrorOr<size_t, LoaderError> read_scale_factors(MP3::MP3Frame&, BigEndianInputBitStream& reservoir, size_t granule_index, size_t channel_index); |
53 | | MaybeLoaderError read_huffman_data(MP3::MP3Frame&, BigEndianInputBitStream& reservoir, size_t granule_index, size_t channel_index, size_t granule_bits_read); |
54 | | static AK::Array<float, 576> calculate_frame_exponents(MP3::MP3Frame const&, size_t granule_index, size_t channel_index); |
55 | | static void reorder_samples(MP3::Granule&, u32 sample_rate); |
56 | | static void reduce_alias(MP3::Granule&, size_t max_subband_index = 576); |
57 | | static void process_stereo(MP3::MP3Frame&, size_t granule_index); |
58 | | static void transform_samples_to_time(Array<float, 576> const& input, size_t input_offset, Array<float, 36>& output, MP3::BlockType block_type); |
59 | | static void synthesis(Array<float, 1024>& V, Array<float, 32>& samples, Array<float, 32>& result); |
60 | | static ReadonlySpan<MP3::Tables::ScaleFactorBand> get_scalefactor_bands(MP3::Granule const&, int samplerate); |
61 | | |
62 | | SeekTable m_seek_table; |
63 | | AK::Array<AK::Array<AK::Array<float, 18>, 32>, 2> m_last_values {}; |
64 | | AK::Array<AK::Array<float, 1024>, 2> m_synthesis_buffer {}; |
65 | | static DSP::MDCT<36> s_mdct_36; |
66 | | static DSP::MDCT<12> s_mdct_12; |
67 | | |
68 | | u32 m_sample_rate { 0 }; |
69 | | u8 m_num_channels { 0 }; |
70 | | PcmSampleFormat m_sample_format { PcmSampleFormat::Int16 }; |
71 | | int m_total_samples { 0 }; |
72 | | size_t m_loaded_samples { 0 }; |
73 | | |
74 | | AllocatingMemoryStream m_bit_reservoir; |
75 | | }; |
76 | | |
77 | | } |