1
1
mirror of https://github.com/wader/fq.git synced 2024-12-23 13:22:58 +03:00

Merge pull request #522 from wader/mp3_frame-vbri

mp3_tags,mp3: Add VBRI header support and rename tags to tag as there is only one
This commit is contained in:
Mattias Wadman 2022-12-14 11:43:31 +01:00 committed by GitHub
commit b43cf5775d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 270 additions and 105 deletions

View File

@ -868,32 +868,31 @@
<text x="160" y="400">t</text> <text x="160" y="400">t</text>
<text x="168" y="400">a</text> <text x="168" y="400">a</text>
<text x="176" y="400">g</text> <text x="176" y="400">g</text>
<text x="184" y="400">s</text> <text x="184" y="400">.</text>
<text x="192" y="400">.</text> <text x="192" y="400">e</text>
<text x="200" y="400">e</text> <text x="200" y="400">n</text>
<text x="208" y="400">n</text> <text x="208" y="400">c</text>
<text x="216" y="400">c</text> <text x="216" y="400">o</text>
<text x="224" y="400">o</text> <text x="224" y="400">d</text>
<text x="232" y="400">d</text> <text x="232" y="400">e</text>
<text x="240" y="400">e</text> <text x="240" y="400">r</text>
<text x="248" y="400">r</text> <text x="256" y="400">|</text>
<text x="264" y="400">|</text> <text x="272" y="400">t</text>
<text x="280" y="400">t</text> <text x="280" y="400">o</text>
<text x="288" y="400">o</text> <text x="288" y="400">v</text>
<text x="296" y="400">v</text> <text x="296" y="400">a</text>
<text x="304" y="400">a</text> <text x="304" y="400">l</text>
<text x="312" y="400">l</text> <text x="312" y="400">u</text>
<text x="320" y="400">u</text> <text x="320" y="400">e</text>
<text x="328" y="400">e</text> <text x="328" y="400">&#39;</text>
<text x="336" y="400">&#39;</text> <text x="344" y="400">f</text>
<text x="352" y="400">f</text> <text x="352" y="400">i</text>
<text x="360" y="400">i</text> <text x="360" y="400">l</text>
<text x="368" y="400">l</text> <text x="368" y="400">e</text>
<text x="376" y="400">e</text> <text x="376" y="400">.</text>
<text x="384" y="400">.</text> <text x="384" y="400">m</text>
<text x="392" y="400">m</text> <text x="392" y="400">p</text>
<text x="400" y="400">p</text> <text x="400" y="400">3</text>
<text x="408" y="400">3</text>
<text x="0" y="416">L</text> <text x="0" y="416">L</text>
<text x="8" y="416">a</text> <text x="8" y="416">a</text>
<text x="16" y="416">v</text> <text x="16" y="416">v</text>

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

@ -18,7 +18,7 @@ c "Show ID3v2 tag inside mp3 file"
s "fq '.headers[0]' file.mp3" s "fq '.headers[0]' file.mp3"
echo echo
c "Show encoder software used" c "Show encoder software used"
s "fq -r '.frames[0].tags.encoder | tovalue' file.mp3" s "fq -r '.frames[0].tag.encoder | tovalue' file.mp3"
echo echo
c "Decode at two offsets as mp3_frame and show bitrate" c "Decode at two offsets as mp3_frame and show bitrate"
s "fq -d bytes '.[0xb79,0xc49:] | mp3_frame.header.bitrate' file.mp3" s "fq -d bytes '.[0xb79,0xc49:] | mp3_frame.header.bitrate' file.mp3"

View File

