1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 13:27:35 +00:00

LibAudio: Optimize FlacLoader by avoiding allocations

- Pre-allocate and reuse sample decompression buffers. In many FLAC
  files, the amount of samples per frame is either constant or the
  largest frame will be hit within the first couple of frames. Also,
  during audio output, we need to move and combine the samples from the
  decompression buffers into the final output buffers anyways. Avoiding
  the reallocation of these large buffers provides an improvement from
  16x to 18x decode speed on strongly compressed but otherwise usual
  input.
- Leave a FIXME for a similar improvement that can be made in the
  residual decoder.
- Pre-allocate audio chunks if frame size is known.
- Use reasonable inline capacities in several places where we know the
  maximum or usual capacity needed.
This commit is contained in:
kleines Filmröllchen 2023-07-06 20:10:17 +02:00 committed by Linus Groh
parent 60ac254df6
commit 111fd1e5fe
3 changed files with 69 additions and 46 deletions

View file

@ -69,11 +69,11 @@ private:
// Helper of next_frame that fetches a sub frame's header
ErrorOr<FlacSubframeHeader, LoaderError> next_subframe_header(BigEndianInputBitStream& bit_input, u8 channel_index);
// Helper of next_frame that decompresses a subframe
ErrorOr<Vector<i64>, LoaderError> parse_subframe(FlacSubframeHeader& subframe_header, BigEndianInputBitStream& bit_input);
ErrorOr<void, LoaderError> parse_subframe(Vector<i64>& samples, FlacSubframeHeader& subframe_header, BigEndianInputBitStream& bit_input);
// Subframe-internal data decoders (heavy lifting)
ErrorOr<Vector<i64>, LoaderError> decode_fixed_lpc(FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input);
ErrorOr<Vector<i64>, LoaderError> decode_verbatim(FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input);
ErrorOr<Vector<i64>, LoaderError> decode_custom_lpc(FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input);
ErrorOr<void, LoaderError> decode_custom_lpc(Vector<i64>& decoded, FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input);
MaybeLoaderError decode_residual(Vector<i64>& decoded, FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input);
// decode a single rice partition that has its own rice parameter
ALWAYS_INLINE ErrorOr<Vector<i64>, LoaderError> decode_rice_partition(u8 partition_type, u32 partitions, u32 partition_index, FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input);
@ -110,6 +110,10 @@ private:
Optional<FlacFrameHeader> m_current_frame;
u64 m_current_sample_or_frame { 0 };
SeekTable m_seektable;
// Keep around a few temporary buffers whose allocated space can be reused.
// This is an empirical optimization since allocations and deallocations take a lot of time in the decoder.
mutable Vector<Vector<i64>, 2> m_subframe_buffers;
};
}