Skip to content

Commit f2a6987

Browse files
committed
Various fix and cleanup
1 parent 83abdda commit f2a6987

File tree

4 files changed

+110
-118
lines changed

4 files changed

+110
-118
lines changed

format/riff/adm.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@ func chnaDecode(d *decode.D, size int64) {
1919
d.FieldUTF8("uid", 12)
2020
d.FieldUTF8("track_format_id_reference", 14)
2121
d.FieldUTF8("pack_format_id_reference", 11)
22-
// Skip padding single byte
23-
d.U8()
22+
d.FieldRawLen("padding", 8)
2423
})
2524
}
2625

2726
func axmlDecode(d *decode.D, size int64) {
2827
// TODO(jmarnell): this chunk is all variable xml, so leave as is?
29-
d.FieldRawLen("xml", size*8)
28+
d.FieldUTF8("xml", int(size))
3029
}

format/riff/common.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ var chunkIDDescriptions = scalar.StrMapDescription{
5858

5959
"dmlh": "Extended AVI header",
6060

61-
"chna": "<chna> Chunk, Track UIDs of Audio Definition Model",
62-
"axml": "<axml> Chunk, BWF XML Metadata, e.g. for Audio Definition Model ambisonics and elements",
61+
"chna": "Track UIDs of Audio Definition Model",
62+
"axml": "Audio Definition Model ambisonics and elements",
6363
"dbmd": "Dolby Metadata, e.g. Atmos, AC3, Dolby Digital [Plus]",
6464

6565
"ISMP": "SMPTE timecode",

format/riff/dolby.go

Lines changed: 105 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -5,87 +5,62 @@ package riff
55
// https://github.com/DolbyLaboratories/dbmd-atmos-parser
66

77
import (
8-
"fmt"
9-
"strings"
10-
118
"github.com/wader/fq/pkg/decode"
129
"github.com/wader/fq/pkg/scalar"
1310
)
1411

15-
func dbmdDecode(d *decode.D, size int64) any {
16-
version := d.U32()
17-
major := (version >> 24) & 0xFF
18-
minor := (version >> 16) & 0xFF
19-
patch := (version >> 8) & 0xFF
20-
build := version & 0xFF
21-
d.FieldValueStr("version", fmt.Sprintf("%d.%d.%d.%d", major, minor, patch, build))
12+
func dbmdDecode(d *decode.D) any {
13+
d.FieldStruct("version", func(d *decode.D) {
14+
d.FieldU8("major")
15+
d.FieldU8("minor")
16+
d.FieldU8("patch")
17+
d.FieldU8("build")
18+
})
2219

2320
d.FieldArray("metadata_segments", func(d *decode.D) {
24-
for {
21+
seenEnd := false
22+
for !seenEnd {
2523
d.FieldStruct("metadata_segment", func(d *decode.D) {
26-
segmentID := d.FieldU8("metadata_segment_id")
27-
28-
// TODO(jmarnell): I think I need a loop until, but not creating these empty segments
29-
// spec says we're done with 0 ID, so I'd like to not make the empty segment(s)
24+
segmentID := d.FieldU8("id", metadataSegmentTypeMap)
3025
if segmentID == 0 {
31-
if d.BitsLeft() > 0 {
32-
d.SeekRel(d.BitsLeft() * 8)
33-
}
26+
seenEnd = true
3427
return
3528
}
3629

37-
segmentSize := d.FieldU16("metadata_segment_size")
38-
bitsLeft := d.BitsLeft()
30+
segmentSize := d.FieldU16("size")
3931

4032
switch segmentID {
41-
case 1:
33+
case metadataSegmentTypeDolyEMetadata:
4234
parseDolbyE(d)
43-
case 3:
35+
case metadataSegmentTypeDolyEDigitaletadata:
4436
parseDolbyDigital(d)
45-
case 7:
37+
case metadataSegmentTypeDolyDigitalPlusMetadata:
4638
parseDolbyDigitalPlus(d)
47-
case 8:
39+
case metadataSegmentTypeAudioInfo:
4840
parseAudioInfo(d)
49-
case 9:
50-
parseDolbyAtmos(d, segmentSize)
51-
case 10:
52-
parseDolbyAtmosSupplemental(d, segmentSize)
41+
case metadataSegmentTypeDolyAtmos:
42+
parseDolbyAtmos(d)
43+
case metadataSegmentTypeDolbyAtmosSupplemental:
44+
parseDolbyAtmosSupplemental(d)
5345
default:
54-
d.FieldRawLen("unknown_segment_raw", int64(segmentSize*8))
46+
d.FieldRawLen("unknown", int64(segmentSize*8))
5547
}
5648

57-
bytesRemaining := (bitsLeft-d.BitsLeft())/8 - int64(segmentSize)
58-
if bytesRemaining < 0 {
59-
d.Fatalf("Read too many bytes for segment %d, read %d over, expected %d", segmentID, -bytesRemaining, segmentSize)
60-
} else if bytesRemaining > 0 {
61-
d.FieldValueUint("SKIPPED_BYTES", uint64(bytesRemaining))
62-
d.SeekRel((int64(segmentSize) - bytesRemaining) * 8)
63-
}
64-
65-
d.FieldU8("metadata_segment_checksum")
49+
d.FieldU8("checksum", scalar.UintHex)
6650
})
6751
}
6852
})
6953

7054
return nil
7155
}
7256

73-
var compressionDesc = scalar.UintMapDescription{
57+
var compressionDescMap = scalar.UintMapSymStr{
7458
0: "none",
75-
1: "Film, Standard",
76-
2: "Film, Light",
77-
3: "Music, Standard",
78-
4: "Music, Light",
79-
5: "Speech",
80-
// TODO(jmarnell): Can I handle rest is "Reserved"?
81-
}
82-
83-
// TODO(jmarnell): Better way to handle "Reserved"?
84-
func mapWithReserved(m map[uint64]string, key uint64) string {
85-
if val, ok := m[key]; ok {
86-
return val
87-
}
88-
return "Reserved"
59+
1: "film_standard",
60+
2: "film_light",
61+
3: "music_standard",
62+
4: "music_light",
63+
5: "speech",
8964
}
9065

9166
var bitstreamMode = scalar.UintMapDescription{
@@ -101,20 +76,20 @@ var bitstreamMode = scalar.UintMapDescription{
10176
0b1000: "associated service: karaoke (K)",
10277
}
10378

104-
var binaural = scalar.UintMapDescription{
79+
var binauralRenderModeMap = scalar.UintMapSymStr{
10580
0: "bypass",
10681
1: "near",
10782
2: "far",
10883
3: "mid",
109-
4: "not indicated",
84+
4: "not_indicated",
11085
}
11186

112-
var warpMode = scalar.UintMapDescription{
113-
0: "normal",
114-
1: "warping",
115-
2: "downmix Dolby Pro Logic IIx",
116-
3: "downmix LoRo",
117-
4: "not indicated (Default warping will be applied.)",
87+
var warpModeMap = scalar.UintMap{
88+
0: {Sym: "normal"},
89+
1: {Sym: "warping"},
90+
2: {Sym: "downmix_dolby_pro_logic_iix"},
91+
3: {Sym: "downmix_loro"},
92+
4: {Sym: "not_indicated", Description: "Default warping will be applied"},
11893
}
11994

12095
var trimConfigName = scalar.UintMapDescription{
@@ -134,9 +109,35 @@ var trimType = scalar.UintMapDescription{
134109
1: "automatic",
135110
}
136111

137-
func parseDolbyE(d *decode.D) {
138-
d.FieldValueStr("metadata_segment_type", "dolby_e")
112+
const (
113+
metadataSegmentTypeEnd = 0
114+
metadataSegmentTypeDolyEMetadata = 1
115+
metadataSegmentTypeDolyReserved2 = 2
116+
metadataSegmentTypeDolyEDigitaletadata = 3
117+
metadataSegmentTypeDolyReserved4 = 4
118+
metadataSegmentTypeDolyReserved5 = 5
119+
metadataSegmentTypeDolyReserved6 = 6
120+
metadataSegmentTypeDolyDigitalPlusMetadata = 7
121+
metadataSegmentTypeAudioInfo = 8
122+
metadataSegmentTypeDolyAtmos = 9
123+
metadataSegmentTypeDolbyAtmosSupplemental = 10
124+
)
125+
126+
var metadataSegmentTypeMap = scalar.UintMapSymStr{
127+
metadataSegmentTypeEnd: "end",
128+
metadataSegmentTypeDolyEMetadata: "doly_e_metadata",
129+
metadataSegmentTypeDolyReserved2: "reserved2",
130+
metadataSegmentTypeDolyEDigitaletadata: "doly_e_digitale_tadata",
131+
metadataSegmentTypeDolyReserved4: "reserved4",
132+
metadataSegmentTypeDolyReserved5: "reserved5",
133+
metadataSegmentTypeDolyReserved6: "reserved6",
134+
metadataSegmentTypeDolyDigitalPlusMetadata: "doly_digital_plus_metadata",
135+
metadataSegmentTypeAudioInfo: "audio_info",
136+
metadataSegmentTypeDolyAtmos: "doly_atmos",
137+
metadataSegmentTypeDolbyAtmosSupplemental: "dolby_atmos_supplemental",
138+
}
139139

140+
func parseDolbyE(d *decode.D) {
140141
d.FieldU8("program_config")
141142
d.FieldU8("frame_rate_code")
142143
d.FieldRawLen("e_SMPTE_time_code", 8*8)
@@ -146,8 +147,6 @@ func parseDolbyE(d *decode.D) {
146147
}
147148

148149
func parseDolbyDigital(d *decode.D) {
149-
d.FieldValueStr("metadata_segment_type", "dolby_digital")
150-
151150
d.FieldU8("ac3_program_id")
152151
d.FieldU8("program_info")
153152
d.FieldU8("datarate_info")
@@ -167,9 +166,8 @@ func parseDolbyDigital(d *decode.D) {
167166
}
168167

169168
func parseDolbyDigitalPlus(d *decode.D) {
170-
d.FieldValueStr("metadata_segment_type", "dolby_digital_plus")
171-
172169
d.FieldU8("program_id")
170+
// TODO: make struct and read U1(?) U1 (lfeon) U3 (bsmod) U3(acmod) fields?
173171
programInfo := d.FieldU8("program_info")
174172
lfeon := programInfo & 0b1_000_000
175173
bsmod := programInfo & 0b0_111_000
@@ -192,8 +190,8 @@ func parseDolbyDigitalPlus(d *decode.D) {
192190

193191
d.FieldU24LE("ddplus_reserved_b")
194192

195-
d.FieldValueStr("compr1_type", mapWithReserved(compressionDesc, d.FieldU8("compr1")))
196-
d.FieldValueStr("dynrng1_type", mapWithReserved(compressionDesc, d.FieldU8("dynrng1")))
193+
d.FieldU8("compr1", scalar.UintSym("reserved"), compressionDescMap)
194+
d.FieldU8("dynrng1", scalar.UintSym("reserved"), compressionDescMap)
197195

198196
d.FieldU24LE("ddplus_reserved_c")
199197

@@ -206,8 +204,6 @@ func parseDolbyDigitalPlus(d *decode.D) {
206204
}
207205

208206
func parseAudioInfo(d *decode.D) {
209-
d.FieldValueStr("metadata_segment_type", "audio_info")
210-
211207
d.FieldU8("program_id")
212208
d.FieldUTF8("audio_origin", 32)
213209
d.FieldU32LE("largest_sample_value")
@@ -224,36 +220,30 @@ func parseAudioInfo(d *decode.D) {
224220
d.FieldUTF8("segment_modified_date", 32)
225221
}
226222

227-
func parseDolbyAtmos(d *decode.D, size uint64) {
228-
d.FieldValueStr("metadata_segment_type", "dolby_atmos")
229-
230-
// d.SeekRel(32 * 8)
231-
str := d.FieldUTF8Null("atmos_dbmd_content_creation_preamble")
232-
d.SeekRel(int64(32-len(str)-1) * 8)
233-
234-
str = d.FieldUTF8Null("atmos_dbmd_content_creation_tool")
235-
d.SeekRel(int64(64-len(str)-1) * 8)
223+
func parseDolbyAtmos(d *decode.D) {
224+
// TODO: both these are fixed size null terminated strings?
225+
d.FieldUTF8NullFixedLen("atmos_dbmd_content_creation_preamble", 32)
226+
d.FieldUTF8NullFixedLen("atmos_dbmd_content_creation_tool", 64)
227+
d.FieldStruct("version", func(d *decode.D) {
228+
d.FieldU8("major")
229+
d.FieldU8("minor")
230+
d.FieldU8("micro")
231+
})
236232

237-
major := d.U8()
238-
minor := d.U8()
239-
micro := d.U8()
240-
d.FieldValueStr("version", fmt.Sprintf("%d.%d.%d", major, minor, micro))
241-
d.SeekRel(53 * 8)
233+
// TODO: what is this?
234+
d.FieldRawLen("unknown0", 53*8)
242235

243-
warpBedReserved := d.U8()
244-
d.FieldValueUint("warp_mode", warpBedReserved&0x7)
245-
d.FieldValueStr("warp_mode_type", warpMode[warpBedReserved&0x7])
236+
d.FieldU8("warp_mode", warpModeMap)
246237

247-
d.SeekRel(15 * 8)
248-
d.SeekRel(80 * 8)
238+
// TODO: what is this?
239+
d.FieldRawLen("unknown1", 15*8)
240+
d.FieldRawLen("unknown2", 80*8)
249241
}
250242

251-
func parseDolbyAtmosSupplemental(d *decode.D, size uint64) {
252-
d.FieldValueStr("metadata_segment_type", "dolby_atmos_supplemental")
253-
254-
sync := d.FieldU32LE("dasms_sync")
255-
d.FieldValueBool("dasms_sync_valid", sync == 0xf8726fbd)
243+
func parseDolbyAtmosSupplemental(d *decode.D) {
244+
d.FieldU32LE("dasms_sync", d.UintAssert(0xf8726fbd), scalar.UintHex)
256245

246+
// TODO: wav.go sets LE default i think?
257247
objectCount := int64(d.FieldU16LE("object_count"))
258248
d.FieldU8LE("reserved")
259249

@@ -265,30 +255,33 @@ func parseDolbyAtmosSupplemental(d *decode.D, size uint64) {
265255
d.FieldValueStr("trim_type", trimType[autoTrim])
266256
d.FieldValueStr("trim_config_name", trimConfigName[uint64(i)])
267257

268-
//d.SeekRel(14 * 8)
269-
// d.FieldUTF8("raw", 14)
270-
str := d.UTF8(14)
271-
bytes := []byte(str)
272-
var nonZeroBytes []string
273-
for _, b := range bytes {
274-
if b != 0 {
275-
nonZeroBytes = append(nonZeroBytes, fmt.Sprintf("%d", b))
276-
}
277-
}
258+
// TODO: this is null separted list of def strings?
259+
d.FieldUTF8("raw", 14)
260+
// str := d.UTF8(14)
261+
// bytes := []byte(str)
262+
// var nonZeroBytes []string
263+
// for _, b := range bytes {
264+
// if b != 0 {
265+
// nonZeroBytes = append(nonZeroBytes, fmt.Sprintf("%d", b))
266+
// }
267+
// }
278268
// TODO(jmarnell): I think the +3dB trim settings are here.
279269
// Would like this at least as an array of numbers, instead of this CSV string
280-
d.FieldValueStr("trim_defs", strings.Join(nonZeroBytes, ", "))
270+
// d.FieldValueStr("trim_defs", strings.Join(nonZeroBytes, ", "))
281271

282272
i++
283273
})
284274

285-
d.FieldStructNArray("objects", "object", objectCount, func(d *decode.D) {
286-
d.FieldU8LE("object_value")
275+
d.FieldArray("objects", func(d *decode.D) {
276+
for i := int64(0); i < objectCount; i++ {
277+
d.FieldU8("object_value")
278+
}
287279
})
288280

289-
d.FieldStructNArray("binaural_render_modes", "binaural_render_mode", objectCount, func(d *decode.D) {
290-
mode := d.U8LE() & 0x7
291-
d.FieldValueUint("render_mode", mode)
292-
d.FieldValueStr("render_mode_type", binaural[mode])
281+
d.FieldArray("binaural_render_modes", func(d *decode.D) {
282+
// TODO: 0x7 mask needed?
283+
for i := int64(0); i < objectCount; i++ {
284+
d.FieldU8("render_mode", scalar.UintActualFn(func(a uint64) uint64 { return a & 0x7 }), binauralRenderModeMap)
285+
}
293286
})
294287
}

format/riff/wav.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ func wavDecode(d *decode.D) any {
165165
axmlDecode(d, size)
166166
return false, nil
167167
case "dbmd":
168-
dbmdDecode(d, size)
168+
dbmdDecode(d)
169169
return false, nil
170170

171171
default:

0 commit comments

Comments
 (0)