@ -8,6 +8,7 @@ import (
"github.com/wader/fq/format" "github.com/wader/fq/format"
"github.com/wader/fq/pkg/decode" "github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/interp" "github.com/wader/fq/pkg/interp"
"github.com/wader/fq/pkg/scalar"
) )
func init() { func init() {
@ -18,61 +19,81 @@ func init() {
}) })
} }
var headerDescription = scalar.StrToDescription{
"Xing": "XING variable bitrate",
"Info": "XING variable bitrate",
"VBRI": "Fraunhofer Encoder variable bitrate info",
}
func mp3FrameTagsDecode(d *decode.D, _ any) any { func mp3FrameTagsDecode(d *decode.D, _ any) any {
switch d.FieldUTF8("header", 4) { switch d.FieldUTF8("header", 4, headerDescription) {
case "Xing": case "Xing",
case "Info": "Info":
default: qualityPresent := false
d.Errorf("no xing or info header found") tocPresent := false
} bytesPresent := false
framesPresent := false
d.FieldStruct("present_flags", func(d *decode.D) {
d.FieldU("unused", 28)
qualityPresent = d.FieldBool("quality")
tocPresent = d.FieldBool("toc")
bytesPresent = d.FieldBool("bytes")
framesPresent = d.FieldBool("frames")
})
qualityPresent := false if framesPresent {
tocPresent := false d.FieldU32BE("frames")
bytesPresent := false }
framesPresent := false if bytesPresent {
d.FieldStruct("present_flags", func(d *decode.D) { d.FieldU32BE("bytes")
d.FieldU("unused", 28) }
qualityPresent = d.FieldBool("quality") if tocPresent {
tocPresent = d.FieldBool("toc") d.FieldArray("toc", func(d *decode.D) {
bytesPresent = d.FieldBool("bytes") for i := 0; i < 100; i++ {
framesPresent = d.FieldBool("frames") d.FieldU8("entry")
}) }
})
}
if qualityPresent {
d.FieldU32BE("quality")
}
if framesPresent { d.FieldUTF8("encoder", 9)
d.FieldU32BE("frames") d.FieldU4("tag_revision")
} d.FieldU4("vbr_method")
if bytesPresent { d.FieldU8("lowpass_filter") // TODO: /100
d.FieldU32BE("bytes") d.FieldU32("replay_gain_peak")
} d.FieldU16("radio_replay_gain")
if tocPresent { d.FieldU16("audiophile_replay_gain")
d.FieldU4("lame_flags")
d.FieldU4("lame_ath_type")
d.FieldU8("abr_vbr") // TODO:
d.FieldU12("encoder_delay") // TODO:
d.FieldU12("encoder_padding") // TODO:
d.FieldU8("misc") // TODO:
d.FieldU8("mp3_gain") // TODO:
d.FieldU16("preset") // TODO:
d.FieldU32("length")
d.FieldU16("music_crc") // TODO:
d.FieldU16("tag_crc") // TODO:
case "VBRI":
d.FieldU16("version_id")
d.FieldU16("delay")
d.FieldU16("quality")
d.FieldU32("length", scalar.Description("Number of bytes"))
d.FieldU32("frames", scalar.Description("Number of frames"))
tocEntries := d.FieldU16("toc_entries", scalar.Description("Number of entries within TOC table"))
d.FieldU16("scale_factor", scalar.Description("Scale factor of TOC table entries"))
tocEntrySize := d.FieldU16("toc_entry_size", d.AssertU(1, 2, 3, 4), scalar.Description("Size per table entry"))
d.FieldU16("frame_per_entry", scalar.Description("Frames per table entry"))
d.FieldArray("toc", func(d *decode.D) { d.FieldArray("toc", func(d *decode.D) {
for i := 0; i < 100; i++ { for i := 0; i < int(tocEntries); i++ {
d.FieldU8("entry") d.FieldU("entry", int(tocEntrySize)*8)
} }
}) })
default:
d.Errorf("no vbri, info or xing header found")
} }
if qualityPresent {
d.FieldU32BE("quality")
}
d.FieldUTF8("encoder", 9)
d.FieldU4("tag_revision")
d.FieldU4("vbr_method")
d.FieldU8("lowpass_filter") // TODO: /100
d.FieldU32("replay_gain_peak")
d.FieldU16("radio_replay_gain")
d.FieldU16("audiophile_replay_gain")
d.FieldU4("lame_flags")
d.FieldU4("lame_ath_type")
d.FieldU8("abr_vbr") // TODO:
d.FieldU12("encoder_delay") // TODO:
d.FieldU12("encoder_padding") // TODO:
d.FieldU8("misc") // TODO:
d.FieldU8("mp3_gain") // TODO:
d.FieldU16("preset") // TODO:
d.FieldU32("length")
d.FieldU16("music_crc") // TODO:
d.FieldU16("tag_crc") // TODO:
return nil return nil
} }

View File

@ -1,7 +1,7 @@
# ffmpeg -y -f lavfi -i sine -ac 2 -t 10ms -f mp3 temp.mp3 && fq temp.mp3 '.frames[0].tags | tobits' > mp3_frame_tags_info # ffmpeg -y -f lavfi -i sine -ac 2 -t 10ms -f mp3 temp.mp3 && fq temp.mp3 '.frames[0].tag | tobits' > mp3_frame_tags_info
$ fq -d mp3_frame_tags dv mp3_frame_tags_info $ fq -d mp3_frame_tags dv mp3_frame_tags_info
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: mp3_frame_tags_info (mp3_frame_tags) 0x0-0x9b.7 (156) |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: mp3_frame_tags_info (mp3_frame_tags) 0x0-0x9b.7 (156)
0x00|49 6e 66 6f |Info | header: "Info" 0x0-0x3.7 (4) 0x00|49 6e 66 6f |Info | header: "Info" (XING variable bitrate) 0x0-0x3.7 (4)
| | | present_flags{}: 0x4-0x7.7 (4) | | | present_flags{}: 0x4-0x7.7 (4)
0x00| 00 00 00 0f | .... | unused: 0 0x4-0x7.3 (3.4) 0x00| 00 00 00 0f | .... | unused: 0 0x4-0x7.3 (3.4)
0x00| 0f | . | quality: true 0x7.4-0x7.4 (0.1) 0x00| 0f | . | quality: true 0x7.4-0x7.4 (0.1)

