19 std::uint32_t
hop = 64;
37 std::unique_ptr<SpectralFrameStamp[]>
frames;
43 std::unique_ptr<std::uint8_t[]>
bytes;
44 [[nodiscard]] std::span<const std::uint8_t>
view() const noexcept {
74 explicit operator bool() const noexcept {
75 return value.has_value();
82static_assert(
sizeof(float) == 4 && std::numeric_limits<float>::is_iec559);
83static_assert(
sizeof(double) == 8 && std::numeric_limits<double>::is_iec559);
92 if (g.profile != 1 || g.layout != 1)
94 const auto rate = std::bit_cast<std::uint64_t>(g.sample_rate);
95 if (g.fft_size < 256 || g.fft_size > 16384 || (g.fft_size & (g.fft_size - 1)) || !g.hop ||
96 g.hop > g.fft_size / 2 || !g.channels || g.channels > 16 || (rate >> 63) ||
97 !(rate & 0x7fffffffffffffffULL) || (rate & 0x7ff0000000000000ULL) == 0x7ff0000000000000ULL)
99 if (!count || count > 1048576)
102 s.components = 2ULL * g.channels * (g.fft_size / 2 + 1);
103 s.record_bytes = 16 + 4 * s.components;
104 s.payload = count * s.record_bytes;
105 if (s.payload > 67108864)
107 s.first_origin = -
static_cast<std::int64_t
>((g.fft_size - 1) / g.hop * g.hop);
111inline std::uint64_t
read(std::span<const std::uint8_t> b, std::size_t p,
unsigned n)
noexcept {
113 for (
unsigned i = 0;
i < n; ++
i)
114 v |= std::uint64_t(b[p +
i]) << (8 *
i);
117inline void write(std::uint8_t* b, std::size_t p, std::uint64_t v,
unsigned n)
noexcept {
118 for (
unsigned i = 0;
i < n; ++
i)
119 b[p +
i] =
static_cast<std::uint8_t
>(v >> (8 *
i));
122 bool strict)
noexcept {
123 if ((bits & 0x7f800000U) == 0x7f800000U)
125 if (strict && bits == 0x80000000U)
127 const auto local = index % (2ULL * (fft / 2 + 1));
128 if ((local == 1 || local == fft + 1) && (bits & 0x7fffffffU))
136inline SpectralCodecResult<OwnedSpectralStream>
144 r.memory.retained_bytes =
145 sizeof(r) + count *
sizeof(
SpectralFrameStamp) + count * s.components *
sizeof(float);
146 if (r.memory.retained_bytes > budget ||
147 r.memory.temporary_bytes > budget - r.memory.retained_bytes) {
161 for (std::uint64_t
i = 0;
i < count; ++
i)
162 out.
frames[
i] = {
i, s.first_origin +
static_cast<std::int64_t
>(
i * g.hop)};
163 r.value.emplace(std::move(out));
169inline SpectralCodecResult<OwnedSpectralStream>
174 r.memory.input_bytes = bytes.size();
179 if (bytes.size() < 64)
181 constexpr char magic[] =
"PULPSFRM";
182 for (
unsigned i = 0;
i < 8; ++
i)
183 if (bytes[
i] != magic[
i])
185 if (read(bytes, 8, 2) != 1 || read(bytes, 10, 2) != 64 || read(bytes, 28, 4) ||
189 g.profile =
static_cast<std::uint32_t
>(read(bytes, 12, 4));
190 g.fft_size =
static_cast<std::uint32_t
>(read(bytes, 16, 4));
191 g.hop =
static_cast<std::uint32_t
>(read(bytes, 20, 4));
192 g.channels =
static_cast<std::uint16_t
>(read(bytes, 24, 2));
193 g.layout =
static_cast<std::uint16_t
>(read(bytes, 26, 2));
194 g.sample_rate = std::bit_cast<double>(read(bytes, 32, 8));
195 const auto count = read(bytes, 40, 8);
197 const auto error = shape(g, count, s);
200 if (read(bytes, 48, 8) != s.payload || bytes.size() != 64 + s.payload)
202 r.memory.retained_bytes =
203 sizeof(r) + count *
sizeof(
SpectralFrameStamp) + count * s.components *
sizeof(float);
204 if (r.memory.retained_bytes > budget ||
205 r.memory.temporary_bytes > budget - r.memory.retained_bytes)
207 for (std::uint64_t
i = 0;
i < count; ++
i) {
208 const auto p =
static_cast<std::size_t
>(64 +
i * s.record_bytes);
210 const auto origin = s.first_origin +
static_cast<std::int64_t
>(
i * g.hop);
211 if (read(bytes, p, 8) !=
i || read(bytes, p + 8, 8) != std::bit_cast<std::uint64_t>(origin))
213 for (std::uint64_t j = 0; j < s.components; ++j) {
214 const auto e = component(
static_cast<std::uint32_t
>(read(bytes, p + 16 + 4 * j, 4)), j,
221 r.memory.input_bytes = bytes.size();
224 for (std::uint64_t
i = 0;
i < count; ++
i)
225 for (std::uint64_t j = 0; j < s.components; ++j)
226 r.value->components[
i * s.components + j] = std::bit_cast<float>(
227 static_cast<std::uint32_t
>(read(bytes, 80 +
i * s.record_bytes + 4 * j, 4)));
232inline SpectralCodecResult<EncodedSpectralStream>
242 const auto error = shape(in.geometry, in.frame_count, s);
245 if (in.component_count != in.frame_count * s.components || !in.frames || !in.components)
248 in.component_count *
sizeof(float);
249 r.memory.retained_bytes =
sizeof(r) + 64 + s.payload;
250 if (r.memory.retained_bytes > budget ||
251 r.memory.temporary_bytes > budget - r.memory.retained_bytes)
253 for (std::uint64_t
i = 0;
i < in.frame_count; ++
i) {
254 if (in.frames[
i].sequence !=
i ||
255 in.frames[
i].origin != s.first_origin +
static_cast<std::int64_t
>(
i * in.geometry.hop))
258 for (std::size_t j = 0; j < in.component_count; ++j) {
259 const auto e = component(std::bit_cast<std::uint32_t>(in.components[j]), j,
260 in.geometry.fft_size,
false);
265 out.
size =
static_cast<std::size_t
>(64 + s.payload);
266 out.
bytes.reset(
new (std::nothrow) std::uint8_t[out.
size]{});
269 auto* b = out.
bytes.get();
270 constexpr char magic[] =
"PULPSFRM";
271 for (
unsigned i = 0;
i < 8; ++
i)
276 write(b, 16, in.geometry.fft_size, 4);
277 write(b, 20, in.geometry.hop, 4);
278 write(b, 24, in.geometry.channels, 2);
280 write(b, 32, std::bit_cast<std::uint64_t>(in.geometry.sample_rate), 8);
281 write(b, 40, in.frame_count, 8);
282 write(b, 48, s.payload, 8);
283 for (std::uint64_t
i = 0;
i < in.frame_count; ++
i) {
284 const auto p =
static_cast<std::size_t
>(64 +
i * s.record_bytes);
285 write(b, p, in.frames[
i].sequence, 8);
286 write(b, p + 8, std::bit_cast<std::uint64_t>(in.frames[
i].origin), 8);
287 for (std::uint64_t j = 0; j < s.components; ++j) {
288 auto bits = std::bit_cast<std::uint32_t>(in.components[
i * s.components + j]);
289 if ((bits & 0x7fffffffU) == 0)
291 write(b, p + 16 + 4 * j, bits, 4);
294 r.value.emplace(std::move(out));
Definition spectral_frame_codec.hpp:81
SpectralCodecError shape(const SpectralStreamGeometry &g, std::uint64_t count, Shape &s) noexcept
Definition spectral_frame_codec.hpp:90
std::uint64_t read(std::span< const std::uint8_t > b, std::size_t p, unsigned n) noexcept
Definition spectral_frame_codec.hpp:111
SpectralCodecError component(std::uint32_t bits, std::uint64_t index, std::uint32_t fft, bool strict) noexcept
Definition spectral_frame_codec.hpp:121
void write(std::uint8_t *b, std::size_t p, std::uint64_t v, unsigned n) noexcept
Definition spectral_frame_codec.hpp:117
Definition additive_bank.hpp:218
@ AllocationFailure
Definition source_filter_analysis.hpp:38
SpectralCodecError
Definition spectral_frame_codec.hpp:49
@ ResourceLimit
Definition spectral_frame_codec.hpp:53
@ InvalidGeometry
Definition spectral_frame_codec.hpp:52
@ InvalidComponent
Definition spectral_frame_codec.hpp:56
@ None
Definition spectral_frame_codec.hpp:50
@ InvalidLength
Definition spectral_frame_codec.hpp:54
@ NoncanonicalZero
Definition spectral_frame_codec.hpp:57
@ UnsupportedFormat
Definition spectral_frame_codec.hpp:51
@ InvalidChronology
Definition spectral_frame_codec.hpp:55
@ AllocationFailure
Definition spectral_frame_codec.hpp:58
SpectralCodecResult< OwnedSpectralStream > make_spectral_stream(SpectralStreamGeometry g, std::uint64_t count, std::uint64_t budget=spectral_codec_memory_budget) noexcept
Allocate an editable owned stream with canonical chronology and zero bins.
Definition spectral_frame_codec.hpp:137
@ None
Definition beat_repeat_kernel.hpp:36
constexpr std::uint64_t spectral_codec_memory_budget
Definition spectral_frame_codec.hpp:79
SpectralCodecResult< EncodedSpectralStream > encode_spectral_stream(const OwnedSpectralStream &in, std::uint64_t budget=spectral_codec_memory_budget) noexcept
Canonicalize signed bin zeros without mutating the caller. Offline only.
Definition spectral_frame_codec.hpp:233
SpectralCodecResult< OwnedSpectralStream > decode_spectral_stream(std::span< const std::uint8_t > bytes, std::uint64_t budget=spectral_codec_memory_budget) noexcept
Validate the whole input before allocating; no partial stream is returned.
Definition spectral_frame_codec.hpp:170
@ i
Definition formant_filter_bank.hpp:20
Definition spectral_frame_codec.hpp:41
std::unique_ptr< std::uint8_t[]> bytes
Definition spectral_frame_codec.hpp:43
std::size_t size
Definition spectral_frame_codec.hpp:42
std::span< const std::uint8_t > view() const noexcept
Definition spectral_frame_codec.hpp:44
Arrays have exact element counts, with no hidden vector capacity.
Definition spectral_frame_codec.hpp:33
std::unique_ptr< float[]> components
Definition spectral_frame_codec.hpp:38
SpectralStreamGeometry geometry
Definition spectral_frame_codec.hpp:34
std::size_t component_count
Definition spectral_frame_codec.hpp:36
std::unique_ptr< SpectralFrameStamp[]> frames
Definition spectral_frame_codec.hpp:37
std::uint64_t frame_count
Definition spectral_frame_codec.hpp:35
Definition spectral_frame_codec.hpp:61
std::uint64_t retained_bytes
Destination arrays plus result object; allocator bookkeeping is excluded.
Definition spectral_frame_codec.hpp:63
std::uint64_t input_bytes
Caller-owned input is reported separately and never copied for validation.
Definition spectral_frame_codec.hpp:65
std::uint64_t temporary_bytes
Conservative allowance for fixed local validation/result objects; no heap scratch.
Definition spectral_frame_codec.hpp:67
Definition spectral_frame_codec.hpp:70
SpectralCodecError error
Definition spectral_frame_codec.hpp:71
SpectralCodecMemory memory
Definition spectral_frame_codec.hpp:72
std::optional< T > value
Definition spectral_frame_codec.hpp:73
Definition spectral_frame_codec.hpp:26
std::int64_t origin
Definition spectral_frame_codec.hpp:28
std::uint64_t sequence
Definition spectral_frame_codec.hpp:27
Offline profile 1: symmetric float Hann, unscaled forward FFT, 1/N inverse, local-origin phase,...
Definition spectral_frame_codec.hpp:17
std::uint32_t hop
Definition spectral_frame_codec.hpp:19
std::uint16_t layout
Definition spectral_frame_codec.hpp:23
std::uint16_t channels
Definition spectral_frame_codec.hpp:20
std::uint32_t profile
Definition spectral_frame_codec.hpp:22
double sample_rate
Definition spectral_frame_codec.hpp:21
std::uint32_t fft_size
Definition spectral_frame_codec.hpp:18
Definition spectral_frame_codec.hpp:85
std::uint64_t record_bytes
Definition spectral_frame_codec.hpp:86
std::uint64_t payload
Definition spectral_frame_codec.hpp:86
std::uint64_t components
Definition spectral_frame_codec.hpp:86
std::int64_t first_origin
Definition spectral_frame_codec.hpp:87