diff --git a/Userland/Libraries/LibAudio/CMakeLists.txt b/Userland/Libraries/LibAudio/CMakeLists.txt index cf807e8ed1..4ef906945a 100644 --- a/Userland/Libraries/LibAudio/CMakeLists.txt +++ b/Userland/Libraries/LibAudio/CMakeLists.txt @@ -22,4 +22,4 @@ if (SERENITYOS) endif() serenity_lib(LibAudio audio) -target_link_libraries(LibAudio PRIVATE LibCore LibIPC LibThreading LibUnicode) +target_link_libraries(LibAudio PRIVATE LibCore LibIPC LibThreading LibUnicode LibCrypto) diff --git a/Userland/Libraries/LibAudio/FlacLoader.cpp b/Userland/Libraries/LibAudio/FlacLoader.cpp index 851fda7137..c5e20f656b 100644 --- a/Userland/Libraries/LibAudio/FlacLoader.cpp +++ b/Userland/Libraries/LibAudio/FlacLoader.cpp @@ -24,6 +24,8 @@ #include #include #include +#include +#include namespace Audio { @@ -367,9 +369,10 @@ LoaderSamples FlacLoaderPlugin::next_frame() dbgln("FLAC Warning: Inserting seek point for sample {} failed: {}", sample_index, maybe_error.release_error()); } - BigEndianInputBitStream bit_stream { MaybeOwned(*m_stream) }; + auto checksum_stream = TRY(try_make>(MaybeOwned(*m_stream))); + BigEndianInputBitStream bit_stream { MaybeOwned { *checksum_stream } }; - // TODO: Check the CRC-16 checksum (and others) by keeping track of read data + // TODO: Check the CRC-16 checksum by keeping track of read data. // 11.22. FRAME_HEADER u16 sync_code = LOADER_TRY(bit_stream.read_bits(14)); @@ -393,7 +396,6 @@ LoaderSamples FlacLoaderPlugin::next_frame() FLAC_VERIFY(reserved_bit == 0, LoaderError::Category::Format, "Reserved frame header end bit"); // 11.22.8. CODED NUMBER - // FIXME: sample number can be 8-56 bits, frame number can be 8-48 bits m_current_sample_or_frame = LOADER_TRY(read_utf8_char(bit_stream)); // Conditional header variables @@ -413,17 +415,22 @@ LoaderSamples FlacLoaderPlugin::next_frame() frame_sample_rate = LOADER_TRY(bit_stream.read_bits(16)) * 10; } + // It does not matter whether we extract the checksum from the digest here, or extract the digest 0x00 after processing the checksum. + auto const calculated_checksum = checksum_stream->digest(); // 11.22.11. FRAME CRC - // TODO: check header checksum, see above - [[maybe_unused]] u8 checksum = LOADER_TRY(bit_stream.read_bits(8)); + u8 specified_checksum = LOADER_TRY(bit_stream.read_bits(8)); + VERIFY(bit_stream.is_aligned_to_byte_boundary()); + if (specified_checksum != calculated_checksum) + dbgln("FLAC frame {}: Calculated header checksum {:02x} is different from specified checksum {:02x}", m_current_sample_or_frame, calculated_checksum, specified_checksum); - dbgln_if(AFLACLOADER_DEBUG, "Frame: {} samples, {}bit {}Hz, channeltype {:x}, {} number {}, header checksum {}", sample_count, bit_depth, frame_sample_rate, channel_type_num, blocking_strategy ? "sample" : "frame", m_current_sample_or_frame, checksum); + dbgln_if(AFLACLOADER_DEBUG, "Frame: {} samples, {}bit {}Hz, channeltype {:x}, {} number {}, header checksum {:02x}{}", sample_count, bit_depth, frame_sample_rate, channel_type_num, blocking_strategy ? "sample" : "frame", m_current_sample_or_frame, specified_checksum, specified_checksum != calculated_checksum ? " (checksum error)"sv : ""sv); m_current_frame = FlacFrameHeader { sample_count, frame_sample_rate, channel_type, bit_depth, + specified_checksum, }; u8 subframe_count = frame_channel_type_to_channel_count(channel_type); diff --git a/Userland/Libraries/LibAudio/FlacTypes.h b/Userland/Libraries/LibAudio/FlacTypes.h index 8eb5851e47..36f9265e2b 100644 --- a/Userland/Libraries/LibAudio/FlacTypes.h +++ b/Userland/Libraries/LibAudio/FlacTypes.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace Audio { @@ -23,6 +24,11 @@ namespace Audio { #define FLAC_SAMPLERATE_AT_END_OF_HEADER_16 0xfffffffe #define FLAC_SAMPLERATE_AT_END_OF_HEADER_16X10 0xfffffffd +// 11.22.11. FRAME CRC +// The polynomial used here is known as CRC-8-CCITT. +static constexpr u8 flac_polynomial = 0x07; +using FlacFrameHeaderCRC = Crypto::Checksum::CRC8; + // 11.8 BLOCK_TYPE (7 bits) enum class FlacMetadataBlockType : u8 { STREAMINFO = 0, // Important data about the audio format @@ -80,6 +86,7 @@ struct FlacFrameHeader { u32 sample_rate; FlacFrameChannelType channels; u8 bit_depth; + u8 checksum; }; // 11.25. SUBFRAME_HEADER