BIN
format/mp3/testdata/mp3_frame_tags_vbri vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,145 @@
$ fq -d mp3_frame_tags dv mp3_frame_tags_vbri
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: mp3_frame_tags_vbri (mp3_frame_tags) 0x0-0x11f.7 (288)
0x000|56 42 52 49 |VBRI | header: "VBRI" (Fraunhofer Encoder variable bitrate info) 0x0-0x3.7 (4)
0x000| 00 01 | .. | version_id: 1 0x4-0x5.7 (2)
0x000| 09 31 | .1 | delay: 2353 0x6-0x7.7 (2)
0x000| 00 64 | .d | quality: 100 0x8-0x9.7 (2)
0x000| 02 ba 34 78 | ..4x | length: 45757560 (Number of bytes) 0xa-0xd.7 (4)
0x000| 00 01| ..| frames: 67465 (Number of frames) 0xe-0x11.7 (4)
0x010|07 89 |.. |
0x010| 00 83 | .. | toc_entries: 131 (Number of entries within TOC table) 0x12-0x13.7 (2)
0x010| 00 10 | .. | scale_factor: 16 (Scale factor of TOC table entries) 0x14-0x15.7 (2)
0x010| 00 02 | .. | toc_entry_size: 2 (Size per table entry) 0x16-0x17.7 (2)
0x010| 02 00 | .. | frame_per_entry: 512 (Frames per table entry) 0x18-0x19.7 (2)
| | | toc[0:131]: 0x1a-0x11f.7 (262)
0x010| 2e 6e | .n | [0]: 11886 entry 0x1a-0x1b.7 (2)
0x010| 56 2e | V. | [1]: 22062 entry 0x1c-0x1d.7 (2)
0x010| 55 bc| U.| [2]: 21948 entry 0x1e-0x1f.7 (2)
0x020|56 52 |VR | [3]: 22098 entry 0x20-0x21.7 (2)
0x020| 2e b9 | .. | [4]: 11961 entry 0x22-0x23.7 (2)
0x020| 53 c4 | S. | [5]: 21444 entry 0x24-0x25.7 (2)
0x020| 52 d4 | R. | [6]: 21204 entry 0x26-0x27.7 (2)
0x020| 56 f4 | V. | [7]: 22260 entry 0x28-0x29.7 (2)
0x020| 53 f4 | S. | [8]: 21492 entry 0x2a-0x2b.7 (2)
0x020| 53 52 | SR | [9]: 21330 entry 0x2c-0x2d.7 (2)
0x020| 59 28| Y(| [10]: 22824 entry 0x2e-0x2f.7 (2)
0x030|52 bc |R. | [11]: 21180 entry 0x30-0x31.7 (2)
0x030| 56 10 | V. | [12]: 22032 entry 0x32-0x33.7 (2)
0x030| 50 05 | P. | [13]: 20485 entry 0x34-0x35.7 (2)
0x030| 55 c2 | U. | [14]: 21954 entry 0x36-0x37.7 (2)
0x030| 56 ac | V. | [15]: 22188 entry 0x38-0x39.7 (2)
0x030| 55 d7 | U. | [16]: 21975 entry 0x3a-0x3b.7 (2)
0x030| 55 2c | U, | [17]: 21804 entry 0x3c-0x3d.7 (2)
0x030| 54 fc| T.| [18]: 21756 entry 0x3e-0x3f.7 (2)
0x040|55 aa |U. | [19]: 21930 entry 0x40-0x41.7 (2)
0x040| 4a 52 | JR | [20]: 19026 entry 0x42-0x43.7 (2)
0x040| 52 44 | RD | [21]: 21060 entry 0x44-0x45.7 (2)
0x040| 54 ba | T. | [22]: 21690 entry 0x46-0x47.7 (2)
0x040| 52 0b | R. | [23]: 21003 entry 0x48-0x49.7 (2)
0x040| 53 9a | S. | [24]: 21402 entry 0x4a-0x4b.7 (2)
0x040| 55 c2 | U. | [25]: 21954 entry 0x4c-0x4d.7 (2)
0x040| 55 80| U.| [26]: 21888 entry 0x4e-0x4f.7 (2)
0x050|4e 48 |NH | [27]: 20040 entry 0x50-0x51.7 (2)
0x050| 55 bf | U. | [28]: 21951 entry 0x52-0x53.7 (2)
0x050| 59 d0 | Y. | [29]: 22992 entry 0x54-0x55.7 (2)
0x050| 56 16 | V. | [30]: 22038 entry 0x56-0x57.7 (2)
0x050| 54 de | T. | [31]: 21726 entry 0x58-0x59.7 (2)
0x050| 52 32 | R2 | [32]: 21042 entry 0x5a-0x5b.7 (2)
0x050| 56 76 | Vv | [33]: 22134 entry 0x5c-0x5d.7 (2)
0x050| 57 c6| W.| [34]: 22470 entry 0x5e-0x5f.7 (2)
0x060|53 31 |S1 | [35]: 21297 entry 0x60-0x61.7 (2)
0x060| 56 94 | V. | [36]: 22164 entry 0x62-0x63.7 (2)
0x060| 55 ce | U. | [37]: 21966 entry 0x64-0x65.7 (2)
0x060| 54 8d | T. | [38]: 21645 entry 0x66-0x67.7 (2)
0x060| 55 2c | U, | [39]: 21804 entry 0x68-0x69.7 (2)
0x060| 57 24 | W$ | [40]: 22308 entry 0x6a-0x6b.7 (2)
0x060| 56 10 | V. | [41]: 22032 entry 0x6c-0x6d.7 (2)
0x060| 55 ec| U.| [42]: 21996 entry 0x6e-0x6f.7 (2)
0x070|52 f5 |R. | [43]: 21237 entry 0x70-0x71.7 (2)
0x070| 52 ec | R. | [44]: 21228 entry 0x72-0x73.7 (2)
0x070| 56 16 | V. | [45]: 22038 entry 0x74-0x75.7 (2)
0x070| 57 78 | Wx | [46]: 22392 entry 0x76-0x77.7 (2)
0x070| 4d ee | M. | [47]: 19950 entry 0x78-0x79.7 (2)
0x070| 52 74 | Rt | [48]: 21108 entry 0x7a-0x7b.7 (2)
0x070| 53 ee | S. | [49]: 21486 entry 0x7c-0x7d.7 (2)
0x070| 54 cc| T.| [50]: 21708 entry 0x7e-0x7f.7 (2)
0x080|53 ee |S. | [51]: 21486 entry 0x80-0x81.7 (2)
0x080| 54 9c | T. | [52]: 21660 entry 0x82-0x83.7 (2)
0x080| 54 18 | T. | [53]: 21528 entry 0x84-0x85.7 (2)
0x080| 56 f4 | V. | [54]: 22260 entry 0x86-0x87.7 (2)
0x080| 56 dc | V. | [55]: 22236 entry 0x88-0x89.7 (2)
0x080| 54 3c | T< | [56]: 21564 entry 0x8a-0x8b.7 (2)
0x080| 59 94 | Y. | [57]: 22932 entry 0x8c-0x8d.7 (2)
0x080| 5b 6e| [n| [58]: 23406 entry 0x8e-0x8f.7 (2)
0x090|5a fc |Z. | [59]: 23292 entry 0x90-0x91.7 (2)
0x090| 5c ac | \. | [60]: 23724 entry 0x92-0x93.7 (2)
0x090| 5b fe | [. | [61]: 23550 entry 0x94-0x95.7 (2)
0x090| 5d 90 | ]. | [62]: 23952 entry 0x96-0x97.7 (2)
0x090| 5c 82 | \. | [63]: 23682 entry 0x98-0x99.7 (2)
0x090| 5d 9c | ]. | [64]: 23964 entry 0x9a-0x9b.7 (2)
0x090| 5d 3c | ]< | [65]: 23868 entry 0x9c-0x9d.7 (2)
0x090| 5e 4a| ^J| [66]: 24138 entry 0x9e-0x9f.7 (2)
0x0a0|5c 6a |\j | [67]: 23658 entry 0xa0-0xa1.7 (2)
0x0a0| 5b da | [. | [68]: 23514 entry 0xa2-0xa3.7 (2)
0x0a0| 5a fc | Z. | [69]: 23292 entry 0xa4-0xa5.7 (2)
0x0a0| 5d 36 | ]6 | [70]: 23862 entry 0xa6-0xa7.7 (2)
0x0a0| 5c 04 | \. | [71]: 23556 entry 0xa8-0xa9.7 (2)
0x0a0| 5c be | \. | [72]: 23742 entry 0xaa-0xab.7 (2)
0x0a0| 5b 5c | [\ | [73]: 23388 entry 0xac-0xad.7 (2)
0x0a0| 5b 0e| [.| [74]: 23310 entry 0xae-0xaf.7 (2)
0x0b0|59 9a |Y. | [75]: 22938 entry 0xb0-0xb1.7 (2)
0x0b0| 5a c6 | Z. | [76]: 23238 entry 0xb2-0xb3.7 (2)
0x0b0| 5b 20 | [ | [77]: 23328 entry 0xb4-0xb5.7 (2)
0x0b0| 56 c4 | V. | [78]: 22212 entry 0xb6-0xb7.7 (2)
0x0b0| 59 a6 | Y. | [79]: 22950 entry 0xb8-0xb9.7 (2)
0x0b0| 58 7a | Xz | [80]: 22650 entry 0xba-0xbb.7 (2)
0x0b0| 59 e2 | Y. | [81]: 23010 entry 0xbc-0xbd.7 (2)
0x0b0| 5b bc| [.| [82]: 23484 entry 0xbe-0xbf.7 (2)
0x0c0|5a c0 |Z. | [83]: 23232 entry 0xc0-0xc1.7 (2)
0x0c0| 58 bc | X. | [84]: 22716 entry 0xc2-0xc3.7 (2)
0x0c0| 58 56 | XV | [85]: 22614 entry 0xc4-0xc5.7 (2)
0x0c0| 58 da | X. | [86]: 22746 entry 0xc6-0xc7.7 (2)
0x0c0| 56 76 | Vv | [87]: 22134 entry 0xc8-0xc9.7 (2)
0x0c0| 54 fc | T. | [88]: 21756 entry 0xca-0xcb.7 (2)
0x0c0| 56 4c | VL | [89]: 22092 entry 0xcc-0xcd.7 (2)
0x0c0| 56 5e| V^| [90]: 22110 entry 0xce-0xcf.7 (2)
0x0d0|54 f0 |T. | [91]: 21744 entry 0xd0-0xd1.7 (2)
0x0d0| 54 ba | T. | [92]: 21690 entry 0xd2-0xd3.7 (2)
0x0d0| 56 fa | V. | [93]: 22266 entry 0xd4-0xd5.7 (2)
0x0d0| 55 20 | U | [94]: 21792 entry 0xd6-0xd7.7 (2)
0x0d0| 52 6e | Rn | [95]: 21102 entry 0xd8-0xd9.7 (2)
0x0d0| 55 9e | U. | [96]: 21918 entry 0xda-0xdb.7 (2)
0x0d0| 53 d6 | S. | [97]: 21462 entry 0xdc-0xdd.7 (2)
0x0d0| 57 de| W.| [98]: 22494 entry 0xde-0xdf.7 (2)
0x0e0|52 6e |Rn | [99]: 21102 entry 0xe0-0xe1.7 (2)
0x0e0| 54 06 | T. | [100]: 21510 entry 0xe2-0xe3.7 (2)
0x0e0| 53 ca | S. | [101]: 21450 entry 0xe4-0xe5.7 (2)
0x0e0| 53 52 | SR | [102]: 21330 entry 0xe6-0xe7.7 (2)
0x0e0| 56 58 | VX | [103]: 22104 entry 0xe8-0xe9.7 (2)
0x0e0| 58 e6 | X. | [104]: 22758 entry 0xea-0xeb.7 (2)
0x0e0| 56 7c | V| | [105]: 22140 entry 0xec-0xed.7 (2)
0x0e0| 57 9c| W.| [106]: 22428 entry 0xee-0xef.7 (2)
0x0f0|57 d8 |W. | [107]: 22488 entry 0xf0-0xf1.7 (2)
0x0f0| 57 6c | Wl | [108]: 22380 entry 0xf2-0xf3.7 (2)
0x0f0| 55 b3 | U. | [109]: 21939 entry 0xf4-0xf5.7 (2)
0x0f0| 56 1c | V. | [110]: 22044 entry 0xf6-0xf7.7 (2)
0x0f0| 4e 30 | N0 | [111]: 20016 entry 0xf8-0xf9.7 (2)
0x0f0| 46 5c | F\ | [112]: 18012 entry 0xfa-0xfb.7 (2)
0x0f0| 47 58 | GX | [113]: 18264 entry 0xfc-0xfd.7 (2)
0x0f0| 4d 22| M"| [114]: 19746 entry 0xfe-0xff.7 (2)
0x100|51 1e |Q. | [115]: 20766 entry 0x100-0x101.7 (2)
0x100| 54 54 | TT | [116]: 21588 entry 0x102-0x103.7 (2)
0x100| 52 50 | RP | [117]: 21072 entry 0x104-0x105.7 (2)
0x100| 50 82 | P. | [118]: 20610 entry 0x106-0x107.7 (2)
0x100| 50 d6 | P. | [119]: 20694 entry 0x108-0x109.7 (2)
0x100| 51 fc | Q. | [120]: 20988 entry 0x10a-0x10b.7 (2)
0x100| 54 84 | T. | [121]: 21636 entry 0x10c-0x10d.7 (2)
0x100| 50 52| PR| [122]: 20562 entry 0x10e-0x10f.7 (2)
0x110|57 ea |W. | [123]: 22506 entry 0x110-0x111.7 (2)
0x110| 56 88 | V. | [124]: 22152 entry 0x112-0x113.7 (2)
0x110| 56 22 | V" | [125]: 22050 entry 0x114-0x115.7 (2)
0x110| 3d 93 | =. | [126]: 15763 entry 0x116-0x117.7 (2)
0x110| 35 eb | 5. | [127]: 13803 entry 0x118-0x119.7 (2)
0x110| 59 70 | Yp | [128]: 22896 entry 0x11a-0x11b.7 (2)
0x110| 58 b6 | X. | [129]: 22710 entry 0x11c-0x11d.7 (2)
0x110| 57 fc| W.| [130]: 22524 entry 0x11e-0x11f.7 (2)

View File

@ -1,7 +1,7 @@
# ffmpeg -y -f lavfi -i sine -ac 2 -t 10ms -qscale:a 2 -f mp3 temp.mp3 && fq temp.mp3 '.frames[0].tags | tobits' > mp3_frame_tags_xing # ffmpeg -y -f lavfi -i sine -ac 2 -t 10ms -qscale:a 2 -f mp3 temp.mp3 && fq temp.mp3 '.frames[0].tag | tobits' > mp3_frame_tags_xing
$ fq -d mp3_frame_tags dv mp3_frame_tags_xing $ fq -d mp3_frame_tags dv mp3_frame_tags_xing
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: mp3_frame_tags_xing (mp3_frame_tags) 0x0-0x9b.7 (156) |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: mp3_frame_tags_xing (mp3_frame_tags) 0x0-0x9b.7 (156)
0x00|58 69 6e 67 |Xing | header: "Xing" 0x0-0x3.7 (4) 0x00|58 69 6e 67 |Xing | header: "Xing" (XING variable bitrate) 0x0-0x3.7 (4)
| | | present_flags{}: 0x4-0x7.7 (4) | | | present_flags{}: 0x4-0x7.7 (4)
0x00| 00 00 00 0f | .... | unused: 0 0x4-0x7.3 (3.4) 0x00| 00 00 00 0f | .... | unused: 0 0x4-0x7.3 (3.4)
0x00| 0f | . | quality: true 0x7.4-0x7.4 (0.1) 0x00| 0f | . | quality: true 0x7.4-0x7.4 (0.1)

View File

@ -369,7 +369,7 @@ func frameDecode(d *decode.D, _ any) any {
// audio data size, may include audio data from other frames also if main_data_begin is used // audio data size, may include audio data from other frames also if main_data_begin is used
restBytes := frameBytes - headerBytes - crcBytes - sideInfoBytes restBytes := frameBytes - headerBytes - crcBytes - sideInfoBytes
d.FramedFn(int64(restBytes)*8, func(d *decode.D) { d.FramedFn(int64(restBytes)*8, func(d *decode.D) {
_, _, _ = d.TryFieldFormat("tags", mp3FrameTagsHeader, nil) _, _, _ = d.TryFieldFormat("tag", mp3FrameTagsHeader, nil)
d.FieldRawLen("audio_data", d.BitsLeft()) d.FieldRawLen("audio_data", d.BitsLeft())
}) })

View File

@ -61,7 +61,7 @@ mp3> .frames[0] | dv({depth: 1, addrbase: 10})
048| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| ...............| side_info{}: 49-65.7 (17) 048| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| ...............| side_info{}: 49-65.7 (17)
064|00 00 |.. | 064|00 00 |.. |
|00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15|0123456789012345| |00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15|0123456789012345|
064| 49 6e 66 6f 00 00 00 0f 00 00 00 02 00 00| Info..........| tags{}: (mp3_frame_tags) 66-221.7 (156) 064| 49 6e 66 6f 00 00 00 0f 00 00 00 02 00 00| Info..........| tag{}: (mp3_frame_tags) 66-221.7 (156)
080|02 57 00 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6|.W..............| 080|02 57 00 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6|.W..............|
* |until 221.7 (156) | | * |until 221.7 (156) | |
208| 00 00| ..| audio_data: raw bits 222-226.7 (5) 208| 00 00| ..| audio_data: raw bits 222-226.7 (5)
@ -74,16 +74,16 @@ mp3> .frames[0] | dv({depth: 1, sizebase: 16})
0x30| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| ...............| side_info{}: 0x31-0x41.7 (0x11) 0x30| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| ...............| side_info{}: 0x31-0x41.7 (0x11)
0x40|00 00 |.. | 0x40|00 00 |.. |
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x40| 49 6e 66 6f 00 00 00 0f 00 00 00 02 00 00| Info..........| tags{}: (mp3_frame_tags) 0x42-0xdd.7 (0x9c) 0x40| 49 6e 66 6f 00 00 00 0f 00 00 00 02 00 00| Info..........| tag{}: (mp3_frame_tags) 0x42-0xdd.7 (0x9c)
0x50|02 57 00 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6|.W..............| 0x50|02 57 00 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6|.W..............|
* |until 0xdd.7 (0x9c) | | * |until 0xdd.7 (0x9c) | |
0xd0| 00 00| ..| audio_data: raw bits 0xde-0xe2.7 (0x5) 0xd0| 00 00| ..| audio_data: raw bits 0xde-0xe2.7 (0x5)
0xe0|00 00 00 |... | 0xe0|00 00 00 |... |
| | | crc_calculated: "827a" (raw bits) 0xe3-NA (0x0) | | | crc_calculated: "827a" (raw bits) 0xe3-NA (0x0)
mp3> .frames[0].tags | "d", d, "da", da, "dd", dd, "dv", dv, "ddv", ddv mp3> .frames[0].tag | "d", d, "da", da, "dd", dd, "dv", dv, "ddv", ddv
"d" "d"
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.frames[0].tags{}: (mp3_frame_tags) |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.frames[0].tag{}: (mp3_frame_tags)
0x40| 49 6e 66 6f | Info | header: "Info" 0x40| 49 6e 66 6f | Info | header: "Info" (XING variable bitrate)
| | | present_flags{}: | | | present_flags{}:
0x40| 00 00 00 0f | .... | unused: 0 0x40| 00 00 00 0f | .... | unused: 0
0x40| 0f | . | quality: true 0x40| 0f | . | quality: true
@ -167,8 +167,8 @@ mp3> .frames[0].tags | "d", d, "da", da, "dd", dd, "dv", dv, "ddv", ddv
0xd0| 62 f0 | b. | music_crc: 25328 0xd0| 62 f0 | b. | music_crc: 25328
0xd0| 5a 35 | Z5 | tag_crc: 23093 0xd0| 5a 35 | Z5 | tag_crc: 23093
"da" "da"
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.frames[0].tags{}: (mp3_frame_tags) |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.frames[0].tag{}: (mp3_frame_tags)
0x40| 49 6e 66 6f | Info | header: "Info" 0x40| 49 6e 66 6f | Info | header: "Info" (XING variable bitrate)
| | | present_flags{}: | | | present_flags{}:
0x40| 00 00 00 0f | .... | unused: 0 0x40| 00 00 00 0f | .... | unused: 0
0x40| 0f | . | quality: true 0x40| 0f | . | quality: true
@ -301,8 +301,8 @@ mp3> .frames[0].tags | "d", d, "da", da, "dd", dd, "dv", dv, "ddv", ddv
0xd0| 62 f0 | b. | music_crc: 25328 0xd0| 62 f0 | b. | music_crc: 25328
0xd0| 5a 35 | Z5 | tag_crc: 23093 0xd0| 5a 35 | Z5 | tag_crc: 23093
"dd" "dd"
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.frames[0].tags{}: (mp3_frame_tags) |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.frames[0].tag{}: (mp3_frame_tags)
0x40| 49 6e 66 6f | Info | header: "Info" 0x40| 49 6e 66 6f | Info | header: "Info" (XING variable bitrate)
| | | present_flags{}: | | | present_flags{}:
0x40| 00 00 00 0f | .... | unused: 0 0x40| 00 00 00 0f | .... | unused: 0
0x40| 0f | . | quality: true 0x40| 0f | . | quality: true
@ -435,8 +435,8 @@ mp3> .frames[0].tags | "d", d, "da", da, "dd", dd, "dv", dv, "ddv", ddv
0xd0| 62 f0 | b. | music_crc: 25328 0xd0| 62 f0 | b. | music_crc: 25328
0xd0| 5a 35 | Z5 | tag_crc: 23093 0xd0| 5a 35 | Z5 | tag_crc: 23093
"dv" "dv"
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.frames[0].tags{}: (mp3_frame_tags) 0x42-0xdd.7 (156) |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.frames[0].tag{}: (mp3_frame_tags) 0x42-0xdd.7 (156)
0x40| 49 6e 66 6f | Info | header: "Info" 0x42-0x45.7 (4) 0x40| 49 6e 66 6f | Info | header: "Info" (XING variable bitrate) 0x42-0x45.7 (4)
| | | present_flags{}: 0x46-0x49.7 (4) | | | present_flags{}: 0x46-0x49.7 (4)
0x40| 00 00 00 0f | .... | unused: 0 0x46-0x49.3 (3.4) 0x40| 00 00 00 0f | .... | unused: 0 0x46-0x49.3 (3.4)
0x40| 0f | . | quality: true 0x49.4-0x49.4 (0.1) 0x40| 0f | . | quality: true 0x49.4-0x49.4 (0.1)
@ -569,8 +569,8 @@ mp3> .frames[0].tags | "d", d, "da", da, "dd", dd, "dv", dv, "ddv", ddv
0xd0| 62 f0 | b. | music_crc: 25328 0xda-0xdb.7 (2) 0xd0| 62 f0 | b. | music_crc: 25328 0xda-0xdb.7 (2)
0xd0| 5a 35 | Z5 | tag_crc: 23093 0xdc-0xdd.7 (2) 0xd0| 5a 35 | Z5 | tag_crc: 23093 0xdc-0xdd.7 (2)
"ddv" "ddv"
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.frames[0].tags{}: (mp3_frame_tags) 0x42-0xdd.7 (156) |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.frames[0].tag{}: (mp3_frame_tags) 0x42-0xdd.7 (156)
0x40| 49 6e 66 6f | Info | header: "Info" 0x42-0x45.7 (4) 0x40| 49 6e 66 6f | Info | header: "Info" (XING variable bitrate) 0x42-0x45.7 (4)
| | | present_flags{}: 0x46-0x49.7 (4) | | | present_flags{}: 0x46-0x49.7 (4)
0x40| 00 00 00 0f | .... | unused: 0 0x46-0x49.3 (3.4) 0x40| 00 00 00 0f | .... | unused: 0 0x46-0x49.3 (3.4)
0x40| 0f | . | quality: true 0x49.4-0x49.4 (0.1) 0x40| 0f | . | quality: true 0x49.4-0x49.4 (0.1)

View File

@ -210,7 +210,7 @@ $ fq -d mp3 '.frames[0] | . + .header | keys, .bitrate' test.mp3
"sample_rate", "sample_rate",
"side_info", "side_info",
"sync", "sync",
"tags" "tag"
] ]
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x20| 40| @|.frames[0].header.bitrate: 56000 (4) 0x20| 40| @|.frames[0].header.bitrate: 56000 (4)
@ -234,7 +234,7 @@ $ fq -d mp3 '[.frames[0] | ., .header] | add | keys, .bitrate' test.mp3
"sample_rate", "sample_rate",
"side_info", "side_info",
"sync", "sync",
"tags" "tag"
] ]
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x20| 40| @|.frames[0].header.bitrate: 56000 (4) 0x20| 40| @|.frames[0].header.bitrate: 56000 (4)
@ -243,14 +243,14 @@ $ fq -d mp3 '.frames[0] | keys' test.mp3
[ [
"header", "header",
"side_info", "side_info",
"tags", "tag",
"audio_data", "audio_data",
"crc_calculated" "crc_calculated"
] ]
$ fq -d mp3 '.frames[0] | to_entries[].key' test.mp3 $ fq -d mp3 '.frames[0] | to_entries[].key' test.mp3
"header" "header"
"side_info" "side_info"
"tags" "tag"
"audio_data" "audio_data"
"crc_calculated" "crc_calculated"
# xml, csv does string normalization, make sure it works with nested JQValue:s # xml, csv does string normalization, make sure it works with nested JQValue:s

View File

@ -17,7 +17,7 @@ mp3> grep(44100, "ID", "^ID3$", "^ID.?$", "Info", "magic", "\u00ff", [0x49, 0x44
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0|49 44 33 |ID3 |.headers[0].magic: "ID3" (valid) 0x0|49 44 33 |ID3 |.headers[0].magic: "ID3" (valid)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x40| 49 6e 66 6f | Info |.frames[0].tags.header: "Info" 0x40| 49 6e 66 6f | Info |.frames[0].tag.header: "Info" (XING variable bitrate)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0|49 44 33 |ID3 |.headers[0].magic: "ID3" (valid) 0x0|49 44 33 |ID3 |.headers[0].magic: "ID3" (valid)
mp3> vgrep(44100, "ID", "^ID3$", "^ID.?$", "Info", "magic", "\u00ff", [0x49, 0x44]) mp3> vgrep(44100, "ID", "^ID3$", "^ID.?$", "Info", "magic", "\u00ff", [0x49, 0x44])
@ -34,7 +34,7 @@ mp3> vgrep(44100, "ID", "^ID3$", "^ID.?$", "Info", "magic", "\u00ff", [0x49, 0x4
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0|49 44 33 |ID3 |.headers[0].magic: "ID3" (valid) 0x0|49 44 33 |ID3 |.headers[0].magic: "ID3" (valid)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x40| 49 6e 66 6f | Info |.frames[0].tags.header: "Info" 0x40| 49 6e 66 6f | Info |.frames[0].tag.header: "Info" (XING variable bitrate)
mp3> fgrep(44100, "ID", "^ID3$", "^ID.?$", "Info", "magic", "\u00ff", [0x49, 0x44]) mp3> fgrep(44100, "ID", "^ID3$", "^ID.?$", "Info", "magic", "\u00ff", [0x49, 0x44])
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0|49 44 33 |ID3 |.headers[0].magic: "ID3" (valid) 0x0|49 44 33 |ID3 |.headers[0].magic: "ID3" (valid)
@ -50,7 +50,7 @@ mp3> bgrep(44100, "ID", "^ID3$", "^ID.?$", "Info", "magic", "\u00ff", [0x49, 0x4
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0|49 44 33 |ID3 |.headers[0].magic: "ID3" (valid) 0x0|49 44 33 |ID3 |.headers[0].magic: "ID3" (valid)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x40| 49 6e 66 6f | Info |.frames[0].tags.header: "Info" 0x40| 49 6e 66 6f | Info |.frames[0].tag.header: "Info" (XING variable bitrate)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x0|49 44 33 |ID3 |.headers[0].magic: "ID3" (valid) 0x0|49 44 33 |ID3 |.headers[0].magic: "ID3" (valid)
mp3> "64ff65ff66" | fromhex | bgrep("\u00ff"; "b") mp3> "64ff65ff66" | fromhex | bgrep("\u00ff"; "b")

View File

@ -94,7 +94,7 @@ mp3> $f[]
0x30| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| ...............| side_info{}: 0x30| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| ...............| side_info{}:
0x40|00 00 |.. | 0x40|00 00 |.. |
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x40| 49 6e 66 6f 00 00 00 0f 00 00 00 02 00 00| Info..........| tags{}: (mp3_frame_tags) 0x40| 49 6e 66 6f 00 00 00 0f 00 00 00 02 00 00| Info..........| tag{}: (mp3_frame_tags)
0x50|02 57 00 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6|.W..............| 0x50|02 57 00 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6 a6|.W..............|
* |until 0xdd.7 (156) | | * |until 0xdd.7 (156) | |
0xd0| 00 00| ..| audio_data: raw bits 0xd0| 00 00| ..| audio_data: raw bits

View File

@ -254,7 +254,7 @@ mp3> .headers[0] = 1
"scfsi0": 0, "scfsi0": 0,
"share": 0 "share": 0
}, },
"tags": { "tag": {
"abr_vbr": 0, "abr_vbr": 0,
"audiophile_replay_gain": 0, "audiophile_replay_gain": 0,
"bytes": 599, "bytes": 599,
@ -587,7 +587,7 @@ mp3> .headers[0] |= empty
"scfsi0": 0, "scfsi0": 0,
"share": 0 "share": 0
}, },
"tags": { "tag": {
"abr_vbr": 0, "abr_vbr": 0,
"audiophile_replay_gain": 0, "audiophile_replay_gain": 0,
"bytes": 599, "bytes": 599,

View File

@ -172,7 +172,7 @@ mp3> .headers[0].flags.a = 1
"scfsi0": 0, "scfsi0": 0,
"share": 0 "share": 0
}, },
"tags": { "tag": {
"abr_vbr": 0, "abr_vbr": 0,
"audiophile_replay_gain": 0, "audiophile_replay_gain": 0,
"bytes": 599, "bytes": 599,
@ -539,7 +539,7 @@ mp3> .headers[0].flags.a |= empty
"scfsi0": 0, "scfsi0": 0,
"share": 0 "share": 0
}, },
"tags": { "tag": {
"abr_vbr": 0, "abr_vbr": 0,
"audiophile_replay_gain": 0, "audiophile_replay_gain": 0,
"bytes": 599, "bytes": 599,