FastLED 3.10.6
Loading...
Searching...
No Matches
mp3_vbr_tag.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/stl/stdint.h"
4#include "fl/stl/noexcept.h"
5#include "fl/stl/span.h"
6
7namespace fl {
8namespace third_party {
9
35static const fl::u32 MP3D_DECODER_DELAY = 529;
36
37struct Mp3VbrTag {
39 bool present;
41 fl::u32 encoderDelay;
44};
45
58namespace detail {
59
60inline fl::u32 mp3VbrRead32(const fl::u8* p) FL_NO_EXCEPT {
61 return (static_cast<fl::u32>(p[0]) << 24) |
62 (static_cast<fl::u32>(p[1]) << 16) |
63 (static_cast<fl::u32>(p[2]) << 8) | static_cast<fl::u32>(p[3]);
64}
65
66inline bool mp3VbrMagic(const fl::u8* p, const char* magic) FL_NO_EXCEPT {
67 return p[0] == static_cast<fl::u8>(magic[0]) &&
68 p[1] == static_cast<fl::u8>(magic[1]) &&
69 p[2] == static_cast<fl::u8>(magic[2]) &&
70 p[3] == static_cast<fl::u8>(magic[3]);
71}
72
73} // namespace detail
74
77 out->present = false;
78 out->encoderDelay = 0;
79 out->encoderPadding = 0;
80 if (bytes.size() < 40) {
81 return false;
82 }
83 const fl::u8* const frame = bytes.data();
84 const fl::size length = bytes.size();
85 if (frame[0] != 0xFF || (frame[1] & 0xE0) != 0xE0) {
86 return false;
87 }
88
89 const int version_bits = (frame[1] >> 3) & 0x03;
90 const int layer_bits = (frame[1] >> 1) & 0x03;
91 if (layer_bits != 0x01) {
92 return false; // Layer III only; Xing/VBRI are not defined elsewhere.
93 }
94 const bool mpeg1 = version_bits == 0x03;
95 const bool mono = ((frame[3] >> 6) & 0x03) == 0x03;
96
97 // Side information sits between the header and the tag, and its size is
98 // fixed by version and channel count.
99 const fl::size side_info = mpeg1 ? (mono ? 17u : 32u) : (mono ? 9u : 17u);
100
101 // VBRI (Fraunhofer) always sits at a fixed offset and carries no delay we
102 // can trust to the sample, so it is reported as metadata without one.
103 if (length >= 40 && detail::mp3VbrMagic(frame + 36, "VBRI")) {
104 out->present = true;
105 return true;
106 }
107
108 const fl::size xing = 4 + side_info;
109 if (length < xing + 8) {
110 return false;
111 }
112 if (!detail::mp3VbrMagic(frame + xing, "Xing") &&
113 !detail::mp3VbrMagic(frame + xing, "Info")) {
114 return false;
115 }
116 out->present = true;
117
118 const fl::u32 flags = detail::mp3VbrRead32(frame + xing + 4);
119 fl::size cursor = xing + 8;
120 if (flags & 0x0001) { cursor += 4; } // frame count
121 if (flags & 0x0002) { cursor += 4; } // byte count
122 if (flags & 0x0004) { cursor += 100; } // seek table
123 if (flags & 0x0008) { cursor += 4; } // quality
124
125 // The encoder tag that follows is optional. Its delay and padding live 21
126 // bytes in, as 12 bits each packed across three bytes.
127 if (cursor + 24 > length) {
128 return true; // a tag frame, but with no usable delay information
129 }
130 const bool lame = detail::mp3VbrMagic(frame + cursor, "LAME") ||
131 detail::mp3VbrMagic(frame + cursor, "Lavc") ||
132 detail::mp3VbrMagic(frame + cursor, "Lavf");
133 if (!lame) {
134 return true;
135 }
136 const fl::u8* gap = frame + cursor + 21;
137 out->encoderDelay =
138 (static_cast<fl::u32>(gap[0]) << 4) | (static_cast<fl::u32>(gap[1]) >> 4);
139 out->encoderPadding =
140 ((static_cast<fl::u32>(gap[1]) & 0x0F) << 8) | static_cast<fl::u32>(gap[2]);
141 return true;
142}
143
144} // namespace third_party
145} // namespace fl
fl::UISlider length("Length", 1.0f, 0.0f, 1.0f, 0.01f)
fl::u32 mp3VbrRead32(const fl::u8 *p) FL_NO_EXCEPT
Definition mp3_vbr_tag.h:60
bool mp3VbrMagic(const fl::u8 *p, const char *magic) FL_NO_EXCEPT
Definition mp3_vbr_tag.h:66
Inspect one complete MPEG audio frame for a VBR metadata header.
Definition mp3_vbr_tag.h:58
bool Mp3ParseVbrTag(fl::span< const fl::u8 > bytes, Mp3VbrTag *out) FL_NO_EXCEPT
Definition mp3_vbr_tag.h:75
static const fl::u32 MP3D_DECODER_DELAY
Metadata carried by an MP3's first frame when an encoder wrote a Xing, Info, or VBRI header there.
Definition mp3_vbr_tag.h:35
bool present
The frame is metadata and must not be emitted as audio.
Definition mp3_vbr_tag.h:39
fl::u32 encoderDelay
Samples per channel of encoder priming to drop from the start.
Definition mp3_vbr_tag.h:41
fl::u32 encoderPadding
Samples per channel of padding to drop from the end.
Definition mp3_vbr_tag.h:43
unsigned char u8
Definition stdint.h:131
InputGamut g FL_NO_EXCEPT
Definition rgbw.h:121
Base definition for an LED controller.
Definition crgb.hpp:179