FlacWriter.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (c) 2023, kleines Filmröllchen <filmroellchen@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/MaybeOwned.h>
  8. #include <AK/Noncopyable.h>
  9. #include <AK/RefPtr.h>
  10. #include <AK/Stream.h>
  11. #include <AK/StringView.h>
  12. #include <LibAudio/Encoder.h>
  13. #include <LibAudio/FlacTypes.h>
  14. #include <LibAudio/Forward.h>
  15. #include <LibAudio/GenericTypes.h>
  16. #include <LibAudio/Sample.h>
  17. #include <LibAudio/SampleFormats.h>
  18. #include <LibCore/Forward.h>
  19. namespace Audio {
  20. // Encodes the sign representation method used in Rice coding.
  21. // Numbers alternate between positive and negative: 0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, ...
  22. ALWAYS_INLINE u32 signed_to_rice(i32 x);
  23. // Encode a single number encoded with exponential golomb encoding of the specified order (k).
  24. ALWAYS_INLINE ErrorOr<void> encode_unsigned_exp_golomb(u8 k, i32 value, BigEndianOutputBitStream& bit_stream);
  25. size_t count_exp_golomb_bits_in(u8 k, ReadonlySpan<i64> residuals);
  26. void predict_fixed_lpc(FlacFixedLPC order, ReadonlySpan<i64> samples, Span<i64> predicted_output);
  27. // A simple FLAC encoder that writes FLAC files compatible with the streamable subset.
  28. // The encoder currently has the following simple output properties:
  29. // FIXME: All frames have a fixed sample size, see below.
  30. // FIXME: All frames are encoded with the best fixed LPC predictor.
  31. // FIXME: All residuals are encoded in one Rice partition.
  32. class FlacWriter : public Encoder {
  33. AK_MAKE_NONCOPYABLE(FlacWriter);
  34. AK_MAKE_NONMOVABLE(FlacWriter);
  35. /// Tunable static parameters. Please try to improve these; only some have already been well-tuned!
  36. // Constant block size.
  37. static constexpr size_t block_size = 1024;
  38. // Used as a percentage to check residual costs before the estimated "necessary" estimation point.
  39. // We usually over-estimate residual costs, so this prevents us from overshooting the actual bail point.
  40. static constexpr double residual_cost_margin = 0.07;
  41. // At what sample index to first estimate residuals, so that the residual parameter can "stabilize" through more encoded values.
  42. static constexpr size_t first_residual_estimation = 16;
  43. // How many samples to advance at minimum before estimating residuals again.
  44. static constexpr size_t min_residual_estimation_step = 20;
  45. // After how many useless (i.e. worse than current optimal) Rice parameters to abort parameter search.
  46. // Note that due to the zig-zag search, we start with searching the parameters that are most likely to be good.
  47. static constexpr size_t useless_parameter_threshold = 2;
  48. // How often a seek point is inserted.
  49. static constexpr double seekpoint_period_seconds = 2.0;
  50. // Default padding reserved for seek points; enough for almost 4 minutes of audio.
  51. static constexpr size_t default_padding = 2048;
  52. enum class WriteState {
  53. // Header has not been written at all, audio data cannot be written.
  54. HeaderUnwritten,
  55. // Header was written, i.e. sample format is finalized,
  56. // but audio data has not been finalized and therefore some header information is still missing.
  57. FormatFinalized,
  58. // File is fully finalized, no more sample data can be written.
  59. FullyFinalized,
  60. };
  61. public:
  62. static ErrorOr<NonnullOwnPtr<FlacWriter>> create(NonnullOwnPtr<SeekableStream> stream, u32 sample_rate = 44100, u8 num_channels = 2, u16 bits_per_sample = 16);
  63. virtual ~FlacWriter();
  64. virtual ErrorOr<void> write_samples(ReadonlySpan<Sample> samples) override;
  65. virtual ErrorOr<void> finalize() override;
  66. u32 sample_rate() const { return m_sample_rate; }
  67. u8 num_channels() const { return m_num_channels; }
  68. PcmSampleFormat sample_format() const { return integer_sample_format_for(m_bits_per_sample).value(); }
  69. Stream const& output_stream() const { return *m_stream; }
  70. ErrorOr<void> set_num_channels(u8 num_channels);
  71. ErrorOr<void> set_sample_rate(u32 sample_rate);
  72. ErrorOr<void> set_bits_per_sample(u16 bits_per_sample);
  73. // The FLAC encoder by default tries to reserve some space for seek points,
  74. // but that may not be enough if more than approximately four minutes of audio are stored.
  75. // The sample count hint can be used to instruct the FLAC encoder on how much space to reserve for seek points,
  76. // which will both reduce the padding for small files and allow the FLAC encoder to write seek points at the end of large files.
  77. virtual void sample_count_hint(size_t sample_count) override;
  78. virtual ErrorOr<void> set_metadata(Metadata const& metadata) override;
  79. ErrorOr<void> finalize_header_format();
  80. private:
  81. FlacWriter(NonnullOwnPtr<SeekableStream>);
  82. ErrorOr<void> write_header();
  83. ErrorOr<void> write_frame();
  84. // Returns the frame start byte offset, to be used for creating a seektable.
  85. ErrorOr<size_t> write_frame_for(ReadonlySpan<Vector<i64, block_size>> subblock, FlacFrameChannelType channel_type);
  86. ErrorOr<void> write_subframe(ReadonlySpan<i64> subframe, BigEndianOutputBitStream& bit_stream, u8 bits_per_sample);
  87. ErrorOr<void> write_lpc_subframe(FlacLPCEncodedSubframe lpc_subframe, BigEndianOutputBitStream& bit_stream, u8 bits_per_sample);
  88. ErrorOr<void> write_verbatim_subframe(ReadonlySpan<i64> subframe, BigEndianOutputBitStream& bit_stream, u8 bits_per_sample);
  89. // Assumes 4-bit k for now.
  90. ErrorOr<void> write_rice_partition(u8 k, ReadonlySpan<i64> residuals, BigEndianOutputBitStream& bit_stream);
  91. // Aborts encoding once the costs exceed the previous minimum, thereby speeding up the encoder's parameter search.
  92. // In this case, an empty Optional is returned.
  93. ErrorOr<Optional<FlacLPCEncodedSubframe>> encode_fixed_lpc(FlacFixedLPC order, ReadonlySpan<i64> subframe, size_t current_min_cost, u8 bits_per_sample);
  94. ErrorOr<void> add_metadata_block(FlacRawMetadataBlock block, Optional<size_t> insertion_index = {});
  95. // Depending on whether the header is finished or not, we either write to the current position for an unfinished header,
  96. // or we write to the start of the last padding and adjust that padding block.
  97. ErrorOr<void> write_metadata_block(FlacRawMetadataBlock& block);
  98. // Determine how many seekpoints we can write depending on the size of our final padding.
  99. size_t max_number_of_seekpoints() const;
  100. ErrorOr<void> flush_seektable();
  101. NonnullOwnPtr<SeekableStream> m_stream;
  102. WriteState m_state { WriteState::HeaderUnwritten };
  103. Vector<Sample, block_size> m_sample_buffer {};
  104. size_t m_current_frame { 0 };
  105. u32 m_sample_rate;
  106. u8 m_num_channels;
  107. u16 m_bits_per_sample;
  108. // Data updated during encoding; written to the header at the end.
  109. u32 m_max_frame_size { 0 };
  110. u32 m_min_frame_size { NumericLimits<u32>::max() };
  111. size_t m_sample_count { 0 };
  112. // Remember where the STREAMINFO block was written in the stream.
  113. size_t m_streaminfo_start_index;
  114. // Start of the first frame, used for calculating seektable byte offsets.
  115. size_t m_frames_start_index;
  116. struct LastPadding {
  117. size_t start;
  118. size_t size;
  119. };
  120. // Remember last PADDING block data, since we overwrite part of it with "late" metadata blocks.
  121. Optional<LastPadding> m_last_padding;
  122. // Raw metadata blocks that will be written out before header finalization.
  123. Vector<FlacRawMetadataBlock> m_cached_metadata_blocks;
  124. // The full seektable, may be fully or partially written.
  125. SeekTable m_cached_seektable {};
  126. };
  127. }