1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
//! `pulse_data()` parser + encoder primitive — ISO/IEC 14496-3
//! §4.4.6.3 / Table 4.7.
//!
//! `pulse_data()` is the optional "pulse escape" tool inside
//! `individual_channel_stream()`: when the encoder finds it cheaper
//! to replace a small number (1..=4) of quantised spectral
//! coefficients with smaller ones plus a fix-up record than to spend
//! the bits on the literal escape codeword, it writes a `pulse_data()`
//! block that the decoder uses to restore the original amplitudes
//! after Huffman decoding. The pulse escape is dispatched by the
//! one-bit `pulse_data_present` flag immediately after
//! `scale_factor_data()` (Table 4.44 / Table 4.50).
//!
//! ## Wire layout (Table 4.7)
//!
//! ```text
//! pulse_data() {
//! number_pulse; 2 bits
//! pulse_start_sfb; 6 bits
//! for (i = 0; i < number_pulse + 1; i++) {
//! pulse_offset[i]; 5 bits
//! pulse_amp[i]; 4 bits
//! }
//! }
//! ```
//!
//! Every field is fixed-width. The actual pulse count on the wire
//! is `number_pulse + 1` (so 1..=4 pulses, never zero), encoded in
//! 2 bits as `0..=3`.
//!
//! ## What this module covers
//!
//! * [`PulseData::parse`] — read a Table 4.7 block from a
//! [`BitReader`], surfacing the raw wire fields without applying
//! the §4.6.13 reconstruction (the spectral fix-up itself needs
//! `swb_offset_long_window[]` + the post-Huffman `x_quant` array,
//! neither of which exists in Phase 2 yet).
//! * [`PulseData::write`] — the inverse: serialise a [`PulseData`]
//! onto a [`BitWriter`] in bit-exact Table 4.7 form. Surfaces
//! field-overflow as [`Error::PulseDataEncodeInvalid`].
//!
//! ## What this module does *not* cover
//!
//! * The §4.6.13 reconstruction loop (`k +=
//! swb_offset[pulse_start_sfb]; k += pulse_offset[j]; x_quant[…] ±=
//! pulse_amp[j]`) is deferred until `swb_offset` tables land with
//! `spectral_data()`.
//! * The normative constraint that `pulse_data_present` *must* be 0
//! when `window_sequence == EIGHT_SHORT_SEQUENCE` (§4.4.6.3 last
//! paragraph) is the responsibility of the dispatching
//! `individual_channel_stream()` (which has not landed yet); the
//! parser and writer here intentionally surface the literal Table 4.7
//! bytes regardless of the surrounding window sequence so that
//! future round work has access to the raw decoded record.
//! * No validation against `swb_offset_long_window[fs_index]` — the
//! parser cannot tell whether `pulse_start_sfb` is in-range for a
//! given sample rate without the offset table; the encoder cannot
//! tell whether a pulse position lands inside the represented
//! coefficient grid. These are §4.6.13 reconstruction concerns,
//! not Table 4.7 wire-format concerns.
use ;
use crate::;
/// Per-pulse `(offset, amp)` record. Both fields are unsigned.
///
/// * `offset` — 5 bits. `pulse_offset[i]` per Table 4.7. Read by
/// the decoder as a delta added to the running coefficient index
/// `k` (initialised to `swb_offset[pulse_start_sfb]` before the
/// loop).
/// * `amp` — 4 bits. `pulse_amp[i]` per Table 4.7. Unsigned
/// magnitude added to (or subtracted from, depending on the sign
/// of the existing `x_quant` coefficient) the reconstructed
/// spectral coefficient.
/// Width in bits of the wire `pulse_offset` field. ISO/IEC 14496-3
/// Table 4.7.
pub const PULSE_OFFSET_BITS: u32 = 5;
/// Width in bits of the wire `pulse_amp` field. ISO/IEC 14496-3
/// Table 4.7.
pub const PULSE_AMP_BITS: u32 = 4;
/// Maximum pulse count expressible in the 2-bit `number_pulse`
/// field. The wire value runs `0..=3`; the actual pulse count is
/// `number_pulse + 1`, so `MAX_PULSES == 4`.
pub const MAX_PULSES: usize = 4;
/// Parsed `pulse_data()` block (Table 4.7).
///
/// `pulses` always carries 1..=4 entries (since `number_pulse + 1
/// >= 1`); this is enforced by the writer and produced by the
/// parser. An empty `pulses` vector is rejected by [`PulseData::write`].