mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 17:37:34 +00:00
LibAudio: Convert FlacLoader to use new Core::Stream APIs :^)
For this change to work "easily", Loader can't take const ByteBuffer's anymore, which is fine for now.
This commit is contained in:
parent
4f48a086b7
commit
8a92573732
7 changed files with 113 additions and 175 deletions
|
@ -9,63 +9,23 @@
|
|||
#include "Buffer.h"
|
||||
#include "FlacTypes.h"
|
||||
#include "Loader.h"
|
||||
#include <AK/BitStream.h>
|
||||
#include <AK/Buffered.h>
|
||||
#include <AK/Error.h>
|
||||
#include <AK/Stream.h>
|
||||
#include <AK/Span.h>
|
||||
#include <AK/Types.h>
|
||||
#include <AK/Variant.h>
|
||||
#include <LibCore/FileStream.h>
|
||||
#include <LibCore/InputBitStream.h>
|
||||
#include <LibCore/MemoryStream.h>
|
||||
#include <LibCore/Stream.h>
|
||||
|
||||
namespace Audio {
|
||||
|
||||
using Core::Stream::BigEndianInputBitStream;
|
||||
|
||||
// Experimentally determined to be a decent buffer size on i686:
|
||||
// 4K (the default) is slightly worse, and 64K is much worse.
|
||||
// At sufficiently large buffer sizes, the advantage of infrequent read() calls is outweighed by the memmove() overhead.
|
||||
// There was no intensive fine-tuning done to determine this value, so improvements may definitely be possible.
|
||||
constexpr size_t FLAC_BUFFER_SIZE = 8 * KiB;
|
||||
|
||||
template<size_t Size = FLAC_BUFFER_SIZE>
|
||||
class FlacInputStream : public Variant<Buffered<Core::InputFileStream, Size>, InputMemoryStream> {
|
||||
|
||||
public:
|
||||
using Variant<Buffered<Core::InputFileStream, Size>, InputMemoryStream>::Variant;
|
||||
|
||||
bool seek(size_t pos)
|
||||
{
|
||||
return this->visit(
|
||||
[&](Buffered<Core::InputFileStream, Size>& buffered) {
|
||||
// Discard the buffer, then seek normally.
|
||||
if (!buffered.discard_or_error(buffered.buffered()))
|
||||
return false;
|
||||
return buffered.underlying_stream().seek(pos);
|
||||
},
|
||||
[&](InputMemoryStream& stream) {
|
||||
if (pos >= stream.bytes().size()) {
|
||||
return false;
|
||||
}
|
||||
stream.seek(pos);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
bool handle_any_error()
|
||||
{
|
||||
return this->visit(
|
||||
[&](auto& stream) {
|
||||
return stream.handle_any_error();
|
||||
});
|
||||
}
|
||||
|
||||
InputBitStream bit_stream()
|
||||
{
|
||||
return this->visit(
|
||||
[&](auto& stream) {
|
||||
return InputBitStream(stream);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
ALWAYS_INLINE u8 frame_channel_type_to_channel_count(FlacFrameChannelType channel_type);
|
||||
// Sign-extend an arbitrary-size signed number to 64 bit signed
|
||||
ALWAYS_INLINE i64 sign_extend(u32 n, u8 size);
|
||||
|
@ -75,18 +35,16 @@ ALWAYS_INLINE i32 rice_to_signed(u32 x);
|
|||
|
||||
// decoders
|
||||
// read a UTF-8 encoded number, even if it is not a valid codepoint
|
||||
ALWAYS_INLINE u64 read_utf8_char(InputStream& input);
|
||||
ALWAYS_INLINE ErrorOr<u64> read_utf8_char(BigEndianInputBitStream& input);
|
||||
// decode a single number encoded with exponential golomb encoding of the specified order
|
||||
ALWAYS_INLINE i32 decode_unsigned_exp_golomb(u8 order, InputBitStream& bit_input);
|
||||
ALWAYS_INLINE ErrorOr<i32> decode_unsigned_exp_golomb(u8 order, BigEndianInputBitStream& bit_input);
|
||||
|
||||
class FlacLoaderPlugin : public LoaderPlugin {
|
||||
public:
|
||||
explicit FlacLoaderPlugin(StringView path);
|
||||
explicit FlacLoaderPlugin(const ByteBuffer& buffer);
|
||||
explicit FlacLoaderPlugin(Bytes& buffer);
|
||||
~FlacLoaderPlugin()
|
||||
{
|
||||
if (m_stream)
|
||||
m_stream->handle_any_error();
|
||||
}
|
||||
|
||||
virtual MaybeLoaderError initialize() override;
|
||||
|
@ -111,20 +69,20 @@ private:
|
|||
MaybeLoaderError parse_header();
|
||||
// Either returns the metadata block or sets error message.
|
||||
// Additionally, increments m_data_start_location past the read meta block.
|
||||
ErrorOr<FlacRawMetadataBlock, LoaderError> next_meta_block(InputBitStream& bit_input);
|
||||
ErrorOr<FlacRawMetadataBlock, LoaderError> next_meta_block(BigEndianInputBitStream& bit_input);
|
||||
// Fetches and writes the next FLAC frame
|
||||
MaybeLoaderError next_frame(Span<Sample>);
|
||||
// Helper of next_frame that fetches a sub frame's header
|
||||
ErrorOr<FlacSubframeHeader, LoaderError> next_subframe_header(InputBitStream& bit_input, u8 channel_index);
|
||||
ErrorOr<FlacSubframeHeader, LoaderError> next_subframe_header(BigEndianInputBitStream& bit_input, u8 channel_index);
|
||||
// Helper of next_frame that decompresses a subframe
|
||||
ErrorOr<Vector<i32>, LoaderError> parse_subframe(FlacSubframeHeader& subframe_header, InputBitStream& bit_input);
|
||||
ErrorOr<Vector<i32>, LoaderError> parse_subframe(FlacSubframeHeader& subframe_header, BigEndianInputBitStream& bit_input);
|
||||
// Subframe-internal data decoders (heavy lifting)
|
||||
ErrorOr<Vector<i32>, LoaderError> decode_fixed_lpc(FlacSubframeHeader& subframe, InputBitStream& bit_input);
|
||||
ErrorOr<Vector<i32>, LoaderError> decode_verbatim(FlacSubframeHeader& subframe, InputBitStream& bit_input);
|
||||
ErrorOr<Vector<i32>, LoaderError> decode_custom_lpc(FlacSubframeHeader& subframe, InputBitStream& bit_input);
|
||||
MaybeLoaderError decode_residual(Vector<i32>& decoded, FlacSubframeHeader& subframe, InputBitStream& bit_input);
|
||||
ErrorOr<Vector<i32>, LoaderError> decode_fixed_lpc(FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input);
|
||||
ErrorOr<Vector<i32>, LoaderError> decode_verbatim(FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input);
|
||||
ErrorOr<Vector<i32>, LoaderError> decode_custom_lpc(FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input);
|
||||
MaybeLoaderError decode_residual(Vector<i32>& decoded, FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input);
|
||||
// decode a single rice partition that has its own rice parameter
|
||||
ALWAYS_INLINE Vector<i32> decode_rice_partition(u8 partition_type, u32 partitions, u32 partition_index, FlacSubframeHeader& subframe, InputBitStream& bit_input);
|
||||
ALWAYS_INLINE ErrorOr<Vector<i32>, LoaderError> decode_rice_partition(u8 partition_type, u32 partitions, u32 partition_index, FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input);
|
||||
|
||||
// Converters for special coding used in frame headers
|
||||
ALWAYS_INLINE ErrorOr<u32, LoaderError> convert_sample_count_code(u8 sample_count_code);
|
||||
|
@ -150,7 +108,7 @@ private:
|
|||
|
||||
// keep track of the start of the data in the FLAC stream to seek back more easily
|
||||
u64 m_data_start_location { 0 };
|
||||
OwnPtr<FlacInputStream<FLAC_BUFFER_SIZE>> m_stream;
|
||||
OwnPtr<Core::Stream::SeekableStream> m_stream;
|
||||
Optional<FlacFrameHeader> m_current_frame;
|
||||
// Whatever the last get_more_samples() call couldn't return gets stored here.
|
||||
Vector<Sample, FLAC_BUFFER_SIZE> m_unread_data;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue