taglib-wasm 2.2.2 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +197 -16
  3. package/dist/index.browser.d.ts +24 -4
  4. package/dist/index.browser.d.ts.map +1 -1
  5. package/dist/index.browser.js +1139 -217
  6. package/dist/index.d.ts +3 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +2 -0
  9. package/dist/simple.browser.js +539 -209
  10. package/dist/src/constants/properties.d.ts +2 -2
  11. package/dist/src/constants/specialized-properties.d.ts +2 -2
  12. package/dist/src/constants/specialized-properties.js +2 -2
  13. package/dist/src/errors/base.d.ts +17 -2
  14. package/dist/src/errors/base.d.ts.map +1 -1
  15. package/dist/src/errors/base.js +18 -0
  16. package/dist/src/runtime/detector.d.ts +16 -1
  17. package/dist/src/runtime/detector.d.ts.map +1 -1
  18. package/dist/src/runtime/detector.js +58 -52
  19. package/dist/src/runtime/platform-io.d.ts +8 -0
  20. package/dist/src/runtime/platform-io.d.ts.map +1 -1
  21. package/dist/src/runtime/platform-io.js +11 -11
  22. package/dist/src/runtime/unified-loader/module-selection.d.ts +2 -2
  23. package/dist/src/runtime/unified-loader/module-selection.d.ts.map +1 -1
  24. package/dist/src/runtime/unified-loader/module-selection.js +3 -5
  25. package/dist/src/runtime/wasi-adapter/adapter.d.ts +13 -1
  26. package/dist/src/runtime/wasi-adapter/adapter.d.ts.map +1 -1
  27. package/dist/src/runtime/wasi-adapter/adapter.js +17 -0
  28. package/dist/src/runtime/wasi-adapter/audio-properties.d.ts +4 -1
  29. package/dist/src/runtime/wasi-adapter/audio-properties.d.ts.map +1 -1
  30. package/dist/src/runtime/wasi-adapter/audio-properties.js +24 -6
  31. package/dist/src/runtime/wasi-adapter/path-open.d.ts +68 -0
  32. package/dist/src/runtime/wasi-adapter/path-open.d.ts.map +1 -0
  33. package/dist/src/runtime/wasi-adapter/path-open.js +76 -0
  34. package/dist/src/runtime/wasi-adapter/wasm-io.d.ts.map +1 -1
  35. package/dist/src/runtime/wasi-adapter/wasm-io.js +36 -28
  36. package/dist/src/runtime/wasi-host-loader.js +8 -3
  37. package/dist/src/runtime/wasmer-sdk-loader/types.d.ts +13 -0
  38. package/dist/src/runtime/wasmer-sdk-loader/types.d.ts.map +1 -1
  39. package/dist/src/simple/checksum-operations.d.ts +25 -0
  40. package/dist/src/simple/checksum-operations.d.ts.map +1 -0
  41. package/dist/src/simple/checksum-operations.js +7 -0
  42. package/dist/src/simple/index.d.ts +2 -0
  43. package/dist/src/simple/index.d.ts.map +1 -1
  44. package/dist/src/simple/index.js +2 -0
  45. package/dist/src/taglib/audio-file-checksum.d.ts +47 -0
  46. package/dist/src/taglib/audio-file-checksum.d.ts.map +1 -0
  47. package/dist/src/taglib/audio-file-checksum.js +77 -0
  48. package/dist/src/taglib/audio-file-impl.d.ts +4 -0
  49. package/dist/src/taglib/audio-file-impl.d.ts.map +1 -1
  50. package/dist/src/taglib/audio-file-impl.js +34 -2
  51. package/dist/src/taglib/audio-file-interface.d.ts +17 -0
  52. package/dist/src/taglib/audio-file-interface.d.ts.map +1 -1
  53. package/dist/src/taglib/embind-adapter.d.ts.map +1 -1
  54. package/dist/src/taglib/embind-adapter.js +4 -1
  55. package/dist/src/taglib/id3v2-frames.d.ts.map +1 -1
  56. package/dist/src/taglib/id3v2-frames.js +2 -2
  57. package/dist/src/taglib/media-ranges.d.ts +85 -0
  58. package/dist/src/taglib/media-ranges.d.ts.map +1 -0
  59. package/dist/src/taglib/media-ranges.js +192 -0
  60. package/dist/src/taglib/metadata-extent.d.ts +55 -0
  61. package/dist/src/taglib/metadata-extent.d.ts.map +1 -1
  62. package/dist/src/taglib/metadata-extent.js +24 -6
  63. package/dist/src/taglib/taglib-class.d.ts.map +1 -1
  64. package/dist/src/taglib/taglib-class.js +13 -24
  65. package/dist/src/types/audio-formats.d.ts +5 -5
  66. package/dist/src/types/audio-formats.d.ts.map +1 -1
  67. package/dist/src/types/format-property-keys.d.ts +1 -1
  68. package/dist/src/types/format-property-keys.d.ts.map +1 -1
  69. package/dist/src/types/tags.d.ts +8 -1
  70. package/dist/src/types/tags.d.ts.map +1 -1
  71. package/dist/src/utils/path.d.ts +12 -0
  72. package/dist/src/utils/path.d.ts.map +1 -1
  73. package/dist/src/utils/path.js +19 -0
  74. package/dist/src/utils/tag-mapping.d.ts.map +1 -1
  75. package/dist/src/utils/tag-mapping.js +2 -0
  76. package/dist/src/version.d.ts +1 -1
  77. package/dist/src/version.js +1 -1
  78. package/dist/src/wasm.d.ts +9 -0
  79. package/dist/src/wasm.d.ts.map +1 -1
  80. package/dist/src/web-utils/data-url.d.ts.map +1 -1
  81. package/dist/src/web-utils/data-url.js +4 -2
  82. package/dist/taglib-wasi.wasm +0 -0
  83. package/dist/taglib-web.wasm +0 -0
  84. package/dist/web.browser.d.ts +13 -0
  85. package/dist/web.browser.d.ts.map +1 -0
  86. package/dist/web.browser.js +3630 -0
  87. package/package.json +19 -17
@@ -1,8 +1,8 @@
1
1
  import { MetadataError, UnsupportedFormatError } from "../errors/classes.js";
2
2
  const FRAME_ID_PATTERN = /^[A-Z0-9]{4}$/;
3
3
  function assertMp3(format) {
4
- if (format !== "MP3") {
5
- throw new UnsupportedFormatError(format, ["MP3"], {
4
+ if (format !== "MP3" && format !== "AAC") {
5
+ throw new UnsupportedFormatError(format, ["MP3", "AAC"], {
6
6
  operation: "id3v2Frames"
7
7
  });
8
8
  }
@@ -0,0 +1,85 @@
1
+ export interface ByteRange {
2
+ offset: number;
3
+ length: number;
4
+ }
5
+ export interface RangeWalk {
6
+ kind: "ranges" | "fallback";
7
+ ranges: ByteRange[];
8
+ detail: string;
9
+ }
10
+ /**
11
+ * Start offset of a trailing tag run (ID3v1 and/or APEv2), scanning inward.
12
+ * TagLib ends a FLAC stream at its ID3v1 location for the same reason.
13
+ */
14
+ export declare function trailingTagStart(bytes: Uint8Array, end?: number): number;
15
+ export declare function walkMpeg(bytes: Uint8Array): RangeWalk;
16
+ /** STREAMINFO is a FLAC file's first metadata block: the `fLaC` marker, a
17
+ * 4-byte block header, then its 34-byte payload, whose last 16 bytes are the
18
+ * MD5 of the *uncompressed* stream — the digest `basis: "pcm"` reports. */
19
+ export declare function flacStreamInfoMd5(bytes: Uint8Array): string | undefined;
20
+ /**
21
+ * FLAC's encoded payload: the audio frames between the end of the metadata
22
+ * block chain and an appended ID3v1/APEv2 tag. An appended ID3v2 is *inside*
23
+ * the payload: TagLib ends a FLAC stream at its ID3v1 location
24
+ * (`flacfile.cpp:595-599`), and a tag not at that location is stream by the
25
+ * same rule — TagLib is this feature's ground truth, so the boundary is pinned
26
+ * by `tests/media-ranges.test.ts`, not "fixed" here. Nothing inside a FLAC
27
+ * stream delimits the frames — the block chain's end is the start, and the
28
+ * stream runs to EOF — so the whole rule is the block walk plus the
29
+ * trailing-tag trim.
30
+ *
31
+ * `flacAudioStart` may legitimately answer past `bytes.length`, because a
32
+ * block's declared length can reach beyond the bytes in hand: that is the
33
+ * extent the chain *implies*, and hashing it would read nothing while claiming
34
+ * a payload. The `end <= start` guard is what refuses it.
35
+ *
36
+ * The walk deliberately does **not** carry the STREAMINFO digest: a range result
37
+ * is not a digest carrier, and the PCM basis reads the digest with
38
+ * `flacStreamInfoMd5` directly. A second, unread path to the same value rots.
39
+ */
40
+ export declare function walkFlac(bytes: Uint8Array): RangeWalk;
41
+ /**
42
+ * MP4's payload: the contents of every non-empty top-level `mdat`, in file
43
+ * order — a fragmented file spreads its audio over several, and a rewritten one
44
+ * may carry an empty `mdat`, which is legal and contributes nothing. The header
45
+ * is excluded, and it is 16 bytes rather than 8 when the size took the 64-bit
46
+ * form.
47
+ *
48
+ * Deliberately not `metadata-extent.ts`'s atom walk: that one looks for `moov`
49
+ * to size the partial-load gate, so it bails on any size below 8 and has no
50
+ * 64-bit path. The checksum's rules differ — `size === 0` runs to EOF, a 64-bit
51
+ * size is legal, and anything the walk cannot fully account for is a fallback —
52
+ * so the two contracts stay apart rather than share an abstraction.
53
+ *
54
+ * Those fallbacks are the point. A range that runs past the buffer would hash
55
+ * zero padding while `bytesHashed` counts it as payload, and bytes no atom
56
+ * accounts for are not something this walk may call audio.
57
+ */
58
+ export declare function walkMp4(bytes: Uint8Array): RangeWalk;
59
+ /**
60
+ * WAV's payload: every non-empty `data` chunk's contents, payload only.
61
+ *
62
+ * The chunk list is the whole rule: a chunk is a 4-byte id, a 4-byte
63
+ * little-endian size that counts the payload but not the header, and that
64
+ * payload padded to an even length. Tag chunks (`LIST`, `id3 `, `bext`, `iXML`)
65
+ * are therefore skipped by construction rather than by name, and chunks that
66
+ * follow `data` cannot move or clip the range — which is the property the
67
+ * repo's `wav/kiss-snippet.wav` pins, `data` first and `LIST` + `id3 ` behind it.
68
+ *
69
+ * A chunk whose declared size reaches past the buffer is a fallback, not a
70
+ * clamp: hashing the bytes that survive would report a payload the file does not
71
+ * claim. That is also the truncated-file case.
72
+ */
73
+ export declare function walkWav(bytes: Uint8Array): RangeWalk;
74
+ /**
75
+ * The per-format dispatch: the one entry point a consumer calls, and the one
76
+ * place a format-level fallback becomes a whole-file range.
77
+ *
78
+ * Consumers MUST dispatch on `kind`, never on `ranges.length`. The walks
79
+ * themselves answer a fallback with `ranges: []`, which this function replaces
80
+ * with the whole file — so after normalization there is no empty-ranges answer
81
+ * to detect, and a caller testing `ranges.length === 0` would read a fallback as
82
+ * a genuine payload and hash the whole file while claiming a range.
83
+ */
84
+ export declare function mediaRanges(format: string, bytes: Uint8Array): RangeWalk;
85
+ //# sourceMappingURL=media-ranges.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-ranges.d.ts","sourceRoot":"","sources":["../../../src/taglib/media-ranges.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAgCD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,UAAU,EACjB,GAAG,SAAe,GACjB,MAAM,CAoBR;AA8DD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,CAYrD;AAED;;2EAE2E;AAC3E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAmBvE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,CAUrD;AAqBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,CAyBpD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,CAsBpD;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,SAAS,CAgCxE"}
@@ -0,0 +1,192 @@
1
+ import {
2
+ flacAudioStart,
3
+ flacMarkerOffset,
4
+ id3v2End,
5
+ mpegFrameLength
6
+ } from "./metadata-extent.js";
7
+ const decoder = new TextDecoder();
8
+ const text = (b, o, n) => decoder.decode(b.subarray(o, o + n));
9
+ const fallback = (detail) => ({
10
+ kind: "fallback",
11
+ ranges: [],
12
+ detail
13
+ });
14
+ function adtsFrameLength(bytes, at) {
15
+ if (bytes.length < at + 7) return 0;
16
+ if (bytes[at] !== 255 || (bytes[at + 1] & 246) !== 240) return 0;
17
+ const length = (bytes[at + 3] & 3) << 11 | bytes[at + 4] << 3 | bytes[at + 5] >> 5;
18
+ return length >= 7 ? length : 0;
19
+ }
20
+ const frameLengthAt = (bytes, at) => mpegFrameLength(bytes, at) || adtsFrameLength(bytes, at);
21
+ function trailingTagStart(bytes, end = bytes.length) {
22
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
23
+ let at = Math.max(0, Math.min(end, bytes.length));
24
+ for (; ; ) {
25
+ if (at >= 128 && text(bytes, at - 128, 3) === "TAG") {
26
+ at -= 128;
27
+ continue;
28
+ }
29
+ if (at >= 32 && text(bytes, at - 32, 8) === "APETAGEX") {
30
+ const size = view.getUint32(at - 32 + 12, true);
31
+ const flags = view.getUint32(at - 32 + 20, true);
32
+ const start = at - size - ((flags & 2147483648) !== 0 ? 32 : 0);
33
+ if (start < 0 || start >= at) return at;
34
+ at = start;
35
+ continue;
36
+ }
37
+ return at;
38
+ }
39
+ }
40
+ const MPEG_SCAN_LIMIT = 65536;
41
+ function firstFrame(bytes) {
42
+ const from = id3v2End(bytes) ?? 0;
43
+ const limit = Math.min(bytes.length - 6, from + MPEG_SCAN_LIMIT);
44
+ for (let o = from; o < limit; o++) {
45
+ const len = frameLengthAt(bytes, o);
46
+ if (len > 0 && frameLengthAt(bytes, o + len) > 0) return o;
47
+ }
48
+ return -1;
49
+ }
50
+ function forwardLastFrame(bytes, from, end) {
51
+ let o = from;
52
+ let start = -1;
53
+ let length = 0;
54
+ let frames = 0;
55
+ while (o + 6 <= end) {
56
+ const len = frameLengthAt(bytes, o);
57
+ if (len === 0 || o + len > end) break;
58
+ start = o;
59
+ length = len;
60
+ frames++;
61
+ o += len;
62
+ }
63
+ return { start, length, frames };
64
+ }
65
+ function walkMpeg(bytes) {
66
+ const from = firstFrame(bytes);
67
+ if (from < 0) return fallback("no valid first frame");
68
+ const end = trailingTagStart(bytes);
69
+ const last = forwardLastFrame(bytes, from, end);
70
+ if (last.start < 0) return fallback("no valid frames");
71
+ return {
72
+ kind: "ranges",
73
+ ranges: [{ offset: from, length: last.start + last.length - from }],
74
+ detail: `first=${from} last=${last.start}+${last.length} frames=${last.frames}`
75
+ };
76
+ }
77
+ function flacStreamInfoMd5(bytes) {
78
+ const marker = flacMarkerOffset(bytes);
79
+ if (marker === void 0) return void 0;
80
+ const header = marker + 4;
81
+ if (header + 4 > bytes.length) return void 0;
82
+ if ((bytes[header] & 127) !== 0) return void 0;
83
+ const blockLength = bytes[header + 1] << 16 | bytes[header + 2] << 8 | bytes[header + 3];
84
+ if (blockLength < 34) return void 0;
85
+ const payload = header + 4;
86
+ if (payload + 34 > bytes.length) return void 0;
87
+ let hex = "";
88
+ for (const byte of bytes.subarray(payload + 18, payload + 34)) {
89
+ hex += byte.toString(16).padStart(2, "0");
90
+ }
91
+ return hex;
92
+ }
93
+ function walkFlac(bytes) {
94
+ const start = flacAudioStart(bytes);
95
+ if (start === void 0) return fallback("no fLaC marker");
96
+ const end = trailingTagStart(bytes);
97
+ if (end <= start) return fallback("no audio bytes");
98
+ return {
99
+ kind: "ranges",
100
+ ranges: [{ offset: start, length: end - start }],
101
+ detail: `audioStart=${start} end=${end}`
102
+ };
103
+ }
104
+ function atomLength(bytes, view, o) {
105
+ const size = view.getUint32(o, false);
106
+ if (size === 0) return { length: bytes.length - o, headerSize: 8 };
107
+ if (size === 1) {
108
+ if (o + 16 > bytes.length) return void 0;
109
+ const big = view.getBigUint64(o + 8, false);
110
+ if (big > BigInt(Number.MAX_SAFE_INTEGER)) return void 0;
111
+ return { length: Number(big), headerSize: 16 };
112
+ }
113
+ return { length: size, headerSize: 8 };
114
+ }
115
+ function walkMp4(bytes) {
116
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
117
+ const ranges = [];
118
+ let o = 0;
119
+ while (o + 8 <= bytes.length) {
120
+ const type = text(bytes, o + 4, 4);
121
+ const atom = atomLength(bytes, view, o);
122
+ if (atom === void 0) return fallback(`malformed ${type} size`);
123
+ if (atom.length < atom.headerSize) {
124
+ return fallback(`malformed ${type} size`);
125
+ }
126
+ if (o + atom.length > bytes.length) return fallback(`oversized ${type}`);
127
+ if (type === "mdat" && atom.length > atom.headerSize) {
128
+ ranges.push({
129
+ offset: o + atom.headerSize,
130
+ length: atom.length - atom.headerSize
131
+ });
132
+ }
133
+ o += atom.length;
134
+ }
135
+ if (o !== bytes.length) return fallback("trailing bytes after the last atom");
136
+ if (ranges.length === 0) return fallback("no non-empty mdat");
137
+ return { kind: "ranges", ranges, detail: `${ranges.length} mdat(s)` };
138
+ }
139
+ function walkWav(bytes) {
140
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
141
+ if (text(bytes, 0, 4) !== "RIFF") return fallback("not RIFF");
142
+ if (text(bytes, 8, 4) !== "WAVE") return fallback("not WAVE");
143
+ const ranges = [];
144
+ let o = 12;
145
+ while (o + 8 <= bytes.length) {
146
+ const id = text(bytes, o, 4);
147
+ const size = view.getUint32(o + 4, true);
148
+ const dataStart = o + 8;
149
+ if (dataStart + size > bytes.length) return fallback(`truncated ${id}`);
150
+ if (id === "data" && size > 0) {
151
+ ranges.push({ offset: dataStart, length: size });
152
+ }
153
+ o = dataStart + size + size % 2;
154
+ }
155
+ if (ranges.length === 0) return fallback("no data chunk");
156
+ return { kind: "ranges", ranges, detail: `${ranges.length} data chunk(s)` };
157
+ }
158
+ function mediaRanges(format, bytes) {
159
+ const walked = (() => {
160
+ switch (format.toUpperCase()) {
161
+ case "MP3":
162
+ case "AAC":
163
+ return walkMpeg(bytes);
164
+ case "FLAC":
165
+ return walkFlac(bytes);
166
+ case "MP4":
167
+ case "M4A":
168
+ return walkMp4(bytes);
169
+ case "WAV":
170
+ return walkWav(bytes);
171
+ default:
172
+ return { kind: "fallback", ranges: [], detail: "format not covered" };
173
+ }
174
+ })();
175
+ if (walked.kind === "fallback") {
176
+ return {
177
+ kind: "fallback",
178
+ ranges: [{ offset: 0, length: bytes.length }],
179
+ detail: `${walked.detail} \u2192 whole file`
180
+ };
181
+ }
182
+ return walked;
183
+ }
184
+ export {
185
+ flacStreamInfoMd5,
186
+ mediaRanges,
187
+ trailingTagStart,
188
+ walkFlac,
189
+ walkMp4,
190
+ walkMpeg,
191
+ walkWav
192
+ };
@@ -14,7 +14,62 @@
14
14
  * asymmetric: return true ONLY when the metadata is provably contained. Anything
15
15
  * unrecognised, malformed, or unbounded answers false, which costs a full read
16
16
  * and never costs correctness.
17
+ *
18
+ * The container walkers themselves are exported (id3v2End, mpegFrameLength,
19
+ * flacAudioStart, flacMarkerOffset) because the media checksum walks the same
20
+ * containers to find a file's encoded-audio payload. One walker per container:
21
+ * a second copy of these rules could silently disagree with the one that
22
+ * decides whether a splice is safe.
23
+ */
24
+ /**
25
+ * End of an ID3v2 tag at offset 0, or undefined when there is none.
26
+ *
27
+ * The size field is "syncsafe": seven bits per byte, so the high bit can never
28
+ * produce a false frame sync. A footer, when the flags say there is one, adds
29
+ * ten bytes that the size does not cover.
30
+ *
31
+ * The `ID3` magic check is part of the contract, not a convenience: the size
32
+ * arithmetic reads a number out of any ten bytes, so a tagless buffer would
33
+ * otherwise report 22.8 million as the end of a tag it does not have. Callers
34
+ * that have already established the magic pay one comparison for it; callers
35
+ * that have not (the media checksum walks) need it.
36
+ */
37
+ export declare function id3v2End(bytes: Uint8Array): number | undefined;
38
+ /**
39
+ * Offset of FLAC's `fLaC` stream marker — at 0, or just past a prepended ID3v2
40
+ * tag (TagLib supports exactly that, flacfile.cpp:90) — or undefined when
41
+ * neither is there. A caller that only wants STREAMINFO can seek straight to it
42
+ * instead of walking the metadata-block chain.
43
+ */
44
+ export declare function flacMarkerOffset(bytes: Uint8Array): number | undefined;
45
+ /**
46
+ * Offset of FLAC's first audio byte: the end of the metadata-block chain, past
47
+ * the optional ID3v2 tag.
48
+ *
49
+ * The chain is walked from block headers alone, so the result can exceed
50
+ * `bytes.length` when a block's declared length reaches past the buffer — that
51
+ * is the extent the chain implies, and the caller decides whether it holds
52
+ * enough of the file to believe it. A buffer too short to hold the next block
53
+ * header has no implied extent at all and answers undefined, as does one with
54
+ * no `fLaC` marker.
55
+ */
56
+ export declare function flacAudioStart(bytes: Uint8Array): number | undefined;
57
+ /**
58
+ * Length in bytes of the MPEG (Layer I/II/III) frame whose header sits at `at`,
59
+ * or 0 when `at` is not a plausible frame header.
60
+ *
61
+ * Plausibility is the header alone: eleven sync bits, a non-reserved version
62
+ * and layer, a bitrate index that is neither free (0) nor invalid (15), and a
63
+ * sample-rate index that is not reserved (3). Nothing here looks at what
64
+ * FOLLOWS the frame — a frame header at the very end of a file is as plausible
65
+ * as any other, which is what lets a walk reach the last frame. Callers that
66
+ * need confidence the bytes really are MPEG audio want isMpegFrameSync, which
67
+ * adds the next-header consistency check.
68
+ *
69
+ * The arithmetic mirrors mpegheader.cpp:236-264: bitrate/sample-rate tables
70
+ * plus the padding bit, and C++ integer division truncates.
17
71
  */
72
+ export declare function mpegFrameLength(bytes: Uint8Array, at: number): number;
18
73
  /**
19
74
  * True only when the metadata of `header` provably ends within `limit` bytes.
20
75
  *
@@ -1 +1 @@
1
- {"version":3,"file":"metadata-extent.d.ts","sourceRoot":"","sources":["../../../src/taglib/metadata-extent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAgPH;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,GACZ,OAAO,CAiCT;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAmBT"}
1
+ {"version":3,"file":"metadata-extent.d.ts","sourceRoot":"","sources":["../../../src/taglib/metadata-extent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAgBH;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAM9D;AA2BD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAItE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAIpE;AAwGD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CA8BrE;AA2DD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,GACZ,OAAO,CAiCT;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAmBT"}
@@ -9,7 +9,7 @@ function startsWith(bytes, magic, at = 0) {
9
9
  return true;
10
10
  }
11
11
  function id3v2End(bytes) {
12
- if (bytes.length < 10) return void 0;
12
+ if (!startsWith(bytes, "ID3") || bytes.length < 10) return void 0;
13
13
  const size = bytes[6] << 21 | bytes[7] << 14 | bytes[8] << 7 | bytes[9];
14
14
  const hasFooter = (bytes[5] & 16) !== 0;
15
15
  return 10 + size + (hasFooter ? 10 : 0);
@@ -25,6 +25,16 @@ function flacEnd(bytes, limit, start) {
25
25
  if (isLast) return offset;
26
26
  }
27
27
  }
28
+ function flacMarkerOffset(bytes) {
29
+ const at = startsWith(bytes, "ID3") ? id3v2End(bytes) : 0;
30
+ if (at === void 0) return void 0;
31
+ return startsWith(bytes, "fLaC", at) ? at : void 0;
32
+ }
33
+ function flacAudioStart(bytes) {
34
+ const at = flacMarkerOffset(bytes);
35
+ if (at === void 0) return void 0;
36
+ return flacEnd(bytes, bytes.length, at);
37
+ }
28
38
  function mp4MoovEnd(bytes, limit, start) {
29
39
  let offset = start;
30
40
  const readable = Math.min(bytes.length, limit);
@@ -97,16 +107,16 @@ const MPEG_SAMPLE_RATES = [
97
107
  [11025, 12e3, 8e3]
98
108
  // MPEG-2.5
99
109
  ];
100
- function isMpegFrameSync(bytes, at = 0) {
101
- if (bytes.length < at + 4) return false;
102
- if (bytes[at] !== 255 || (bytes[at + 1] & 224) !== 224) return false;
110
+ function mpegFrameLength(bytes, at) {
111
+ if (bytes.length < at + 4) return 0;
112
+ if (bytes[at] !== 255 || (bytes[at + 1] & 224) !== 224) return 0;
103
113
  const version = bytes[at + 1] >> 3 & 3;
104
114
  const layer = bytes[at + 1] >> 1 & 3;
105
- if (version === 1 || layer === 0) return false;
115
+ if (version === 1 || layer === 0) return 0;
106
116
  const bitrateIndex = bytes[at + 2] >> 4 & 15;
107
117
  const sampleRateIndex = bytes[at + 2] >> 2 & 3;
108
118
  if (bitrateIndex === 0 || bitrateIndex === 15 || sampleRateIndex === 3) {
109
- return false;
119
+ return 0;
110
120
  }
111
121
  const mpeg1 = version === 3;
112
122
  const layerIndex = layer ^ 3;
@@ -116,6 +126,10 @@ function isMpegFrameSync(bytes, at = 0) {
116
126
  const samplesPerFrame = layerIndex === 2 ? mpeg1 ? 1152 : 576 : layerIndex === 1 ? 1152 : 384;
117
127
  let frameLength = Math.floor(samplesPerFrame * bitrate * 125 / sampleRate);
118
128
  if ((bytes[at + 2] & 2) !== 0) frameLength += layerIndex === 0 ? 4 : 1;
129
+ return frameLength === 0 ? 0 : frameLength;
130
+ }
131
+ function isMpegFrameSync(bytes, at = 0) {
132
+ const frameLength = mpegFrameLength(bytes, at);
119
133
  if (frameLength === 0) return false;
120
134
  const next = at + frameLength;
121
135
  if (bytes.length < next + 4) return false;
@@ -166,6 +180,10 @@ function trailerFitsInFooter(tail, footerSize) {
166
180
  return true;
167
181
  }
168
182
  export {
183
+ flacAudioStart,
184
+ flacMarkerOffset,
185
+ id3v2End,
169
186
  metadataFitsInHeader,
187
+ mpegFrameLength,
170
188
  trailerFitsInFooter
171
189
  };
@@ -1 +1 @@
1
- {"version":3,"file":"taglib-class.d.ts","sourceRoot":"","sources":["../../../src/taglib/taglib-class.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgC,UAAU,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AA4C3D;;GAEG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAE1B,MAAM,EAAE,UAAU;IAI9B;;;;;OAKG;WACU,UAAU,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAMrE;;;;;;;OAOG;IACG,IAAI,CACR,KAAK,EAAE,cAAc,EACrB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,SAAS,CAAC;IAmGrB;;;;;;;;;OASG;IACG,IAAI,CACR,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC5C,OAAO,CAAC,IAAI,CAAC;IACV,IAAI,CACR,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI,GAAG,eAAe,EACxD,EAAE,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC5C,OAAO,CAAC,UAAU,CAAC;IAmBtB;;;;;;OAMG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtE;;;;;;;OAOG;IACG,YAAY,CAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,GACtB,OAAO,CAAC,IAAI,CAAC;IAUhB,oEAAoE;IACpE,OAAO,IAAI,MAAM;IAIjB,OAAO,CAAC,aAAa;CAStB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAEtE"}
1
+ {"version":3,"file":"taglib-class.d.ts","sourceRoot":"","sources":["../../../src/taglib/taglib-class.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgC,UAAU,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AA4C3D;;GAEG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAE1B,MAAM,EAAE,UAAU;IAI9B;;;;;OAKG;WACU,UAAU,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAMrE;;;;;;;OAOG;IACG,IAAI,CACR,KAAK,EAAE,cAAc,EACrB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,SAAS,CAAC;IA0FrB;;;;;;;;;OASG;IACG,IAAI,CACR,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC5C,OAAO,CAAC,IAAI,CAAC;IACV,IAAI,CACR,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI,GAAG,eAAe,EACxD,EAAE,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC5C,OAAO,CAAC,UAAU,CAAC;IAmBtB;;;;;;OAMG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtE;;;;;;;OAOG;IACG,YAAY,CAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,GACtB,OAAO,CAAC,IAAI,CAAC;IAUhB,oEAAoE;IACpE,OAAO,IAAI,MAAM;IAIjB,OAAO,CAAC,aAAa;CAStB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAEtE"}
@@ -69,30 +69,19 @@ class TagLib {
69
69
  const actualInput = isNamedAudioInput(input) ? input.data : input;
70
70
  const sourcePath = typeof actualInput === "string" ? actualInput : void 0;
71
71
  if (typeof actualInput === "string" && this.module.isWasi) {
72
- const fileHandle2 = this.module.createFileHandle();
73
- try {
74
- const fh = fileHandle2;
75
- if (fh.loadFromPath) {
76
- const wasiPath = toWasiPath(actualInput);
77
- const success = fh.loadFromPath(wasiPath);
78
- if (!success) {
79
- throw new InvalidFormatError(
80
- `Failed to load audio file. Path: ${actualInput}`
81
- );
82
- }
83
- return new AudioFileImpl(
84
- this.module,
85
- fileHandle2,
86
- sourcePath,
87
- actualInput,
88
- false
89
- );
90
- }
91
- } catch (error) {
92
- if (typeof fileHandle2.destroy === "function") {
93
- fileHandle2.destroy();
94
- }
95
- throw error;
72
+ const wasiPath = toWasiPath(actualInput);
73
+ if (this.module.loadAudioPath) {
74
+ const fileHandle2 = await this.module.loadAudioPath(
75
+ wasiPath,
76
+ actualInput
77
+ );
78
+ return new AudioFileImpl(
79
+ this.module,
80
+ fileHandle2,
81
+ sourcePath,
82
+ actualInput,
83
+ false
84
+ );
96
85
  }
97
86
  }
98
87
  const opts = {
@@ -24,7 +24,7 @@ export declare function isNamedAudioInput(input: AudioFileInput): input is Named
24
24
  * }
25
25
  * ```
26
26
  */
27
- export type FileType = "MP3" | "MP4" | "FLAC" | "OGG" | "OPUS" | "WAV" | "AIFF" | "ASF" | "APE" | "DSF" | "DSDIFF" | "WV" | "MPC" | "TTA" | "SHN" | "MOD" | "S3M" | "IT" | "XM" | "OggFLAC" | "SPEEX" | "MATROSKA" | "unknown";
27
+ export type FileType = "MP3" | "AAC" | "MP4" | "FLAC" | "OGG" | "OPUS" | "WAV" | "AIFF" | "ASF" | "APE" | "DSF" | "DSDIFF" | "WV" | "MPC" | "TTA" | "SHN" | "MOD" | "S3M" | "IT" | "XM" | "OggFLAC" | "SPEEX" | "MATROSKA" | "unknown";
28
28
  /**
29
29
  * Container formats for audio files.
30
30
  * A container format defines how audio data and metadata are stored in a file.
@@ -37,7 +37,7 @@ export type FileType = "MP3" | "MP4" | "FLAC" | "OGG" | "OPUS" | "WAV" | "AIFF"
37
37
  * console.log(`Codec: ${props.codec}`); // "AAC"
38
38
  * ```
39
39
  */
40
- export type ContainerFormat = "MP3" | "MP4" | "FLAC" | "OGG" | "WAV" | "AIFF" | "ASF" | "APE" | "DSF" | "DSDIFF" | "WavPack" | "MPC" | "TTA" | "Shorten" | "MOD" | "S3M" | "IT" | "XM" | "Matroska" | "unknown";
40
+ export type ContainerFormat = "MP3" | "ADTS" | "MP4" | "FLAC" | "OGG" | "WAV" | "AIFF" | "ASF" | "APE" | "DSF" | "DSDIFF" | "WavPack" | "MPC" | "TTA" | "Shorten" | "MOD" | "S3M" | "IT" | "XM" | "Matroska" | "unknown";
41
41
  /**
42
42
  * Audio codecs (compression formats) for audio data.
43
43
  * A codec defines how audio is encoded/compressed within a container.
@@ -54,7 +54,7 @@ export type ContainerFormat = "MP3" | "MP4" | "FLAC" | "OGG" | "WAV" | "AIFF" |
54
54
  * console.log(props2.codec); // "ALAC" (lossless)
55
55
  * ```
56
56
  */
57
- export type AudioCodec = "AAC" | "ALAC" | "MP3" | "FLAC" | "Vorbis" | "Opus" | "Speex" | "PCM" | "IEEEFloat" | "WAV" | "WMA" | "WMALossless" | "APE" | "DSD" | "WavPack" | "MPC" | "TTA" | "Shorten" | "MOD" | "S3M" | "IT" | "XM" | "unknown";
57
+ export type AudioCodec = "AAC" | "ALAC" | "AC-3" | "E-AC-3" | "DTS" | "MP3" | "FLAC" | "Vorbis" | "Opus" | "Speex" | "PCM" | "IEEEFloat" | "WAV" | "WMA" | "WMALossless" | "APE" | "DSD" | "WavPack" | "MPC" | "TTA" | "Shorten" | "MOD" | "S3M" | "IT" | "XM" | "unknown";
58
58
  /**
59
59
  * Bitrate mode for MP3 audio.
60
60
  *
@@ -118,7 +118,7 @@ export interface AudioProperties {
118
118
  *
119
119
  * After narrowing via `isFormat()`, optional fields that are guaranteed present
120
120
  * for a given format become required:
121
- * - MP3: `mpegVersion`, `mpegLayer`
121
+ * - MP3 / ADTS (`"AAC"`, raw .aac): `mpegVersion`, `mpegLayer`
122
122
  * - MP4/ASF: `isEncrypted`
123
123
  * - OPUS: `outputGainDb`
124
124
  * - APE/WV/TTA/MPC/SHN: `formatVersion`
@@ -131,7 +131,7 @@ export interface AudioProperties {
131
131
  * }
132
132
  * ```
133
133
  */
134
- export type TypedAudioProperties<F extends FileType> = F extends "MP3" ? AudioProperties & {
134
+ export type TypedAudioProperties<F extends FileType> = F extends "MP3" | "AAC" ? AudioProperties & {
135
135
  readonly mpegVersion: number;
136
136
  readonly mpegLayer: number;
137
137
  } : F extends "MP4" | "ASF" ? AudioProperties & {
@@ -1 +1 @@
1
- {"version":3,"file":"audio-formats.d.ts","sourceRoot":"","sources":["../../../src/types/audio-formats.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"audio-formats.d.ts","sourceRoot":"","sources":["../../../src/types/audio-formats.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,UAAU,GACV,WAAW,GACX,IAAI,GACJ,eAAe,CAAC;AAEpB,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,GACpB,KAAK,IAAI,eAAe,CAU1B;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,QAAQ,GAChB,KAAK,GACL,KAAK,GACL,KAAK,GACL,MAAM,GACN,KAAK,GACL,MAAM,GACN,KAAK,GACL,MAAM,GACN,KAAK,GACL,KAAK,GACL,KAAK,GACL,QAAQ,GACR,IAAI,GACJ,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,SAAS,GACT,OAAO,GACP,UAAU,GACV,SAAS,CAAC;AAEd;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,eAAe,GACvB,KAAK,GACL,MAAM,GACN,KAAK,GACL,MAAM,GACN,KAAK,GACL,KAAK,GACL,MAAM,GACN,KAAK,GACL,KAAK,GACL,KAAK,GACL,QAAQ,GACR,SAAS,GACT,KAAK,GACL,KAAK,GACL,SAAS,GACT,KAAK,GACL,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,UAAU,GACV,SAAS,CAAC;AAEd;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,UAAU,GAClB,KAAK,GACL,MAAM,GACN,MAAM,GACN,QAAQ,GACR,KAAK,GACL,KAAK,GACL,MAAM,GACN,QAAQ,GACR,MAAM,GACN,OAAO,GACP,KAAK,GACL,WAAW,GACX,KAAK,GACL,KAAK,GACL,aAAa,GACb,KAAK,GACL,KAAK,GACL,SAAS,GACT,KAAK,GACL,KAAK,GACL,SAAS,GACT,KAAK,GACL,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,SAAS,CAAC;AAEd;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEhD;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,eAAe;IAC9B,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,sBAAsB;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,wBAAwB;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,+BAA+B;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,sCAAsC;IACtC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,oDAAoD;IACpD,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,+FAA+F;IAC/F,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,QAAQ,IAAI,CAAC,SAAS,KAAK,GAAG,KAAK,GAC1E,eAAe,GAAG;IAClB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,GACC,CAAC,SAAS,KAAK,GAAG,KAAK,GACrB,eAAe,GAAG;IAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;CAAE,GACrD,CAAC,SAAS,MAAM,GAAG,eAAe,GAAG;IAAE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACtE,CAAC,SAAS,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAC5C,eAAe,GAAG;IAAE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GACtD,eAAe,CAAC"}
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import type { FileType } from "./audio-formats.js";
8
8
  export type TagFormat = "ID3v2" | "MP4" | "Vorbis" | "WAV";
9
- export type FileTypeToTagFormat<F extends FileType> = F extends "MP3" | "AIFF" ? "ID3v2" : F extends "MP4" ? "MP4" : F extends "FLAC" | "OGG" | "OPUS" | "OggFLAC" | "SPEEX" | "MATROSKA" ? "Vorbis" : F extends "WAV" ? "WAV" : TagFormat;
9
+ export type FileTypeToTagFormat<F extends FileType> = F extends "MP3" | "AAC" | "AIFF" ? "ID3v2" : F extends "MP4" ? "MP4" : F extends "FLAC" | "OGG" | "OPUS" | "OggFLAC" | "SPEEX" | "MATROSKA" ? "Vorbis" : F extends "WAV" ? "WAV" : TagFormat;
10
10
  type AllPropertyDefs = typeof import("../constants/basic-properties.js").BASIC_PROPERTIES & typeof import("../constants/general-extended-properties.js").GENERAL_EXTENDED_PROPERTIES & typeof import("../constants/specialized-properties.js").SPECIALIZED_PROPERTIES;
11
11
  type PropertyKeysForTagFormat<TF extends TagFormat> = {
12
12
  [K in keyof AllPropertyDefs]: TF extends AllPropertyDefs[K]["supportedFormats"][number] ? K : never;
@@ -1 +1 @@
1
- {"version":3,"file":"format-property-keys.d.ts","sourceRoot":"","sources":["../../../src/types/format-property-keys.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAC;AAM3D,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,QAAQ,IAAI,CAAC,SAAS,KAAK,GAAG,MAAM,GAC1E,OAAO,GACP,CAAC,SAAS,KAAK,GAAG,KAAK,GACvB,CAAC,SAAS,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,GAClE,QAAQ,GACV,CAAC,SAAS,KAAK,GAAG,KAAK,GACvB,SAAS,CAAC;AAId,KAAK,eAAe,GAChB,cAAc,kCAAkC,EAAE,gBAAgB,GAClE,cAAc,6CAA6C,EAAE,2BAA2B,GACxF,cAAc,wCAAwC,EAAE,sBAAsB,CAAC;AAEnF,KAAK,wBAAwB,CAAC,EAAE,SAAS,SAAS,IAAI;KACnD,CAAC,IAAI,MAAM,eAAe,GAAG,EAAE,SAC9B,eAAe,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK;CAC7D,CAAC,MAAM,eAAe,CAAC,CAAC;AAEzB,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,QAAQ,IAAI,wBAAwB,CAC1E,mBAAmB,CAAC,CAAC,CAAC,CACvB,CAAC"}
1
+ {"version":3,"file":"format-property-keys.d.ts","sourceRoot":"","sources":["../../../src/types/format-property-keys.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAC;AAM3D,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,QAAQ,IAAI,CAAC,SACrD,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAC9B,CAAC,SAAS,KAAK,GAAG,KAAK,GACvB,CAAC,SAAS,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,GAClE,QAAQ,GACV,CAAC,SAAS,KAAK,GAAG,KAAK,GACvB,SAAS,CAAC;AAId,KAAK,eAAe,GAChB,cAAc,kCAAkC,EAAE,gBAAgB,GAClE,cAAc,6CAA6C,EAAE,2BAA2B,GACxF,cAAc,wCAAwC,EAAE,sBAAsB,CAAC;AAEnF,KAAK,wBAAwB,CAAC,EAAE,SAAS,SAAS,IAAI;KACnD,CAAC,IAAI,MAAM,eAAe,GAAG,EAAE,SAC9B,eAAe,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK;CAC7D,CAAC,MAAM,eAAe,CAAC,CAAC;AAEzB,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,QAAQ,IAAI,wBAAwB,CAC1E,mBAAmB,CAAC,CAAC,CAAC,CACvB,CAAC"}
@@ -131,6 +131,11 @@ export interface TagInput {
131
131
  readonly discNumber?: number;
132
132
  readonly totalTracks?: number;
133
133
  readonly totalDiscs?: number;
134
+ /** Integer BPM. The typed surface is integer by convention — the read
135
+ * side narrows any wire value to its leading integer, so a fractional
136
+ * value is truncated toward zero on write to keep all formats in
137
+ * agreement (ID3v2 would store "120.5" verbatim while MP4's tmpo atom
138
+ * int-converts; taglib-ory8). */
134
139
  readonly bpm?: number;
135
140
  readonly compilation?: boolean;
136
141
  }
@@ -198,7 +203,9 @@ export interface ExtendedTag extends Tag {
198
203
  readonly totalTracks?: number;
199
204
  /** Total discs in release */
200
205
  readonly totalDiscs?: number;
201
- /** BPM (beats per minute) */
206
+ /** BPM (beats per minute), always an integer — the typed surface narrows
207
+ * to the leading integer on read and truncates fractional writes
208
+ * (taglib-ory8). */
202
209
  readonly bpm?: number;
203
210
  /** Compilation flag */
204
211
  readonly compilation?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../../src/types/tags.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../../src/types/tags.ts"],"names":[],"mappings":"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"}
@@ -11,4 +11,16 @@ export declare function fileUrlToPath(url: URL): string;
11
11
  export declare function basename(path: string): string;
12
12
  /** Join path segments with the OS-appropriate separator. */
13
13
  export declare function joinPath(...segments: string[]): string;
14
+ /**
15
+ * The host path behind a WASI path, given the preopen map the guest was started
16
+ * with (`WasiHostLoaderConfig.preopens`): the inverse of the virtual-path
17
+ * mapping the host resolves `path_open` through, and the only way host-side code
18
+ * can read the same file the guest reads. On Windows the map is the drive list
19
+ * (`{"/C": "C:\\"}`), so `/C/music/a.mp3` is `C:\music\a.mp3`; on POSIX it is
20
+ * the identity (`{"/": "/"}`).
21
+ *
22
+ * Returns undefined for a path no preopen covers — the guest cannot open that
23
+ * path either, so there is nothing on the host side to read.
24
+ */
25
+ export declare function hostPathForPreopens(wasiPath: string, preopens: Record<string, string>): string | undefined;
14
26
  //# sourceMappingURL=path.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../src/utils/path.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAK9C;AAED,0EAA0E;AAC1E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7C;AAED,4DAA4D;AAC5D,wBAAgB,QAAQ,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAKtD"}
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../src/utils/path.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAK9C;AAED,0EAA0E;AAC1E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7C;AAED,4DAA4D;AAC5D,wBAAgB,QAAQ,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAKtD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,MAAM,GAAG,SAAS,CAqBpB"}