summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibAudio/FlacLoader.cpp26
-rw-r--r--Userland/Libraries/LibAudio/FlacLoader.h2
-rw-r--r--Userland/Libraries/LibAudio/FlacTypes.h6
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;
+};
+
}