diff options
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibAudio/FlacLoader.cpp | 26 | ||||
-rw-r--r-- | Userland/Libraries/LibAudio/FlacLoader.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibAudio/FlacTypes.h | 6 |
3 files changed, 32 insertions, 2 deletions
diff --git a/Userland/Libraries/LibAudio/FlacLoader.cpp b/Userland/Libraries/LibAudio/FlacLoader.cpp index ab74865e27..baef59d7eb 100644 --- a/Userland/Libraries/LibAudio/FlacLoader.cpp +++ b/Userland/Libraries/LibAudio/FlacLoader.cpp @@ -118,13 +118,20 @@ MaybeLoaderError FlacLoaderPlugin::parse_header() md5_checksum.bytes().copy_to({ m_md5_checksum, sizeof(m_md5_checksum) }); // Parse other blocks - // TODO: For a simple first implementation, all other blocks are skipped as allowed by the FLAC specification. - // Especially the SEEKTABLE block may become useful in a more sophisticated version. [[maybe_unused]] u16 meta_blocks_parsed = 1; [[maybe_unused]] u16 total_meta_blocks = meta_blocks_parsed; FlacRawMetadataBlock block = streaminfo; while (!block.is_last_block) { block = TRY(next_meta_block(*bit_input)); + switch (block.type) { + case (FlacMetadataBlockType::SEEKTABLE): + TRY(load_seektable(block)); + break; + default: + // TODO: Parse the remaining metadata block types. + // Currently only STREAMINFO and SEEKTABLE are handled. + break; + } ++total_meta_blocks; } @@ -133,6 +140,21 @@ MaybeLoaderError FlacLoaderPlugin::parse_header() return {}; } +MaybeLoaderError FlacLoaderPlugin::load_seektable(FlacRawMetadataBlock& block) +{ + auto memory_stream = LOADER_TRY(Core::Stream::MemoryStream::construct(block.data.bytes())); + auto seektable_bytes = LOADER_TRY(BigEndianInputBitStream::construct(*memory_stream)); + for (size_t i = 0; i < block.length / 18; ++i) { + FlacSeekPoint seekpoint { + .sample_index = LOADER_TRY(seektable_bytes->read_bits<u64>(64)), + .byte_offset = LOADER_TRY(seektable_bytes->read_bits<u64>(64)), + .num_samples = LOADER_TRY(seektable_bytes->read_bits<u16>(16)) + }; + m_seektable.append(seekpoint); + } + return {}; +} + ErrorOr<FlacRawMetadataBlock, LoaderError> FlacLoaderPlugin::next_meta_block(BigEndianInputBitStream& bit_input) { diff --git a/Userland/Libraries/LibAudio/FlacLoader.h b/Userland/Libraries/LibAudio/FlacLoader.h index 9082b3901f..f78c2cf093 100644 --- a/Userland/Libraries/LibAudio/FlacLoader.h +++ b/Userland/Libraries/LibAudio/FlacLoader.h @@ -83,6 +83,7 @@ private: MaybeLoaderError decode_residual(Vector<i32>& decoded, FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input); // decode a single rice partition that has its own rice parameter ALWAYS_INLINE ErrorOr<Vector<i32>, LoaderError> decode_rice_partition(u8 partition_type, u32 partitions, u32 partition_index, FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input); + MaybeLoaderError load_seektable(FlacRawMetadataBlock&); // Converters for special coding used in frame headers ALWAYS_INLINE ErrorOr<u32, LoaderError> convert_sample_count_code(u8 sample_count_code); @@ -113,6 +114,7 @@ private: // Whatever the last get_more_samples() call couldn't return gets stored here. Vector<Sample, FLAC_BUFFER_SIZE> m_unread_data; u64 m_current_sample_or_frame { 0 }; + Vector<FlacSeekPoint> m_seektable; }; } diff --git a/Userland/Libraries/LibAudio/FlacTypes.h b/Userland/Libraries/LibAudio/FlacTypes.h index c5fb663b4e..0b1f6e5431 100644 --- a/Userland/Libraries/LibAudio/FlacTypes.h +++ b/Userland/Libraries/LibAudio/FlacTypes.h @@ -87,4 +87,10 @@ struct FlacSubframeHeader { u8 bits_per_sample; }; +struct FlacSeekPoint { + u64 sample_index; + u64 byte_offset; + u16 num_samples; +}; + } |