diff --git a/README.md b/README.md
index 5ab49fc62..2957a56ff 100644
--- a/README.md
+++ b/README.md
@@ -35,6 +35,7 @@ It was originally designed to query, inspect and debug media codecs and containe
[aac_frame](doc/formats.md#aac_frame),
adts,
adts_frame,
+[adm](doc/formats.md#adm),
aiff,
amf0,
apev2,
@@ -53,6 +54,7 @@ avc_sei,
avc_sps,
[avi](doc/formats.md#avi),
[avro_ocf](doc/formats.md#avro_ocf),
+[axml](doc/formats.md#adm),
[bencode](doc/formats.md#bencode),
bitcoin_blkdat,
[bitcoin_block](doc/formats.md#bitcoin_block),
@@ -66,7 +68,9 @@ bsd_loopback_frame,
bzip2,
[caff](doc/formats.md#caff),
[cbor](doc/formats.md#cbor),
+[chna](doc/formats.md#adm),
[csv](doc/formats.md#csv),
+[dolby_metadata](doc/formats.md#dolby_metadata),
dns,
dns_tcp,
elf,
diff --git a/doc/formats.md b/doc/formats.md
index 80b7aea4b..ab6e3c03e 100644
--- a/doc/formats.md
+++ b/doc/formats.md
@@ -7,6 +7,7 @@
|[`aac_frame`](#aac_frame) |Advanced Audio Coding frame ||
|`adts` |Audio Data Transport Stream |`adts_frame`|
|`adts_frame` |Audio Data Transport Stream frame |`aac_frame`|
+|[`adm`](#adm) |Audio Definition Model |`riff`|
|`aiff` |Audio Interchange File Format ||
|`amf0` |Action Message Format 0 ||
|`apev2` |APEv2 metadata tag |`image`|
@@ -25,6 +26,7 @@
|`avc_sps` |H.264/AVC Sequence Parameter Set ||
|[`avi`](#avi) |Audio Video Interleaved |`avc_au` `hevc_au` `mp3_frame` `flac_frame`|
|[`avro_ocf`](#avro_ocf) |Avro object container file ||
+|[`axml`](#adm) |Audio Definition Model Chunk |`riff`|
|[`bencode`](#bencode) |BitTorrent bencoding ||
|`bitcoin_blkdat` |Bitcoin blk.dat |`bitcoin_block`|
|[`bitcoin_block`](#bitcoin_block) |Bitcoin block |`bitcoin_transaction`|
@@ -38,7 +40,9 @@
|`bzip2` |bzip2 compression |`probe`|
|[`caff`](#caff) |Live2D Cubism archive |`probe`|
|[`cbor`](#cbor) |Concise Binary Object Representation ||
+|[`chna`](#adm) |Audio Definition Model Chunk |`riff`|
|[`csv`](#csv) |Comma separated values ||
+|[`dolby_metadata`](#dolby_metadata) |Dolby Metadata (Atmos, AC3, Digital Plus) |`riff`|
|`dns` |DNS packet ||
|`dns_tcp` |DNS packet (TCP) ||
|`elf` |Executable and Linkable Format ||
@@ -179,6 +183,27 @@ Decode value as aac_frame
... | aac_frame({object_type:1})
```
+## adm
+[Audio Definition Model](https://adm.ebu.io/background/what_is_the_adm.html) including 3D Audio.
+
+RIFF / WAV / Broadcast Wave Format (BWF) chunks:
+- `` Chunk, Track UIDs of Audio Definition Model
+- `` Chunk, BWF XML Metadata, e.g. for Audio Definition Model ambisonics and elements
+
+### Examples
+Decode ADM configuration from `` and `` chunks:
+```
+$ fq -d wav '.chunks[] | select(.id | IN("chna", "axml")) | tovalue' bwf.wav
+```
+
+### Authors
+- [@johnnymarnell](https://johnnymarnell.github.io), original author
+
+### References
+- https://adm.ebu.io/background/what_is_the_adm.html
+- https://tech.ebu.ch/publications/tech3285s7
+- https://tech.ebu.ch/publications/tech3285s5
+
## apple_bookmark
Apple BookmarkData.
@@ -590,6 +615,23 @@ $ fq -d csv -o comma="\t" to_csv file.tsv
$ fq -d csv '.[0] as $t | .[1:] | map(with_entries(.key = $t[.key]))' file.csv
```
+## dolby_metadata
+Dolby Metadata from `` chunk of RIFF / WAV / Broadcast Wave Format (BWF),
+including Dolby Atmos, AC3, Dolby Digital \[Plus\], and Dolby Audio Info (e.g. LUFS, True Peak).
+
+### Examples
+Decode Dolby metadata from `` chunk:
+```
+$ fq -d wav '.chunks[] | select(.id | IN("dbmd")) | tovalue' bwf.wav
+```
+
+### References
+- https://tech.ebu.ch/files/live/sites/tech/files/shared/tech/tech3285s6.pdf
+- https://github.com/DolbyLaboratories/dbmd-atmos-parser
+
+### Authors
+- [@johnnymarnell](https://johnnymarnell.github.io), original author
+
## fit
Garmin Flexible and Interoperable Data Transfer.
@@ -782,7 +824,6 @@ LevelDB Table.
- Zstandard uncompression is not implemented yet.
### Authors
-
- [@mikez](https://github.com/mikez), original author
### References
diff --git a/format/riff/adm.go b/format/riff/adm.go
index 21cd0a1e8..399fef0ee 100644
--- a/format/riff/adm.go
+++ b/format/riff/adm.go
@@ -25,7 +25,6 @@ func chnaDecode(d *decode.D, size int64) {
}
func axmlDecode(d *decode.D, size int64) {
- // fmt.Println("test axml")
// TODO(jmarnell): this chunk is all variable xml, so leave as is?
d.FieldRawLen("xml", size*8)
}
diff --git a/format/riff/common.go b/format/riff/common.go
index eeffe6222..6915b9f22 100644
--- a/format/riff/common.go
+++ b/format/riff/common.go
@@ -60,7 +60,7 @@ var chunkIDDescriptions = scalar.StrMapDescription{
"chna": " Chunk, Track UIDs of Audio Definition Model",
"axml": " Chunk, BWF XML Metadata, e.g. for Audio Definition Model ambisonics and elements",
- "dbmd": "Dolby Metadata",
+ "dbmd": "Dolby Metadata, e.g. Atmos, AC3, Dolby Digital [Plus]",
"ISMP": "SMPTE timecode",
"IDIT": "Time and date digitizing commenced",
diff --git a/format/riff/dolby.go b/format/riff/dolby.go
index af2cb3801..5ec16f95c 100644
--- a/format/riff/dolby.go
+++ b/format/riff/dolby.go
@@ -54,8 +54,6 @@ func dbmdDecode(d *decode.D, size int64) any {
d.FieldRawLen("unknown_segment_raw", int64(segmentSize*8))
}
- fmt.Println("bytesRead: ", (bitsLeft-d.BitsLeft())/8, " segment size:", segmentSize)
-
bytesRemaining := (bitsLeft-d.BitsLeft())/8 - int64(segmentSize)
if bytesRemaining < 0 {
d.Fatalf("Read too many bytes for segment %d, read %d over, expected %d", segmentID, -bytesRemaining, segmentSize)
@@ -63,6 +61,7 @@ func dbmdDecode(d *decode.D, size int64) any {
d.FieldValueUint("SKIPPED_BYTES", uint64(bytesRemaining))
d.SeekRel((int64(segmentSize) - bytesRemaining) * 8)
}
+
d.FieldU8("metadata_segment_checksum")
})
}
@@ -227,7 +226,6 @@ func parseAudioInfo(d *decode.D) {
func parseDolbyAtmos(d *decode.D, size uint64) {
d.FieldValueStr("metadata_segment_type", "dolby_atmos")
- bitsLeft := d.BitsLeft()
// d.SeekRel(32 * 8)
str := d.FieldUTF8Null("atmos_dbmd_content_creation_preamble")
@@ -248,14 +246,10 @@ func parseDolbyAtmos(d *decode.D, size uint64) {
d.SeekRel(15 * 8)
d.SeekRel(80 * 8)
-
- fmt.Println("test", int64(size)*8-(bitsLeft-d.BitsLeft()))
- d.SeekRel(int64(size)*8 - (bitsLeft - d.BitsLeft()))
}
func parseDolbyAtmosSupplemental(d *decode.D, size uint64) {
d.FieldValueStr("metadata_segment_type", "dolby_atmos_supplemental")
- bitsLeft := d.BitsLeft()
sync := d.FieldU32LE("dasms_sync")
d.FieldValueBool("dasms_sync_valid", sync == 0xf8726fbd)
@@ -281,8 +275,8 @@ func parseDolbyAtmosSupplemental(d *decode.D, size uint64) {
nonZeroBytes = append(nonZeroBytes, fmt.Sprintf("%d", b))
}
}
- // TODO(jmarnell): I think the +3dB trim settings are here. Would like this as an array of numbers
- // at least, instead of CSV string
+ // TODO(jmarnell): I think the +3dB trim settings are here.
+ // Would like this at least as an array of numbers, instead of this CSV string
d.FieldValueStr("trim_defs", strings.Join(nonZeroBytes, ", "))
i++
@@ -297,7 +291,4 @@ func parseDolbyAtmosSupplemental(d *decode.D, size uint64) {
d.FieldValueUint("render_mode", mode)
d.FieldValueStr("render_mode_type", binaural[mode])
})
-
- fmt.Println("test", int64(size)*8-(bitsLeft-d.BitsLeft()))
- d.SeekRel(int64(size)*8 - (bitsLeft - d.BitsLeft()))
}