/src/serenity/Userland/Libraries/LibAudio/FlacLoader.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021, kleines Filmröllchen <filmroellchen@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <AK/ByteString.h> |
8 | | #include <AK/Debug.h> |
9 | | #include <AK/DeprecatedFlyString.h> |
10 | | #include <AK/FixedArray.h> |
11 | | #include <AK/Format.h> |
12 | | #include <AK/Forward.h> |
13 | | #include <AK/IntegralMath.h> |
14 | | #include <AK/Math.h> |
15 | | #include <AK/MemoryStream.h> |
16 | | #include <AK/NonnullOwnPtr.h> |
17 | | #include <AK/ScopeGuard.h> |
18 | | #include <AK/StdLibExtras.h> |
19 | | #include <AK/Try.h> |
20 | | #include <AK/TypedTransfer.h> |
21 | | #include <AK/UFixedBigInt.h> |
22 | | #include <LibAudio/FlacLoader.h> |
23 | | #include <LibAudio/FlacTypes.h> |
24 | | #include <LibAudio/GenericTypes.h> |
25 | | #include <LibAudio/LoaderError.h> |
26 | | #include <LibAudio/MultiChannel.h> |
27 | | #include <LibAudio/Resampler.h> |
28 | | #include <LibAudio/VorbisComment.h> |
29 | | #include <LibCore/File.h> |
30 | | #include <LibCrypto/Checksum/ChecksumFunction.h> |
31 | | #include <LibCrypto/Checksum/ChecksummingStream.h> |
32 | | |
33 | | namespace Audio { |
34 | | |
35 | | FlacLoaderPlugin::FlacLoaderPlugin(NonnullOwnPtr<SeekableStream> stream) |
36 | 298 | : LoaderPlugin(move(stream)) |
37 | 298 | { |
38 | 298 | } |
39 | | |
40 | | ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> FlacLoaderPlugin::create(NonnullOwnPtr<SeekableStream> stream) |
41 | 298 | { |
42 | 298 | auto loader = make<FlacLoaderPlugin>(move(stream)); |
43 | 298 | TRY(loader->initialize()); |
44 | 152 | return loader; |
45 | 298 | } |
46 | | |
47 | | MaybeLoaderError FlacLoaderPlugin::initialize() |
48 | 298 | { |
49 | 298 | TRY(parse_header()); |
50 | 152 | TRY(reset()); |
51 | 152 | return {}; |
52 | 152 | } |
53 | | |
54 | | bool FlacLoaderPlugin::sniff(SeekableStream& stream) |
55 | 0 | { |
56 | 0 | BigEndianInputBitStream bit_input { MaybeOwned<Stream>(stream) }; |
57 | 0 | auto maybe_flac = bit_input.read_bits<u32>(32); |
58 | 0 | return !maybe_flac.is_error() && maybe_flac.value() == 0x664C6143; // "flaC" |
59 | 0 | } |
60 | | |
61 | | // 11.5 STREAM |
62 | | MaybeLoaderError FlacLoaderPlugin::parse_header() |
63 | 298 | { |
64 | 298 | BigEndianInputBitStream bit_input { MaybeOwned<Stream>(*m_stream) }; |
65 | | |
66 | | // A mixture of VERIFY and the non-crashing TRY(). |
67 | 298 | #define FLAC_VERIFY(check, category, msg) \ |
68 | 37.5k | do { \ |
69 | 37.5k | if (!(check)) { \ |
70 | 12 | return LoaderError { category, TRY(m_stream->tell()), TRY(String::formatted("FLAC header: {}", msg)) }; \ |
71 | 12 | } \ |
72 | 37.5k | } while (0) |
73 | | |
74 | | // Magic number |
75 | 298 | u32 flac = TRY(bit_input.read_bits<u32>(32)); |
76 | 298 | m_data_start_location += 4; |
77 | 298 | FLAC_VERIFY(flac == 0x664C6143, LoaderError::Category::Format, "Magic number must be 'flaC'"); // "flaC" |
78 | | |
79 | | // Receive the streaminfo block |
80 | 286 | auto streaminfo = TRY(next_meta_block(bit_input)); |
81 | 282 | FLAC_VERIFY(streaminfo.type == FlacMetadataBlockType::STREAMINFO, LoaderError::Category::Format, "First block must be STREAMINFO"); |
82 | 282 | FixedMemoryStream streaminfo_data_memory { streaminfo.data.bytes() }; |
83 | 282 | BigEndianInputBitStream streaminfo_data { MaybeOwned<Stream>(streaminfo_data_memory) }; |
84 | | |
85 | | // 11.10 METADATA_BLOCK_STREAMINFO |
86 | 282 | m_min_block_size = TRY(streaminfo_data.read_bits<u16>(16)); |
87 | 282 | FLAC_VERIFY(m_min_block_size >= 16, LoaderError::Category::Format, "Minimum block size must be 16"); |
88 | 282 | m_max_block_size = TRY(streaminfo_data.read_bits<u16>(16)); |
89 | 282 | FLAC_VERIFY(m_max_block_size >= 16, LoaderError::Category::Format, "Maximum block size"); |
90 | 282 | m_min_frame_size = TRY(streaminfo_data.read_bits<u32>(24)); |
91 | 282 | m_max_frame_size = TRY(streaminfo_data.read_bits<u32>(24)); |
92 | 282 | m_sample_rate = TRY(streaminfo_data.read_bits<u32>(20)); |
93 | 282 | FLAC_VERIFY(m_sample_rate <= 655350, LoaderError::Category::Format, "Sample rate"); |
94 | 282 | m_num_channels = TRY(streaminfo_data.read_bits<u8>(3)) + 1; // 0 = one channel |
95 | | |
96 | 282 | m_bits_per_sample = TRY(streaminfo_data.read_bits<u8>(5)) + 1; |
97 | 282 | if (m_bits_per_sample <= 8) { |
98 | | // FIXME: Signed/Unsigned issues? |
99 | 44 | m_sample_format = PcmSampleFormat::Uint8; |
100 | 238 | } else if (m_bits_per_sample <= 16) { |
101 | 195 | m_sample_format = PcmSampleFormat::Int16; |
102 | 195 | } else if (m_bits_per_sample <= 24) { |
103 | 10 | m_sample_format = PcmSampleFormat::Int24; |
104 | 33 | } else if (m_bits_per_sample <= 32) { |
105 | 33 | m_sample_format = PcmSampleFormat::Int32; |
106 | 33 | } else { |
107 | 0 | FLAC_VERIFY(false, LoaderError::Category::Format, "Sample bit depth too large"); |
108 | 0 | } |
109 | | |
110 | 282 | m_total_samples = TRY(streaminfo_data.read_bits<u64>(36)); |
111 | 282 | if (m_total_samples == 0) { |
112 | | // "A value of zero here means the number of total samples is unknown." |
113 | 13 | dbgln("FLAC Warning: File has unknown amount of samples, the loader will not stop before EOF"); |
114 | 13 | m_total_samples = NumericLimits<decltype(m_total_samples)>::max(); |
115 | 13 | } |
116 | | |
117 | 282 | VERIFY(streaminfo_data.is_aligned_to_byte_boundary()); |
118 | 564 | TRY(streaminfo_data.read_until_filled({ m_md5_checksum, sizeof(m_md5_checksum) })); |
119 | | |
120 | | // Parse other blocks |
121 | 564 | [[maybe_unused]] u16 meta_blocks_parsed = 1; |
122 | 564 | [[maybe_unused]] u16 total_meta_blocks = meta_blocks_parsed; |
123 | 564 | FlacRawMetadataBlock block = streaminfo; |
124 | 24.1k | while (!block.is_last_block) { |
125 | 24.0k | block = TRY(next_meta_block(bit_input)); |
126 | 23.9k | switch (block.type) { |
127 | 79 | case (FlacMetadataBlockType::SEEKTABLE): |
128 | 79 | TRY(load_seektable(block)); |
129 | 79 | break; |
130 | 6.07k | case FlacMetadataBlockType::PICTURE: |
131 | 6.07k | TRY(load_picture(block)); |
132 | 6.06k | break; |
133 | 1 | case FlacMetadataBlockType::APPLICATION: |
134 | | // Note: Third-party library can encode specific data in this. |
135 | 1 | dbgln("FLAC Warning: Unknown 'Application' metadata block encountered."); |
136 | 1 | [[fallthrough]]; |
137 | 148 | case FlacMetadataBlockType::PADDING: |
138 | | // Note: A padding block is empty and does not need any treatment. |
139 | 148 | break; |
140 | 4.47k | case FlacMetadataBlockType::VORBIS_COMMENT: |
141 | 4.47k | load_vorbis_comment(block); |
142 | 4.47k | break; |
143 | 13.1k | default: |
144 | | // TODO: Parse the remaining metadata block types. |
145 | 13.1k | break; |
146 | 23.9k | } |
147 | 23.9k | ++total_meta_blocks; |
148 | 23.9k | } |
149 | | |
150 | 152 | dbgln_if(AFLACLOADER_DEBUG, "Parsed FLAC header: blocksize {}-{}{}, framesize {}-{}, {}Hz, {}bit, {} channels, {} samples total ({:.2f}s), MD5 {:hex-dump}, data start at {:x} bytes, {} headers total (skipped {})", m_min_block_size, m_max_block_size, is_fixed_blocksize_stream() ? " (constant)" : "", m_min_frame_size, m_max_frame_size, m_sample_rate, pcm_bits_per_sample(m_sample_format), m_num_channels, m_total_samples, static_cast<float>(m_total_samples) / static_cast<float>(m_sample_rate), ReadonlyBytes { m_md5_checksum }, m_data_start_location, total_meta_blocks, total_meta_blocks - meta_blocks_parsed); |
151 | 152 | TRY(m_seektable.insert_seek_point({ 0, 0 })); |
152 | | |
153 | 152 | return {}; |
154 | 152 | } |
155 | | |
156 | | // 11.19. METADATA_BLOCK_PICTURE |
157 | | MaybeLoaderError FlacLoaderPlugin::load_picture(FlacRawMetadataBlock& block) |
158 | 6.07k | { |
159 | 6.07k | FixedMemoryStream memory_stream { block.data.bytes() }; |
160 | 6.07k | BigEndianInputBitStream picture_block_bytes { MaybeOwned<Stream>(memory_stream) }; |
161 | | |
162 | 6.07k | PictureData picture; |
163 | | |
164 | 6.07k | picture.type = static_cast<ID3PictureType>(TRY(picture_block_bytes.read_bits(32))); |
165 | | |
166 | 6.07k | auto const mime_string_length = TRY(picture_block_bytes.read_bits(32)); |
167 | 6.07k | auto offset_before_seeking = memory_stream.offset(); |
168 | 6.07k | if (offset_before_seeking + mime_string_length >= block.data.size()) |
169 | 3 | return LoaderError { LoaderError::Category::Format, TRY(m_stream->tell()), "Picture MIME type exceeds available data"_fly_string }; |
170 | | |
171 | | // "The MIME type string, in printable ASCII characters 0x20-0x7E." |
172 | 6.07k | picture.mime_string = TRY(String::from_stream(memory_stream, mime_string_length)); |
173 | 6.07k | for (auto code_point : picture.mime_string.code_points()) { |
174 | 370 | if (code_point < 0x20 || code_point > 0x7E) |
175 | 0 | return LoaderError { LoaderError::Category::Format, TRY(m_stream->tell()), "Picture MIME type is not ASCII in range 0x20 - 0x7E"_fly_string }; |
176 | 370 | } |
177 | | |
178 | 6.07k | auto const description_string_length = TRY(picture_block_bytes.read_bits(32)); |
179 | 6.07k | offset_before_seeking = memory_stream.offset(); |
180 | 6.07k | if (offset_before_seeking + description_string_length >= block.data.size()) |
181 | 2 | return LoaderError { LoaderError::Category::Format, TRY(m_stream->tell()), "Picture description exceeds available data"_fly_string }; |
182 | | |
183 | 6.07k | picture.description_string = TRY(String::from_stream(memory_stream, description_string_length)); |
184 | | |
185 | 6.07k | picture.width = TRY(picture_block_bytes.read_bits(32)); |
186 | 6.06k | picture.height = TRY(picture_block_bytes.read_bits(32)); |
187 | | |
188 | 6.06k | picture.color_depth = TRY(picture_block_bytes.read_bits(32)); |
189 | 6.06k | picture.colors = TRY(picture_block_bytes.read_bits(32)); |
190 | | |
191 | 6.06k | auto const picture_size = TRY(picture_block_bytes.read_bits(32)); |
192 | 6.06k | offset_before_seeking = memory_stream.offset(); |
193 | 6.06k | if (offset_before_seeking + picture_size > block.data.size()) |
194 | 0 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(TRY(m_stream->tell())), "Picture size exceeds available data"_fly_string }; |
195 | | |
196 | 6.06k | TRY(memory_stream.seek(picture_size, SeekMode::FromCurrentPosition)); |
197 | 6.06k | picture.data = Vector<u8> { block.data.bytes().slice(offset_before_seeking, picture_size) }; |
198 | | |
199 | 6.06k | m_pictures.append(move(picture)); |
200 | | |
201 | 6.06k | return {}; |
202 | 6.06k | } |
203 | | |
204 | | // 11.15. METADATA_BLOCK_VORBIS_COMMENT |
205 | | void FlacLoaderPlugin::load_vorbis_comment(FlacRawMetadataBlock& block) |
206 | 4.47k | { |
207 | 4.47k | auto metadata_or_error = Audio::load_vorbis_comment(block.data); |
208 | 4.47k | if (metadata_or_error.is_error()) { |
209 | 3.45k | dbgln("FLAC Warning: Vorbis comment invalid, error: {}", metadata_or_error.release_error()); |
210 | 3.45k | return; |
211 | 3.45k | } |
212 | 1.01k | m_metadata = metadata_or_error.release_value(); |
213 | 1.01k | } |
214 | | |
215 | | // 11.13. METADATA_BLOCK_SEEKTABLE |
216 | | MaybeLoaderError FlacLoaderPlugin::load_seektable(FlacRawMetadataBlock& block) |
217 | 79 | { |
218 | 79 | FixedMemoryStream memory_stream { block.data.bytes() }; |
219 | 79 | BigEndianInputBitStream seektable_bytes { MaybeOwned<Stream>(memory_stream) }; |
220 | 52.8k | for (size_t i = 0; i < block.length / 18; ++i) { |
221 | | // 11.14. SEEKPOINT |
222 | 52.8k | u64 sample_index = TRY(seektable_bytes.read_bits<u64>(64)); |
223 | 52.8k | u64 byte_offset = TRY(seektable_bytes.read_bits<u64>(64)); |
224 | | // The sample count of a seek point is not relevant to us. |
225 | 52.8k | [[maybe_unused]] u16 sample_count = TRY(seektable_bytes.read_bits<u16>(16)); |
226 | | // Placeholder, to be ignored. |
227 | 52.8k | if (sample_index == 0xFFFFFFFFFFFFFFFF) |
228 | 285 | continue; |
229 | | |
230 | 52.5k | SeekPoint seekpoint { |
231 | 52.5k | .sample_index = sample_index, |
232 | 52.5k | .byte_offset = byte_offset, |
233 | 52.5k | }; |
234 | 52.5k | TRY(m_seektable.insert_seek_point(seekpoint)); |
235 | 52.5k | } |
236 | 79 | dbgln_if(AFLACLOADER_DEBUG, "Loaded seektable of size {}", m_seektable.size()); |
237 | 79 | return {}; |
238 | 79 | } |
239 | | |
240 | | // 11.6 METADATA_BLOCK |
241 | | ErrorOr<FlacRawMetadataBlock, LoaderError> FlacLoaderPlugin::next_meta_block(BigEndianInputBitStream& bit_input) |
242 | 24.3k | { |
243 | | // 11.7 METADATA_BLOCK_HEADER |
244 | 24.3k | bool is_last_block = TRY(bit_input.read_bit()); |
245 | | // The block type enum constants agree with the specification |
246 | 24.3k | FlacMetadataBlockType type = (FlacMetadataBlockType)TRY(bit_input.read_bits<u8>(7)); |
247 | 24.3k | m_data_start_location += 1; |
248 | 24.3k | FLAC_VERIFY(type != FlacMetadataBlockType::INVALID, LoaderError::Category::Format, "Invalid metadata block"); |
249 | | |
250 | 24.3k | u32 block_length = TRY(bit_input.read_bits<u32>(24)); |
251 | 24.2k | m_data_start_location += 3; |
252 | | // Blocks can be zero-sized, which would trip up the raw data reader below. |
253 | 24.2k | if (block_length == 0) |
254 | 12.4k | return FlacRawMetadataBlock { |
255 | 12.4k | .is_last_block = is_last_block, |
256 | 12.4k | .type = type, |
257 | 12.4k | .length = 0, |
258 | 12.4k | .data = TRY(ByteBuffer::create_uninitialized(0)) |
259 | 12.4k | }; |
260 | 11.7k | auto block_data_result = ByteBuffer::create_uninitialized(block_length); |
261 | 11.7k | FLAC_VERIFY(!block_data_result.is_error(), LoaderError::Category::IO, "Out of memory"); |
262 | 11.7k | auto block_data = block_data_result.release_value(); |
263 | | |
264 | 11.7k | TRY(bit_input.read_until_filled(block_data)); |
265 | | |
266 | 11.6k | m_data_start_location += block_length; |
267 | 11.6k | return FlacRawMetadataBlock { |
268 | 11.6k | is_last_block, |
269 | 11.6k | type, |
270 | 11.6k | block_length, |
271 | 11.6k | block_data, |
272 | 11.6k | }; |
273 | 11.7k | } |
274 | | #undef FLAC_VERIFY |
275 | | |
276 | | MaybeLoaderError FlacLoaderPlugin::reset() |
277 | 152 | { |
278 | 152 | TRY(seek(0)); |
279 | 152 | m_current_frame.clear(); |
280 | 152 | return {}; |
281 | 152 | } |
282 | | |
283 | | MaybeLoaderError FlacLoaderPlugin::seek(int int_sample_index) |
284 | 152 | { |
285 | 152 | auto sample_index = static_cast<size_t>(int_sample_index); |
286 | 152 | if (sample_index == m_loaded_samples) |
287 | 152 | return {}; |
288 | | |
289 | 0 | auto maybe_target_seekpoint = m_seektable.seek_point_before(sample_index); |
290 | | // No seektable or no fitting entry: Perform normal forward read |
291 | 0 | if (!maybe_target_seekpoint.has_value()) { |
292 | 0 | if (sample_index < m_loaded_samples) { |
293 | 0 | TRY(m_stream->seek(m_data_start_location, SeekMode::SetPosition)); |
294 | 0 | m_loaded_samples = 0; |
295 | 0 | } |
296 | 0 | if (sample_index - m_loaded_samples == 0) |
297 | 0 | return {}; |
298 | 0 | dbgln_if(AFLACLOADER_DEBUG, "Seeking {} samples manually", sample_index - m_loaded_samples); |
299 | 0 | } else { |
300 | 0 | auto target_seekpoint = maybe_target_seekpoint.release_value(); |
301 | | |
302 | | // When a small seek happens, we may already be closer to the target than the seekpoint. |
303 | 0 | if (sample_index - target_seekpoint.sample_index > sample_index - m_loaded_samples) { |
304 | 0 | dbgln_if(AFLACLOADER_DEBUG, "Close enough to target ({} samples): ignoring seek point", sample_index - m_loaded_samples); |
305 | 0 | } else { |
306 | 0 | dbgln_if(AFLACLOADER_DEBUG, "Seeking to seektable: sample index {}, byte offset {}", target_seekpoint.sample_index, target_seekpoint.byte_offset); |
307 | 0 | auto position = target_seekpoint.byte_offset + m_data_start_location; |
308 | 0 | if (m_stream->seek(static_cast<i64>(position), SeekMode::SetPosition).is_error()) |
309 | 0 | return LoaderError { LoaderError::Category::IO, m_loaded_samples, TRY(String::formatted("Invalid seek position {}", position)) }; |
310 | 0 | m_loaded_samples = target_seekpoint.sample_index; |
311 | 0 | } |
312 | 0 | } |
313 | | |
314 | | // Skip frames until we're just before the target sample. |
315 | 0 | VERIFY(m_loaded_samples <= sample_index); |
316 | 0 | size_t frame_start_location; |
317 | 0 | while (m_loaded_samples <= sample_index) { |
318 | 0 | frame_start_location = TRY(m_stream->tell()); |
319 | 0 | (void)TRY(next_frame()); |
320 | 0 | m_loaded_samples += m_current_frame->sample_count; |
321 | 0 | } |
322 | 0 | TRY(m_stream->seek(frame_start_location, SeekMode::SetPosition)); |
323 | |
|
324 | 0 | return {}; |
325 | 0 | } |
326 | | |
327 | | bool FlacLoaderPlugin::should_insert_seekpoint_at(u64 sample_index) const |
328 | 107k | { |
329 | 107k | auto const max_seekpoint_distance = (maximum_seekpoint_distance_ms * m_sample_rate) / 1000; |
330 | 107k | auto const seek_tolerance = (seek_tolerance_ms * m_sample_rate) / 1000; |
331 | 107k | auto const current_seekpoint_distance = m_seektable.seek_point_sample_distance_around(sample_index).value_or(NumericLimits<u64>::max()); |
332 | 107k | auto const previous_seekpoint = m_seektable.seek_point_before(sample_index); |
333 | 107k | auto const distance_to_previous_seekpoint = previous_seekpoint.has_value() ? sample_index - previous_seekpoint->sample_index : NumericLimits<u64>::max(); |
334 | | |
335 | | // We insert a seekpoint only under two conditions: |
336 | | // - The seek points around us are spaced too far for what the loader recommends. |
337 | | // Prevents inserting too many seek points between pre-loaded seek points. |
338 | | // - We are so far away from the previous seek point that seeking will become too imprecise if we don't insert a seek point at least here. |
339 | | // Prevents inserting too many seek points at the end of files without pre-loaded seek points. |
340 | 107k | return current_seekpoint_distance >= max_seekpoint_distance && distance_to_previous_seekpoint >= seek_tolerance; |
341 | 107k | } |
342 | | |
343 | | ErrorOr<Vector<FixedArray<Sample>>, LoaderError> FlacLoaderPlugin::load_chunks(size_t samples_to_read_from_input) |
344 | 86.4k | { |
345 | 86.4k | ssize_t remaining_samples = static_cast<ssize_t>(m_total_samples - m_loaded_samples); |
346 | | // The first condition is relevant for unknown-size streams (total samples = 0 in the header) |
347 | 86.4k | if (m_stream->is_eof() || (m_total_samples < NumericLimits<u64>::max() && remaining_samples <= 0)) |
348 | 3 | return Vector<FixedArray<Sample>> {}; |
349 | | |
350 | 86.4k | size_t samples_to_read = min(samples_to_read_from_input, remaining_samples); |
351 | 86.4k | Vector<FixedArray<Sample>> frames; |
352 | | // In this case we can know exactly how many frames we're going to read. |
353 | 86.4k | if (is_fixed_blocksize_stream() && m_current_frame.has_value()) |
354 | 1.60k | TRY(frames.try_ensure_capacity(samples_to_read / m_current_frame->sample_count + 1)); |
355 | | |
356 | 86.4k | size_t sample_index = 0; |
357 | | |
358 | 194k | while (!m_stream->is_eof() && sample_index < samples_to_read) { |
359 | 215k | TRY(frames.try_append(TRY(next_frame()))); |
360 | 215k | sample_index += m_current_frame->sample_count; |
361 | 215k | } |
362 | | |
363 | 86.4k | m_loaded_samples += sample_index; |
364 | | |
365 | 86.3k | return frames; |
366 | 86.4k | } |
367 | | |
368 | | // 11.21. FRAME |
369 | | LoaderSamples FlacLoaderPlugin::next_frame() |
370 | 107k | { |
371 | 107k | #define FLAC_VERIFY(check, category, msg) \ |
372 | 430k | do { \ |
373 | 430k | if (!(check)) { \ |
374 | 53 | return LoaderError { category, static_cast<size_t>(m_current_sample_or_frame), TRY(String::formatted("FLAC header: {}", msg)) }; \ |
375 | 53 | } \ |
376 | 430k | } while (0) |
377 | | |
378 | 107k | auto frame_byte_index = TRY(m_stream->tell()); |
379 | 107k | auto sample_index = m_loaded_samples; |
380 | | // Insert a new seek point if we don't have enough here. |
381 | 107k | if (should_insert_seekpoint_at(sample_index)) { |
382 | 90.3k | dbgln_if(AFLACLOADER_DEBUG, "Inserting ad-hoc seek point for sample {} at byte {:x} (seekpoint spacing {} samples)", sample_index, frame_byte_index, m_seektable.seek_point_sample_distance_around(sample_index).value_or(NumericLimits<u64>::max())); |
383 | 90.3k | auto maybe_error = m_seektable.insert_seek_point({ .sample_index = sample_index, .byte_offset = frame_byte_index - m_data_start_location }); |
384 | 90.3k | if (maybe_error.is_error()) |
385 | 0 | dbgln("FLAC Warning: Inserting seek point for sample {} failed: {}", sample_index, maybe_error.release_error()); |
386 | 90.3k | } |
387 | | |
388 | 107k | auto frame_checksum_stream = TRY(try_make<Crypto::Checksum::ChecksummingStream<IBMCRC>>(MaybeOwned<Stream>(*m_stream))); |
389 | 107k | auto header_checksum_stream = TRY(try_make<Crypto::Checksum::ChecksummingStream<FlacFrameHeaderCRC>>(MaybeOwned<Stream>(*frame_checksum_stream))); |
390 | 107k | BigEndianInputBitStream bit_stream { MaybeOwned<Stream> { *header_checksum_stream } }; |
391 | | |
392 | | // 11.22. FRAME_HEADER |
393 | 107k | u16 sync_code = TRY(bit_stream.read_bits<u16>(14)); |
394 | 107k | FLAC_VERIFY(sync_code == 0b11111111111110, LoaderError::Category::Format, "Sync code"); |
395 | 107k | bool reserved_bit = TRY(bit_stream.read_bit()); |
396 | 107k | FLAC_VERIFY(reserved_bit == 0, LoaderError::Category::Format, "Reserved frame header bit"); |
397 | | // 11.22.2. BLOCKING STRATEGY |
398 | 107k | [[maybe_unused]] bool blocking_strategy = TRY(bit_stream.read_bit()); |
399 | | |
400 | 215k | u32 sample_count = TRY(convert_sample_count_code(TRY(bit_stream.read_bits<u8>(4)))); |
401 | | |
402 | 215k | u32 frame_sample_rate = TRY(convert_sample_rate_code(TRY(bit_stream.read_bits<u8>(4)))); |
403 | | |
404 | 215k | u8 channel_type_num = TRY(bit_stream.read_bits<u8>(4)); |
405 | 107k | FLAC_VERIFY(channel_type_num < 0b1011, LoaderError::Category::Format, "Channel assignment"); |
406 | 107k | FlacFrameChannelType channel_type = (FlacFrameChannelType)channel_type_num; |
407 | | |
408 | 215k | u8 bit_depth = TRY(convert_bit_depth_code(TRY(bit_stream.read_bits<u8>(3)))); |
409 | | |
410 | 215k | reserved_bit = TRY(bit_stream.read_bit()); |
411 | 107k | FLAC_VERIFY(reserved_bit == 0, LoaderError::Category::Format, "Reserved frame header end bit"); |
412 | | |
413 | | // 11.22.8. CODED NUMBER |
414 | 107k | m_current_sample_or_frame = TRY(read_utf8_char(bit_stream)); |
415 | | |
416 | | // Conditional header variables |
417 | | // 11.22.9. BLOCK SIZE INT |
418 | 107k | if (sample_count == FLAC_BLOCKSIZE_AT_END_OF_HEADER_8) { |
419 | 14.4k | sample_count = TRY(bit_stream.read_bits<u32>(8)) + 1; |
420 | 93.1k | } else if (sample_count == FLAC_BLOCKSIZE_AT_END_OF_HEADER_16) { |
421 | 2.14k | sample_count = TRY(bit_stream.read_bits<u32>(16)) + 1; |
422 | 2.14k | } |
423 | | |
424 | | // 11.22.10. SAMPLE RATE INT |
425 | 107k | if (frame_sample_rate == FLAC_SAMPLERATE_AT_END_OF_HEADER_8) { |
426 | 154 | frame_sample_rate = TRY(bit_stream.read_bits<u32>(8)) * 1000; |
427 | 107k | } else if (frame_sample_rate == FLAC_SAMPLERATE_AT_END_OF_HEADER_16) { |
428 | 136 | frame_sample_rate = TRY(bit_stream.read_bits<u32>(16)); |
429 | 107k | } else if (frame_sample_rate == FLAC_SAMPLERATE_AT_END_OF_HEADER_16X10) { |
430 | 1 | frame_sample_rate = TRY(bit_stream.read_bits<u32>(16)) * 10; |
431 | 1 | } |
432 | | |
433 | | // It does not matter whether we extract the checksum from the digest here, or extract the digest 0x00 after processing the checksum. |
434 | 107k | auto const calculated_header_checksum = header_checksum_stream->digest(); |
435 | | // 11.22.11. FRAME CRC |
436 | 107k | u8 specified_header_checksum = TRY(bit_stream.read_bits<u8>(8)); |
437 | 107k | VERIFY(bit_stream.is_aligned_to_byte_boundary()); |
438 | 107k | if (specified_header_checksum != calculated_header_checksum) |
439 | 107k | dbgln("FLAC frame {}: Calculated header checksum {:02x} is different from specified checksum {:02x}", m_current_sample_or_frame, calculated_header_checksum, specified_header_checksum); |
440 | | |
441 | 107k | 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_header_checksum, specified_header_checksum != calculated_header_checksum ? " (checksum error)"sv : ""sv); |
442 | | |
443 | 107k | m_current_frame = FlacFrameHeader { |
444 | 107k | .sample_rate = frame_sample_rate, |
445 | 107k | .sample_count = static_cast<u16>(sample_count), |
446 | 107k | .sample_or_frame_index = static_cast<u32>(m_current_sample_or_frame), |
447 | 107k | .blocking_strategy = static_cast<BlockingStrategy>(blocking_strategy), |
448 | 107k | .channels = channel_type, |
449 | 107k | .bit_depth = bit_depth, |
450 | 107k | .checksum = specified_header_checksum, |
451 | 107k | }; |
452 | | |
453 | 107k | u8 subframe_count = frame_channel_type_to_channel_count(channel_type); |
454 | 107k | TRY(m_subframe_buffers.try_resize_and_keep_capacity(subframe_count)); |
455 | | |
456 | 107k | float sample_rescale = 1 / static_cast<float>(1 << (m_current_frame->bit_depth - 1)); |
457 | 107k | dbgln_if(AFLACLOADER_DEBUG, "Samples will be rescaled from {} bits: factor {:.8f}", m_current_frame->bit_depth, sample_rescale); |
458 | | |
459 | 238k | for (u8 i = 0; i < subframe_count; ++i) { |
460 | 130k | FlacSubframeHeader new_subframe = TRY(next_subframe_header(bit_stream, i)); |
461 | 130k | auto& subframe_samples = m_subframe_buffers[i]; |
462 | 130k | subframe_samples.clear_with_capacity(); |
463 | 130k | TRY(parse_subframe(subframe_samples, new_subframe, bit_stream)); |
464 | | // We only verify the sample count for the common case of a constant sample rate. |
465 | 130k | if (m_sample_rate == m_current_frame->sample_rate) |
466 | 33.7k | VERIFY(subframe_samples.size() == m_current_frame->sample_count); |
467 | 130k | } |
468 | | |
469 | | // 11.2. Overview ("The audio data is composed of...") |
470 | 107k | bit_stream.align_to_byte_boundary(); |
471 | | |
472 | | // 11.23. FRAME_FOOTER |
473 | 107k | auto const calculated_frame_checksum = frame_checksum_stream->digest(); |
474 | 107k | auto const specified_frame_checksum = TRY(bit_stream.read_bits<u16>(16)); |
475 | 107k | if (calculated_frame_checksum != specified_frame_checksum) |
476 | 107k | dbgln("FLAC frame {}: Calculated frame checksum {:04x} is different from specified checksum {:04x}", m_current_sample_or_frame, calculated_frame_checksum, specified_frame_checksum); |
477 | 107k | dbgln_if(AFLACLOADER_DEBUG, "Subframe footer checksum: {:04x}{}", specified_frame_checksum, specified_frame_checksum != calculated_frame_checksum ? " (checksum error)"sv : ""sv); |
478 | | |
479 | 107k | FixedArray<Sample> samples; |
480 | | |
481 | 107k | switch (channel_type) { |
482 | 89.9k | case FlacFrameChannelType::Mono: |
483 | 90.2k | case FlacFrameChannelType::Stereo: |
484 | 90.5k | case FlacFrameChannelType::StereoCenter: |
485 | 90.5k | case FlacFrameChannelType::Surround4p0: |
486 | 91.2k | case FlacFrameChannelType::Surround5p0: |
487 | 91.2k | case FlacFrameChannelType::Surround5p1: |
488 | 91.2k | case FlacFrameChannelType::Surround6p1: |
489 | 91.7k | case FlacFrameChannelType::Surround7p1: { |
490 | 91.7k | auto new_samples = TRY(downmix_surround_to_stereo<Vector<i64>>(m_subframe_buffers, sample_rescale)); |
491 | 91.7k | samples.swap(new_samples); |
492 | 91.7k | break; |
493 | 91.7k | } |
494 | 622 | case FlacFrameChannelType::LeftSideStereo: { |
495 | 622 | auto new_samples = TRY(FixedArray<Sample>::create(m_current_frame->sample_count)); |
496 | 622 | samples.swap(new_samples); |
497 | | // channels are left (0) and side (1) |
498 | 5.80M | for (size_t i = 0; i < m_current_frame->sample_count; ++i) { |
499 | | // right = left - side |
500 | 5.80M | samples[i] = { static_cast<float>(m_subframe_buffers[0][i]) * sample_rescale, |
501 | 5.80M | static_cast<float>(m_subframe_buffers[0][i] - m_subframe_buffers[1][i]) * sample_rescale }; |
502 | 5.80M | } |
503 | 622 | break; |
504 | 622 | } |
505 | 13.8k | case FlacFrameChannelType::RightSideStereo: { |
506 | 13.8k | auto new_samples = TRY(FixedArray<Sample>::create(m_current_frame->sample_count)); |
507 | 13.8k | samples.swap(new_samples); |
508 | | // channels are side (0) and right (1) |
509 | 39.8M | for (size_t i = 0; i < m_current_frame->sample_count; ++i) { |
510 | | // left = right + side |
511 | 39.7M | samples[i] = { static_cast<float>(m_subframe_buffers[1][i] + m_subframe_buffers[0][i]) * sample_rescale, |
512 | 39.7M | static_cast<float>(m_subframe_buffers[1][i]) * sample_rescale }; |
513 | 39.7M | } |
514 | 13.8k | break; |
515 | 13.8k | } |
516 | 1.30k | case FlacFrameChannelType::MidSideStereo: { |
517 | 1.30k | auto new_samples = TRY(FixedArray<Sample>::create(m_current_frame->sample_count)); |
518 | 1.30k | samples.swap(new_samples); |
519 | | // channels are mid (0) and side (1) |
520 | 665k | for (size_t i = 0; i < m_subframe_buffers[0].size(); ++i) { |
521 | 664k | i64 mid = m_subframe_buffers[0][i]; |
522 | 664k | i64 side = m_subframe_buffers[1][i]; |
523 | 664k | mid *= 2; |
524 | | // prevent integer division errors |
525 | 664k | samples[i] = { static_cast<float>(mid + side) * .5f * sample_rescale, |
526 | 664k | static_cast<float>(mid - side) * .5f * sample_rescale }; |
527 | 664k | } |
528 | 1.30k | break; |
529 | 1.30k | } |
530 | 107k | } |
531 | | |
532 | 107k | return samples; |
533 | 107k | #undef FLAC_VERIFY |
534 | 107k | } |
535 | | |
536 | | // 11.22.3. INTERCHANNEL SAMPLE BLOCK SIZE |
537 | | ErrorOr<u32, LoaderError> FlacLoaderPlugin::convert_sample_count_code(u8 sample_count_code) |
538 | 107k | { |
539 | | // single codes |
540 | 107k | switch (sample_count_code) { |
541 | 0 | case 0: |
542 | 0 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(m_current_sample_or_frame), "Reserved block size"_fly_string }; |
543 | 1 | case 1: |
544 | 1 | return 192; |
545 | 14.4k | case 6: |
546 | 14.4k | return FLAC_BLOCKSIZE_AT_END_OF_HEADER_8; |
547 | 2.14k | case 7: |
548 | 2.14k | return FLAC_BLOCKSIZE_AT_END_OF_HEADER_16; |
549 | 107k | } |
550 | 91.0k | if (sample_count_code >= 2 && sample_count_code <= 5) { |
551 | 9.50k | return 576 * AK::exp2(sample_count_code - 2); |
552 | 9.50k | } |
553 | 81.5k | return 256 * AK::exp2(sample_count_code - 8); |
554 | 91.0k | } |
555 | | |
556 | | // 11.22.4. SAMPLE RATE |
557 | | ErrorOr<u32, LoaderError> FlacLoaderPlugin::convert_sample_rate_code(u8 sample_rate_code) |
558 | 107k | { |
559 | 107k | switch (sample_rate_code) { |
560 | 14.9k | case 0: |
561 | 14.9k | return m_sample_rate; |
562 | 75.5k | case 1: |
563 | 75.5k | return 88200; |
564 | 7 | case 2: |
565 | 7 | return 176400; |
566 | 1 | case 3: |
567 | 1 | return 192000; |
568 | 43 | case 4: |
569 | 43 | return 8000; |
570 | 0 | case 5: |
571 | 0 | return 16000; |
572 | 7.41k | case 6: |
573 | 7.41k | return 22050; |
574 | 6.84k | case 7: |
575 | 6.84k | return 24000; |
576 | 214 | case 8: |
577 | 214 | return 32000; |
578 | 1.20k | case 9: |
579 | 1.20k | return 44100; |
580 | 0 | case 10: |
581 | 0 | return 48000; |
582 | 1.11k | case 11: |
583 | 1.11k | return 96000; |
584 | 154 | case 12: |
585 | 154 | return FLAC_SAMPLERATE_AT_END_OF_HEADER_8; |
586 | 136 | case 13: |
587 | 136 | return FLAC_SAMPLERATE_AT_END_OF_HEADER_16; |
588 | 1 | case 14: |
589 | 1 | return FLAC_SAMPLERATE_AT_END_OF_HEADER_16X10; |
590 | 1 | default: |
591 | 1 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(m_current_sample_or_frame), "Invalid sample rate code"_fly_string }; |
592 | 107k | } |
593 | 107k | } |
594 | | |
595 | | // 11.22.6. SAMPLE SIZE |
596 | | ErrorOr<u8, LoaderError> FlacLoaderPlugin::convert_bit_depth_code(u8 bit_depth_code) |
597 | 107k | { |
598 | 107k | switch (bit_depth_code) { |
599 | 84.0k | case 0: |
600 | 84.0k | return m_bits_per_sample; |
601 | 1.02k | case 1: |
602 | 1.02k | return 8; |
603 | 650 | case 2: |
604 | 650 | return 12; |
605 | 0 | case 3: |
606 | 0 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(m_current_sample_or_frame), "Reserved sample size"_fly_string }; |
607 | 7.05k | case 4: |
608 | 7.05k | return 16; |
609 | 24 | case 5: |
610 | 24 | return 20; |
611 | 14.5k | case 6: |
612 | 14.5k | return 24; |
613 | 259 | case 7: |
614 | 259 | return 32; |
615 | 0 | default: |
616 | 0 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(m_current_sample_or_frame), TRY(String::formatted("Unsupported sample size {}", bit_depth_code)) }; |
617 | 107k | } |
618 | 107k | } |
619 | | |
620 | | // 11.22.5. CHANNEL ASSIGNMENT |
621 | | u8 frame_channel_type_to_channel_count(FlacFrameChannelType channel_type) |
622 | 107k | { |
623 | 107k | if (channel_type <= FlacFrameChannelType::Surround7p1) |
624 | 91.8k | return to_underlying(channel_type) + 1; |
625 | 15.7k | return 2; |
626 | 107k | } |
627 | | |
628 | | // 11.25. SUBFRAME_HEADER |
629 | | ErrorOr<FlacSubframeHeader, LoaderError> FlacLoaderPlugin::next_subframe_header(BigEndianInputBitStream& bit_stream, u8 channel_index) |
630 | 130k | { |
631 | 130k | u8 bits_per_sample = m_current_frame->bit_depth; |
632 | | |
633 | | // For inter-channel correlation, the side channel needs an extra bit for its samples |
634 | 130k | switch (m_current_frame->channels) { |
635 | 1.25k | case FlacFrameChannelType::LeftSideStereo: |
636 | 3.87k | case FlacFrameChannelType::MidSideStereo: |
637 | 3.87k | if (channel_index == 1) { |
638 | 1.93k | ++bits_per_sample; |
639 | 1.93k | } |
640 | 3.87k | break; |
641 | 27.6k | case FlacFrameChannelType::RightSideStereo: |
642 | 27.6k | if (channel_index == 0) { |
643 | 13.8k | ++bits_per_sample; |
644 | 13.8k | } |
645 | 27.6k | break; |
646 | | // "normal" channel types |
647 | 99.4k | default: |
648 | 99.4k | break; |
649 | 130k | } |
650 | | |
651 | | // zero-bit padding |
652 | 261k | if (TRY(bit_stream.read_bit()) != 0) |
653 | 32 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(m_current_sample_or_frame), "Zero bit padding"_fly_string }; |
654 | | |
655 | | // 11.25.1. SUBFRAME TYPE |
656 | 130k | u8 subframe_code = TRY(bit_stream.read_bits<u8>(6)); |
657 | 130k | if ((subframe_code >= 0b000010 && subframe_code <= 0b000111) || (subframe_code > 0b001100 && subframe_code < 0b100000)) |
658 | 3 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(m_current_sample_or_frame), "Subframe type"_fly_string }; |
659 | | |
660 | 130k | FlacSubframeType subframe_type; |
661 | 130k | u8 order = 0; |
662 | | // LPC has the highest bit set |
663 | 130k | if ((subframe_code & 0b100000) > 0) { |
664 | 629 | subframe_type = FlacSubframeType::LPC; |
665 | 629 | order = (subframe_code & 0b011111) + 1; |
666 | 130k | } else if ((subframe_code & 0b001000) > 0) { |
667 | | // Fixed has the third-highest bit set |
668 | 340 | subframe_type = FlacSubframeType::Fixed; |
669 | 340 | order = (subframe_code & 0b000111); |
670 | 129k | } else { |
671 | 129k | subframe_type = (FlacSubframeType)subframe_code; |
672 | 129k | } |
673 | | |
674 | | // 11.25.2. WASTED BITS PER SAMPLE FLAG |
675 | 130k | bool has_wasted_bits = TRY(bit_stream.read_bit()); |
676 | 130k | u8 k = 0; |
677 | 130k | if (has_wasted_bits) { |
678 | 1.98k | bool current_k_bit = 0; |
679 | 7.37k | do { |
680 | 7.37k | current_k_bit = TRY(bit_stream.read_bit()); |
681 | 7.37k | ++k; |
682 | 7.37k | } while (current_k_bit != 1); |
683 | 1.98k | } |
684 | | |
685 | 130k | return FlacSubframeHeader { |
686 | 130k | subframe_type, |
687 | 130k | order, |
688 | 130k | k, |
689 | 130k | bits_per_sample |
690 | 130k | }; |
691 | 130k | } |
692 | | |
693 | | ErrorOr<void, LoaderError> FlacLoaderPlugin::parse_subframe(Vector<i64>& samples, FlacSubframeHeader& subframe_header, BigEndianInputBitStream& bit_input) |
694 | 130k | { |
695 | 130k | TRY(samples.try_ensure_capacity(m_current_frame->sample_count)); |
696 | | |
697 | 130k | switch (subframe_header.type) { |
698 | 128k | case FlacSubframeType::Constant: { |
699 | | // 11.26. SUBFRAME_CONSTANT |
700 | 128k | u64 constant_value = TRY(bit_input.read_bits<u64>(subframe_header.bits_per_sample - subframe_header.wasted_bits_per_sample)); |
701 | 128k | dbgln_if(AFLACLOADER_DEBUG, " Constant subframe: {}", constant_value); |
702 | | |
703 | 128k | VERIFY(subframe_header.bits_per_sample - subframe_header.wasted_bits_per_sample != 0); |
704 | 128k | i64 constant = AK::sign_extend(static_cast<u64>(constant_value), subframe_header.bits_per_sample - subframe_header.wasted_bits_per_sample); |
705 | 431M | for (u64 i = 0; i < m_current_frame->sample_count; ++i) { |
706 | 431M | samples.unchecked_append(constant); |
707 | 431M | } |
708 | 128k | break; |
709 | 128k | } |
710 | 340 | case FlacSubframeType::Fixed: { |
711 | 340 | dbgln_if(AFLACLOADER_DEBUG, " Fixed LPC subframe order {}", subframe_header.order); |
712 | 340 | samples = TRY(decode_fixed_lpc(subframe_header, bit_input)); |
713 | 333 | break; |
714 | 340 | } |
715 | 1.03k | case FlacSubframeType::Verbatim: { |
716 | 1.03k | dbgln_if(AFLACLOADER_DEBUG, " Verbatim subframe"); |
717 | 1.03k | samples = TRY(decode_verbatim(subframe_header, bit_input)); |
718 | 1.03k | break; |
719 | 1.03k | } |
720 | 629 | case FlacSubframeType::LPC: { |
721 | 629 | dbgln_if(AFLACLOADER_DEBUG, " Custom LPC subframe order {}", subframe_header.order); |
722 | 629 | TRY(decode_custom_lpc(samples, subframe_header, bit_input)); |
723 | 613 | break; |
724 | 629 | } |
725 | 0 | default: |
726 | 0 | return LoaderError { LoaderError::Category::Unimplemented, static_cast<size_t>(m_current_sample_or_frame), "Unhandled FLAC subframe type"_fly_string }; |
727 | 130k | } |
728 | | |
729 | 434M | for (size_t i = 0; i < samples.size(); ++i) { |
730 | 434M | samples[i] <<= subframe_header.wasted_bits_per_sample; |
731 | 434M | } |
732 | | |
733 | | // Resamplers VERIFY that the sample rate is non-zero. |
734 | 130k | if (m_current_frame->sample_rate == 0 || m_sample_rate == 0 |
735 | 111k | || m_current_frame->sample_rate == m_sample_rate) |
736 | 35.3k | return {}; |
737 | | |
738 | 95.5k | ResampleHelper<i64> resampler(m_current_frame->sample_rate, m_sample_rate); |
739 | 95.5k | samples = resampler.resample(samples); |
740 | 95.5k | return {}; |
741 | 130k | } |
742 | | |
743 | | // 11.29. SUBFRAME_VERBATIM |
744 | | // Decode a subframe that isn't actually encoded, usually seen in random data |
745 | | ErrorOr<Vector<i64>, LoaderError> FlacLoaderPlugin::decode_verbatim(FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input) |
746 | 1.03k | { |
747 | 1.03k | Vector<i64> decoded; |
748 | 1.03k | decoded.ensure_capacity(m_current_frame->sample_count); |
749 | | |
750 | 1.03k | if (subframe.bits_per_sample <= subframe.wasted_bits_per_sample) { |
751 | 0 | return LoaderError { |
752 | 0 | LoaderError::Category::Format, |
753 | 0 | TRY(m_stream->tell()), |
754 | 0 | "Effective verbatim bits per sample are zero"_fly_string, |
755 | 0 | }; |
756 | 0 | } |
757 | 1.43k | for (size_t i = 0; i < m_current_frame->sample_count; ++i) { |
758 | 402 | decoded.unchecked_append(AK::sign_extend( |
759 | 402 | TRY(bit_input.read_bits<u64>(subframe.bits_per_sample - subframe.wasted_bits_per_sample)), |
760 | 402 | subframe.bits_per_sample - subframe.wasted_bits_per_sample)); |
761 | 402 | } |
762 | | |
763 | 1.03k | return decoded; |
764 | 1.03k | } |
765 | | |
766 | | // 11.28. SUBFRAME_LPC |
767 | | // Decode a subframe encoded with a custom linear predictor coding, i.e. the subframe provides the polynomial order and coefficients |
768 | | ErrorOr<void, LoaderError> FlacLoaderPlugin::decode_custom_lpc(Vector<i64>& decoded, FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input) |
769 | 629 | { |
770 | | // LPC must provide at least as many samples as its order. |
771 | 629 | if (subframe.order > m_current_frame->sample_count) |
772 | 0 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(m_current_sample_or_frame), "Too small frame for LPC order"_fly_string }; |
773 | | |
774 | 629 | decoded.ensure_capacity(m_current_frame->sample_count); |
775 | | |
776 | 629 | if (subframe.bits_per_sample <= subframe.wasted_bits_per_sample) { |
777 | 0 | return LoaderError { |
778 | 0 | LoaderError::Category::Format, |
779 | 0 | TRY(m_stream->tell()), |
780 | 0 | "Effective verbatim bits per sample are zero"_fly_string, |
781 | 0 | }; |
782 | 0 | } |
783 | | // warm-up samples |
784 | 5.95k | for (auto i = 0; i < subframe.order; ++i) { |
785 | 5.32k | decoded.unchecked_append(AK::sign_extend( |
786 | 5.32k | TRY(bit_input.read_bits<u64>(subframe.bits_per_sample - subframe.wasted_bits_per_sample)), |
787 | 5.32k | subframe.bits_per_sample - subframe.wasted_bits_per_sample)); |
788 | 5.32k | } |
789 | | |
790 | | // precision of the coefficients |
791 | 629 | u8 lpc_precision = TRY(bit_input.read_bits<u8>(4)); |
792 | 628 | if (lpc_precision == 0b1111) |
793 | 0 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(m_current_sample_or_frame), "Invalid linear predictor coefficient precision"_fly_string }; |
794 | 628 | lpc_precision += 1; |
795 | | |
796 | | // shift needed on the data (signed!) |
797 | 628 | i8 lpc_shift = static_cast<i8>(AK::sign_extend(TRY(bit_input.read_bits<u8>(5)), 5)); |
798 | | |
799 | 628 | Vector<i64, 32> coefficients; |
800 | 628 | coefficients.ensure_capacity(subframe.order); |
801 | | // read coefficients |
802 | 5.95k | for (auto i = 0; i < subframe.order; ++i) { |
803 | 5.32k | u64 raw_coefficient = TRY(bit_input.read_bits<u64>(lpc_precision)); |
804 | 5.32k | i64 coefficient = AK::sign_extend(raw_coefficient, lpc_precision); |
805 | 5.32k | coefficients.unchecked_append(coefficient); |
806 | 5.32k | } |
807 | | |
808 | 628 | dbgln_if(AFLACLOADER_DEBUG, " {}-bit {} shift coefficients: {}", lpc_precision, lpc_shift, coefficients); |
809 | | |
810 | 628 | TRY(decode_residual(decoded, subframe, bit_input)); |
811 | | |
812 | | // approximate the waveform with the predictor |
813 | 2.78M | for (size_t i = subframe.order; i < m_current_frame->sample_count; ++i) { |
814 | | // (see below) |
815 | 2.78M | Checked<i64> sample = 0; |
816 | 28.0M | for (size_t t = 0; t < subframe.order; ++t) { |
817 | | // It's really important that we compute in 64-bit land here. |
818 | | // Even though FLAC operates at a maximum bit depth of 32 bits, modern encoders use super-large coefficients for maximum compression. |
819 | | // These will easily overflow 32 bits and cause strange white noise that abruptly stops intermittently (at the end of a frame). |
820 | | // The simple fix of course is to do intermediate computations in 64 bits, but we additionally use saturating arithmetic. |
821 | | // These considerations are not in the original FLAC spec, but have been added to the IETF standard: https://datatracker.ietf.org/doc/html/draft-ietf-cellar-flac-03#appendix-A.3 |
822 | 25.3M | sample.saturating_add(Checked<i64>::saturating_mul(static_cast<i64>(coefficients[t]), static_cast<i64>(decoded[i - t - 1]))); |
823 | 25.3M | } |
824 | 2.78M | decoded[i] += lpc_shift >= 0 ? (sample.value() >> lpc_shift) : (sample.value() << -lpc_shift); |
825 | 2.78M | } |
826 | | |
827 | 613 | return {}; |
828 | 628 | } |
829 | | |
830 | | // 11.27. SUBFRAME_FIXED |
831 | | // Decode a subframe encoded with one of the fixed linear predictor codings |
832 | | ErrorOr<Vector<i64>, LoaderError> FlacLoaderPlugin::decode_fixed_lpc(FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input) |
833 | 340 | { |
834 | | // LPC must provide at least as many samples as its order. |
835 | 340 | if (subframe.order > m_current_frame->sample_count) |
836 | 0 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(m_current_sample_or_frame), "Too small frame for LPC order"_fly_string }; |
837 | | |
838 | 340 | Vector<i64> decoded; |
839 | 340 | decoded.ensure_capacity(m_current_frame->sample_count); |
840 | | |
841 | 340 | if (subframe.bits_per_sample <= subframe.wasted_bits_per_sample) { |
842 | 0 | return LoaderError { |
843 | 0 | LoaderError::Category::Format, |
844 | 0 | TRY(m_stream->tell()), |
845 | 0 | "Effective verbatim bits per sample are zero"_fly_string, |
846 | 0 | }; |
847 | 0 | } |
848 | | // warm-up samples |
849 | 1.27k | for (auto i = 0; i < subframe.order; ++i) { |
850 | 933 | decoded.unchecked_append(AK::sign_extend( |
851 | 933 | TRY(bit_input.read_bits<u64>(subframe.bits_per_sample - subframe.wasted_bits_per_sample)), |
852 | 932 | subframe.bits_per_sample - subframe.wasted_bits_per_sample)); |
853 | 932 | } |
854 | | |
855 | 672 | TRY(decode_residual(decoded, subframe, bit_input)); |
856 | | |
857 | 672 | dbgln_if(AFLACLOADER_DEBUG, " decoded length {}, {} order predictor, now at file offset {:x}", decoded.size(), subframe.order, TRY(m_stream->tell())); |
858 | | |
859 | | // Skip these comments if you don't care about the neat math behind fixed LPC :^) |
860 | | // These coefficients for the recursive prediction formula are the only ones that can be resolved to polynomial predictor functions. |
861 | | // The order equals the degree of the polynomial - 1, so the second-order predictor has an underlying polynomial of degree 1, a straight line. |
862 | | // More specifically, the closest approximation to a polynomial is used, and the degree depends on how many previous values are available. |
863 | | // This makes use of a very neat property of polynomials, which is that they are entirely characterized by their finitely many derivatives. |
864 | | // (Mathematically speaking, the infinite Taylor series of any polynomial equals the polynomial itself.) |
865 | | // Now remember that derivation is just the slope of the function, which is the same as the difference of two close-by values. |
866 | | // Therefore, with two samples we can calculate the first derivative at a sample via the difference, which gives us a polynomial of degree 1. |
867 | | // With three samples, we can do the same but also calculate the second derivative via the difference in the first derivatives. |
868 | | // This gives us a polynomial of degree 2, as it has two "proper" (non-constant) derivatives. |
869 | | // This can be continued for higher-order derivatives when we have more coefficients, giving us higher-order polynomials. |
870 | | // In essence, it's akin to a Lagrangian polynomial interpolation for every sample (but already pre-solved). |
871 | | |
872 | | // The coefficients for orders 0-3 originate from the SHORTEN codec: |
873 | | // http://mi.eng.cam.ac.uk/reports/svr-ftp/auto-pdf/robinson_tr156.pdf page 4 |
874 | | // The coefficients for order 4 are undocumented in the original FLAC specification(s), but can now be found in |
875 | | // https://datatracker.ietf.org/doc/html/draft-ietf-cellar-flac-03#section-10.2.5 |
876 | | // FIXME: Share this code with predict_fixed_lpc(). |
877 | 672 | switch (subframe.order) { |
878 | 2 | case 0: |
879 | | // s_0(t) = 0 |
880 | 56.8k | for (u32 i = subframe.order; i < m_current_frame->sample_count; ++i) |
881 | 56.8k | decoded[i] += 0; |
882 | 2 | break; |
883 | 80 | case 1: |
884 | | // s_1(t) = s(t-1) |
885 | 325k | for (u32 i = subframe.order; i < m_current_frame->sample_count; ++i) |
886 | 325k | decoded[i] += decoded[i - 1]; |
887 | 80 | break; |
888 | 10 | case 2: |
889 | | // s_2(t) = 2s(t-1) - s(t-2) |
890 | 105k | for (u32 i = subframe.order; i < m_current_frame->sample_count; ++i) |
891 | 105k | decoded[i] += 2 * decoded[i - 1] - decoded[i - 2]; |
892 | 10 | break; |
893 | 142 | case 3: |
894 | | // s_3(t) = 3s(t-1) - 3s(t-2) + s(t-3) |
895 | 28.7k | for (u32 i = subframe.order; i < m_current_frame->sample_count; ++i) |
896 | 28.6k | decoded[i] += 3 * decoded[i - 1] - 3 * decoded[i - 2] + decoded[i - 3]; |
897 | 142 | break; |
898 | 99 | case 4: |
899 | | // s_4(t) = 4s(t-1) - 6s(t-2) + 4s(t-3) - s(t-4) |
900 | 146k | for (u32 i = subframe.order; i < m_current_frame->sample_count; ++i) |
901 | 146k | decoded[i] += 4 * decoded[i - 1] - 6 * decoded[i - 2] + 4 * decoded[i - 3] - decoded[i - 4]; |
902 | 99 | break; |
903 | 0 | default: |
904 | 0 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(m_current_sample_or_frame), TRY(String::formatted("Unrecognized predictor order {}", subframe.order)) }; |
905 | 672 | } |
906 | 333 | return decoded; |
907 | 672 | } |
908 | | |
909 | | // 11.30. RESIDUAL |
910 | | // Decode the residual, the "error" between the function approximation and the actual audio data |
911 | | MaybeLoaderError FlacLoaderPlugin::decode_residual(Vector<i64>& decoded, FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input) |
912 | 967 | { |
913 | | // 11.30.1. RESIDUAL_CODING_METHOD |
914 | 967 | auto residual_mode = static_cast<FlacResidualMode>(TRY(bit_input.read_bits<u8>(2))); |
915 | 967 | u8 partition_order = TRY(bit_input.read_bits<u8>(4)); |
916 | 967 | size_t partitions = 1 << partition_order; |
917 | | |
918 | 967 | dbgln_if(AFLACLOADER_DEBUG, " {}-bit Rice partitions, {} total (order {})", residual_mode == FlacResidualMode::Rice4Bit ? "4"sv : "5"sv, partitions, partition_order); |
919 | | |
920 | 967 | if (partitions > m_current_frame->sample_count) |
921 | 1 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(m_current_sample_or_frame), "Too many Rice partitions, each partition must contain at least one sample"_fly_string }; |
922 | | // “The partition order MUST be such that the block size is evenly divisible by the number of partitions.” |
923 | | // FIXME: Check “The partition order also MUST be such that the (block size >> partition order) is larger than the predictor order.” |
924 | 966 | if (m_current_frame->sample_count % partitions != 0) |
925 | 0 | return LoaderError { LoaderError::Category::Format, TRY(m_stream->tell()), "Block size is not evenly divisible by number of partitions"_fly_string }; |
926 | | |
927 | 966 | if (residual_mode == FlacResidualMode::Rice4Bit) { |
928 | | // 11.30.2. RESIDUAL_CODING_METHOD_PARTITIONED_EXP_GOLOMB |
929 | | // decode a single Rice partition with four bits for the order k |
930 | 8.81k | for (size_t i = 0; i < partitions; ++i) { |
931 | | // FIXME: Write into the decode buffer directly. |
932 | 7.96k | auto rice_partition = TRY(decode_rice_partition(4, partitions, i, subframe, bit_input)); |
933 | 7.95k | decoded.extend(move(rice_partition)); |
934 | 7.95k | } |
935 | 861 | } else if (residual_mode == FlacResidualMode::Rice5Bit) { |
936 | | // 11.30.3. RESIDUAL_CODING_METHOD_PARTITIONED_EXP_GOLOMB2 |
937 | | // five bits equivalent |
938 | 30.9k | for (size_t i = 0; i < partitions; ++i) { |
939 | | // FIXME: Write into the decode buffer directly. |
940 | 30.8k | auto rice_partition = TRY(decode_rice_partition(5, partitions, i, subframe, bit_input)); |
941 | 30.8k | decoded.extend(move(rice_partition)); |
942 | 30.8k | } |
943 | 102 | } else |
944 | 3 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(m_current_sample_or_frame), "Reserved residual coding method"_fly_string }; |
945 | | |
946 | 946 | return {}; |
947 | 966 | } |
948 | | |
949 | | // 11.30.2.1. EXP_GOLOMB_PARTITION and 11.30.3.1. EXP_GOLOMB2_PARTITION |
950 | | // Decode a single Rice partition as part of the residual, every partition can have its own Rice parameter k |
951 | | ALWAYS_INLINE ErrorOr<Vector<i64>, LoaderError> FlacLoaderPlugin::decode_rice_partition(u8 partition_type, u32 partitions, u32 partition_index, FlacSubframeHeader& subframe, BigEndianInputBitStream& bit_input) |
952 | 38.8k | { |
953 | | // 11.30.2.2. EXP GOLOMB PARTITION ENCODING PARAMETER and 11.30.3.2. EXP-GOLOMB2 PARTITION ENCODING PARAMETER |
954 | 38.8k | u8 k = TRY(bit_input.read_bits<u8>(partition_type)); |
955 | | |
956 | 38.8k | u32 residual_sample_count; |
957 | 38.8k | if (partitions == 0) |
958 | 0 | residual_sample_count = m_current_frame->sample_count - subframe.order; |
959 | 38.8k | else |
960 | 38.8k | residual_sample_count = m_current_frame->sample_count / partitions; |
961 | 38.8k | if (partition_index == 0) { |
962 | 963 | if (subframe.order > residual_sample_count) |
963 | 0 | return LoaderError { LoaderError::Category::Format, static_cast<size_t>(m_current_sample_or_frame), "First Rice partition must advertise more residuals than LPC order"_fly_string }; |
964 | 963 | residual_sample_count -= subframe.order; |
965 | 963 | } |
966 | | |
967 | 38.8k | Vector<i64> rice_partition; |
968 | 38.8k | rice_partition.resize(residual_sample_count); |
969 | | |
970 | | // escape code for unencoded binary partition |
971 | 38.8k | if (k == (1 << partition_type) - 1) { |
972 | 330 | u8 unencoded_bps = TRY(bit_input.read_bits<u8>(5)); |
973 | 330 | if (unencoded_bps != 0) { |
974 | 3.83k | for (size_t r = 0; r < residual_sample_count; ++r) { |
975 | 3.63k | rice_partition[r] = AK::sign_extend(TRY(bit_input.read_bits<u32>(unencoded_bps)), unencoded_bps); |
976 | 3.63k | } |
977 | 194 | } |
978 | 38.5k | } else { |
979 | 3.55M | for (size_t r = 0; r < residual_sample_count; ++r) { |
980 | 3.51M | rice_partition[r] = TRY(decode_unsigned_exp_golomb(k, bit_input)); |
981 | 3.51M | } |
982 | 38.5k | } |
983 | | |
984 | 38.8k | return rice_partition; |
985 | 38.8k | } |
986 | | |
987 | | // Decode a single number encoded with Rice/Exponential-Golomb encoding (the unsigned variant) |
988 | | ALWAYS_INLINE ErrorOr<i32> decode_unsigned_exp_golomb(u8 k, BigEndianInputBitStream& bit_input) |
989 | 3.51M | { |
990 | 3.51M | u8 q = 0; |
991 | 16.8M | while (TRY(bit_input.read_bit()) == 0) |
992 | 4.89M | ++q; |
993 | | |
994 | | // least significant bits (remainder) |
995 | 3.51M | u32 rem = TRY(bit_input.read_bits<u32>(k)); |
996 | 3.51M | u32 value = q << k | rem; |
997 | | |
998 | 3.51M | return rice_to_signed(value); |
999 | 3.51M | } |
1000 | | |
1001 | | ErrorOr<u64> read_utf8_char(BigEndianInputBitStream& input) |
1002 | 107k | { |
1003 | 107k | u64 character; |
1004 | 107k | u8 start_byte = TRY(input.read_value<u8>()); |
1005 | | // Signal byte is zero: ASCII character |
1006 | 107k | if ((start_byte & 0b10000000) == 0) { |
1007 | 89.3k | return start_byte; |
1008 | 89.3k | } else if ((start_byte & 0b11000000) == 0b10000000) { |
1009 | 1 | return Error::from_string_literal("Illegal continuation byte"); |
1010 | 1 | } |
1011 | | // This algorithm supports the theoretical max 0xFF start byte, which is not part of the regular UTF-8 spec. |
1012 | 18.2k | u8 length = 1; |
1013 | 67.4k | while (((start_byte << length) & 0b10000000) == 0b10000000) |
1014 | 49.1k | ++length; |
1015 | | |
1016 | | // This is technically not spec-compliant, but if we take UTF-8 to its logical extreme, |
1017 | | // we can say 0xFF means there's 7 following continuation bytes and no data at all in the leading character. |
1018 | 18.2k | if (length == 8) [[unlikely]] { |
1019 | 533 | character = 0; |
1020 | 17.7k | } else { |
1021 | 17.7k | u8 bits_from_start_byte = 8 - (length + 1); |
1022 | 17.7k | u8 start_byte_bitmask = AK::exp2(bits_from_start_byte) - 1; |
1023 | 17.7k | character = start_byte_bitmask & start_byte; |
1024 | 17.7k | } |
1025 | 67.4k | for (u8 i = length - 1; i > 0; --i) { |
1026 | 49.1k | u8 current_byte = TRY(input.read_value<u8>()); |
1027 | 49.1k | character = (character << 6) | (current_byte & 0b00111111); |
1028 | 49.1k | } |
1029 | 18.2k | return character; |
1030 | 18.2k | } |
1031 | | |
1032 | | i32 rice_to_signed(u32 x) |
1033 | 3.51M | { |
1034 | | // positive numbers are even, negative numbers are odd |
1035 | | // bitmask for conditionally inverting the entire number, thereby "negating" it |
1036 | 3.51M | i32 sign = -static_cast<i32>(x & 1); |
1037 | | // copies the sign's sign onto the actual magnitude of x |
1038 | 3.51M | return static_cast<i32>(sign ^ (x >> 1)); |
1039 | 3.51M | } |
1040 | | } |