Skip to content

Commit 90adba3

Browse files
committed
Address latest CR, temp using old code as supplemental segment broke?
1 parent c009996 commit 90adba3

File tree

13 files changed

+174
-124
lines changed

13 files changed

+174
-124
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ vp9_cfm,
158158
vp9_frame,
159159
vpx_ccr,
160160
[wasm](doc/formats.md#wasm),
161-
wav,
161+
[wav](doc/formats.md#wav),
162162
webp,
163163
[xml](doc/formats.md#xml),
164164
yaml,

doc/formats.md

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@
130130
|`vp9_frame` |VP9&nbsp;frame |<sub></sub>|
131131
|`vpx_ccr` |VPX&nbsp;Codec&nbsp;Configuration&nbsp;Record |<sub></sub>|
132132
|[`wasm`](#wasm) |WebAssembly&nbsp;Binary&nbsp;Format |<sub></sub>|
133-
|`wav` |WAV&nbsp;file |<sub>`id3v2` `id3v1` `id3v11` `dolby_metadata`</sub>|
133+
|[`wav`](#wav) |WAV&nbsp;file |<sub>`id3v2` `id3v1` `id3v11` `dolby_metadata`</sub>|
134134
|`webp` |WebP&nbsp;image |<sub>`exif` `vp8_frame` `icc_profile` `xml`</sub>|
135135
|[`xml`](#xml) |Extensible&nbsp;Markup&nbsp;Language |<sub></sub>|
136136
|`yaml` |YAML&nbsp;Ain't&nbsp;Markup&nbsp;Language |<sub></sub>|
@@ -616,7 +616,7 @@ RIFF / WAV / Broadcast Wave Format (BWF) chunks:
616616
- https://tech.ebu.ch/publications/tech3285s5
617617
- https://tech.ebu.ch/files/live/sites/tech/files/shared/tech/tech3285s6.pdf
618618
- https://github.com/DolbyLaboratories/dbmd-atmos-parser
619-
- https://github.com/MediaArea/MediaInfoLib/tree/Source/MediaInfo/Audio/File_DolbyAudioMetadata.cpp
619+
- https://github.com/MediaArea/MediaInfoLib/blob/master/Source/MediaInfo/Audio/File_DolbyAudioMetadata.cpp
620620

621621
## fit
622622
Garmin Flexible and Interoperable Data Transfer.
@@ -1470,6 +1470,49 @@ $ fq '.sections | {import: map(select(.id == "import_section").content.im.x[].nm
14701470
### References
14711471
- https://webassembly.github.io/spec/core/
14721472

1473+
## wav
1474+
WAV file.
1475+
1476+
WAVE audio file format.
1477+
1478+
Also includes support for [Audio Definition Model](https://adm.ebu.io/background/what_is_the_adm.html) and 3D Audio.
1479+
1480+
RIFF / WAV / Broadcast Wave Format (BWF) chunks:
1481+
1482+
- `RIFF`: primary container chunk specifying the file type and containing sub-chunks (e.g., fmt, data)
1483+
- `fmt`: describes format / stream encoding in data chunk
1484+
- `data`: indicates size and contains encoded raw sound data
1485+
- `bext`: broadcast extension chunk, containing broadcast-specific metadata such as description, originator, creation date, time reference, and more
1486+
- `LIST`: organizes additional metadata in sub-chunks, often used to include information like artist, genre, or title in INFO or other standardized formats
1487+
- `smpl`: sample metadata chunk, containing looping and sampling information, such as start and end points for loops, sample rate, and MIDI pitch
1488+
- `fact`: contains metadata on the original uncompressed data, such as the number of samples, typically used in non-PCM (compressed) formats to aid in playback and synchronization
1489+
- `chna`: track UIDs of Audio Definition Model
1490+
- `axml`: XML metadata, e.g. for Audio Definition Model ambisonics and elements as in [EBUCore spec](https://tech.ebu.ch/docs/tech/tech3293.pdf)
1491+
- `dbmd`: Dolby specific metadata like loudness and binaural settings, see also [`dolby_metadata` format](#dolby_metadata)
1492+
1493+
1494+
### Examples
1495+
Decode ADM configuration from `<chna>` and `<axml>` chunks:
1496+
```bash
1497+
$ fq -d wav '.chunks[] | select(.id | IN("chna", "axml")) | tovalue' amd-bwf.wav
1498+
1499+
# Extract ADM <axml> chunk objects definitions xml content
1500+
$ fq -r -d wav '.chunks[] | select(.id | IN("axml")) | .xml | tovalue' amd-bwf.wav | tee axml-content.xml
1501+
```
1502+
1503+
### Authors
1504+
- [@wader](https://github.com/wader), original author
1505+
- [@johnnymarnell](https://johnnymarnell.github.io), ADM support
1506+
1507+
### References
1508+
- http://soundfile.sapp.org/doc/WaveFormat/
1509+
- https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/wavdec.c
1510+
- https://tech.ebu.ch/docs/tech/tech3285.pdf
1511+
- http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
1512+
- https://adm.ebu.io/background/what_is_the_adm.html
1513+
- https://tech.ebu.ch/docs/tech/tech3285s7.pdf
1514+
- https://tech.ebu.ch/docs/tech/tech3285s5.pdf
1515+
14731516
## xml
14741517
Extensible Markup Language.
14751518

format/riff/adm.go

Lines changed: 0 additions & 30 deletions
This file was deleted.

format/riff/adm.md

Lines changed: 0 additions & 22 deletions
This file was deleted.

format/riff/aiff.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func aiffDecode(d *decode.D) any {
5454
}
5555
return id, size
5656
},
57-
func(d *decode.D, id string, path path, size int64) (bool, any) {
57+
func(d *decode.D, id string, path path) (bool, any) {
5858
switch id {
5959
case "FORM":
6060
riffType = d.FieldUTF8("format", 4, d.StrAssert(aiffRiffType))

format/riff/avi.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ func aviDecodeEx(d *decode.D, ai format.AVI_In, extendedChunk bool) {
238238
size := d.FieldU32("size")
239239
return id, int64(size)
240240
},
241-
func(d *decode.D, id string, path path, size int64) (bool, any) {
241+
func(d *decode.D, id string, path path) (bool, any) {
242242
switch id {
243243
case "RIFF":
244244
foundRiffType = d.FieldUTF8("type", 4, d.StrAssert(requiredRiffType))

format/riff/common.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ func (p path) topData() any {
1919
return p[len(p)-1].data
2020
}
2121

22-
func riffDecode(d *decode.D, path path, headFn func(d *decode.D, path path) (string, int64), chunkFn func(d *decode.D, id string, path path, size int64) (bool, any)) {
22+
func riffDecode(d *decode.D, path path, headFn func(d *decode.D, path path) (string, int64), chunkFn func(d *decode.D, id string, path path) (bool, any)) {
2323
id, size := headFn(d, path)
2424

2525
d.FramedFn(size*8, func(d *decode.D) {
26-
hasChildren, data := chunkFn(d, id, path, size)
26+
hasChildren, data := chunkFn(d, id, path)
2727
if hasChildren {
2828
np := append(path, pathEntry{id: id, data: data})
2929
d.FieldArray("chunks", func(d *decode.D) {
@@ -58,6 +58,12 @@ var chunkIDDescriptions = scalar.StrMapDescription{
5858

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

61+
"data": "Raw sound encoded data",
62+
"bext": "Broadcast extension, e.g. creator, date, etc.",
63+
"smpl": "Sample metadata, e.g. loop points",
64+
"fact": "Original info used for compression, e.g. sample length",
65+
66+
// BWF ADM master and Dolby Metadata
6167
"chna": "Track UIDs of Audio Definition Model",
6268
"axml": "Audio Definition Model ambisonics and elements",
6369
"dbmd": "Dolby Metadata, e.g. Atmos, AC3, Dolby Digital [Plus]",

format/riff/dolby.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/wader/fq/pkg/scalar"
1313
)
1414

15-
func tmp_dbmdDecode(d *decode.D, size int64) any {
15+
func old_dbmdDecode(d *decode.D) any {
1616
version := d.U32()
1717
major := (version >> 24) & 0xFF
1818
minor := (version >> 16) & 0xFF
@@ -35,32 +35,32 @@ func tmp_dbmdDecode(d *decode.D, size int64) any {
3535
}
3636

3737
segmentSize := d.FieldU16("metadata_segment_size")
38-
bitsLeft := d.BitsLeft()
38+
// bitsLeft := d.BitsLeft()
3939

4040
switch segmentID {
4141
case 1:
42-
parseDolbyE(d)
42+
tmp_parseDolbyE(d)
4343
case 3:
44-
parseDolbyDigital(d)
44+
tmp_parseDolbyDigital(d)
4545
case 7:
46-
parseDolbyDigitalPlus(d)
46+
tmp_parseDolbyDigitalPlus(d)
4747
case 8:
48-
parseAudioInfo(d)
48+
tmp_parseAudioInfo(d)
4949
case 9:
50-
parseDolbyAtmos(d)
50+
tmp_parseDolbyAtmos(d)
5151
case 10:
52-
parseDolbyAtmosSupplemental(d)
52+
tmp_parseDolbyAtmosSupplemental(d)
5353
default:
5454
d.FieldRawLen("unknown_segment_raw", int64(segmentSize*8))
5555
}
5656

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-
}
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+
// }
6464

6565
d.FieldU8("metadata_segment_checksum")
6666
})
@@ -224,7 +224,7 @@ func tmp_parseAudioInfo(d *decode.D) {
224224
d.FieldUTF8("segment_modified_date", 32)
225225
}
226226

227-
func tmp_parseDolbyAtmos(d *decode.D, size uint64) {
227+
func tmp_parseDolbyAtmos(d *decode.D) {
228228
d.FieldValueStr("metadata_segment_type", "dolby_atmos")
229229

230230
// d.SeekRel(32 * 8)
@@ -248,7 +248,7 @@ func tmp_parseDolbyAtmos(d *decode.D, size uint64) {
248248
d.SeekRel(80 * 8)
249249
}
250250

251-
func tmp_parseDolbyAtmosSupplemental(d *decode.D, size uint64) {
251+
func tmp_parseDolbyAtmosSupplemental(d *decode.D) {
252252
d.FieldValueStr("metadata_segment_type", "dolby_atmos_supplemental")
253253

254254
sync := d.FieldU32LE("dasms_sync")

format/riff/dolby_metadata.go

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,21 @@ func dbmdDecode(d *decode.D) any {
4242
for !seenEnd {
4343
d.FieldStruct("metadata_segment", func(d *decode.D) {
4444
segmentID := d.FieldU8("id", metadataSegmentTypeMap)
45-
if segmentID == 0 {
45+
46+
// TODO(jmarnell): This will always make an empty end segment, I think it would be better to omit it
47+
if segmentID == metadataSegmentTypeEnd {
4648
seenEnd = true
4749
return
4850
}
4951

5052
segmentSize := d.FieldU16("size")
5153

5254
switch segmentID {
53-
case metadataSegmentTypeDolbyEMetadata:
55+
case metadataSegmentTypeDolbyE:
5456
parseDolbyE(d)
55-
case metadataSegmentTypeDolbyEDigitaletadata:
57+
case metadataSegmentTypeDolbyDigital:
5658
parseDolbyDigital(d)
57-
case metadataSegmentTypeDolbyDigitalPlusMetadata:
59+
case metadataSegmentTypeDolbyDigitalPlus:
5860
parseDolbyDigitalPlus(d)
5961
case metadataSegmentTypeAudioInfo:
6062
parseAudioInfo(d)
@@ -66,6 +68,7 @@ func dbmdDecode(d *decode.D) any {
6668
d.FieldRawLen("unknown", int64(segmentSize*8))
6769
}
6870

71+
// TODO: use this to validate parsing
6972
d.FieldU8("checksum", scalar.UintHex)
7073
})
7174
}
@@ -138,31 +141,31 @@ var trimConfigName = scalar.UintMapDescription{
138141
}
139142

140143
const (
141-
metadataSegmentTypeEnd = 0
142-
metadataSegmentTypeDolbyEMetadata = 1
143-
metadataSegmentTypeDolbyReserved2 = 2
144-
metadataSegmentTypeDolbyEDigitaletadata = 3
145-
metadataSegmentTypeDolbyReserved4 = 4
146-
metadataSegmentTypeDolbyReserved5 = 5
147-
metadataSegmentTypeDolbyReserved6 = 6
148-
metadataSegmentTypeDolbyDigitalPlusMetadata = 7
149-
metadataSegmentTypeAudioInfo = 8
150-
metadataSegmentTypeDolbyAtmos = 9
151-
metadataSegmentTypeDolbyAtmosSupplemental = 10
144+
metadataSegmentTypeEnd = 0
145+
metadataSegmentTypeDolbyE = 1
146+
metadataSegmentTypeDolbyReserved2 = 2
147+
metadataSegmentTypeDolbyDigital = 3
148+
metadataSegmentTypeDolbyReserved4 = 4
149+
metadataSegmentTypeDolbyReserved5 = 5
150+
metadataSegmentTypeDolbyReserved6 = 6
151+
metadataSegmentTypeDolbyDigitalPlus = 7
152+
metadataSegmentTypeAudioInfo = 8
153+
metadataSegmentTypeDolbyAtmos = 9
154+
metadataSegmentTypeDolbyAtmosSupplemental = 10
152155
)
153156

154157
var metadataSegmentTypeMap = scalar.UintMapSymStr{
155-
metadataSegmentTypeEnd: "end",
156-
metadataSegmentTypeDolbyEMetadata: "dolby_e_metadata",
157-
metadataSegmentTypeDolbyReserved2: "reserved2",
158-
metadataSegmentTypeDolbyEDigitaletadata: "dolby_e_digitale_tadata",
159-
metadataSegmentTypeDolbyReserved4: "reserved4",
160-
metadataSegmentTypeDolbyReserved5: "reserved5",
161-
metadataSegmentTypeDolbyReserved6: "reserved6",
162-
metadataSegmentTypeDolbyDigitalPlusMetadata: "dolby_digital_plus_metadata",
163-
metadataSegmentTypeAudioInfo: "audio_info",
164-
metadataSegmentTypeDolbyAtmos: "dolby_atmos",
165-
metadataSegmentTypeDolbyAtmosSupplemental: "dolby_atmos_supplemental",
158+
metadataSegmentTypeEnd: "end",
159+
metadataSegmentTypeDolbyE: "dolby_e_metadata",
160+
metadataSegmentTypeDolbyReserved2: "reserved2",
161+
metadataSegmentTypeDolbyDigital: "dolby_digital_metadata",
162+
metadataSegmentTypeDolbyReserved4: "reserved4",
163+
metadataSegmentTypeDolbyReserved5: "reserved5",
164+
metadataSegmentTypeDolbyReserved6: "reserved6",
165+
metadataSegmentTypeDolbyDigitalPlus: "dolby_digital_plus_metadata",
166+
metadataSegmentTypeAudioInfo: "audio_info",
167+
metadataSegmentTypeDolbyAtmos: "dolby_atmos",
168+
metadataSegmentTypeDolbyAtmosSupplemental: "dolby_atmos_supplemental",
166169
}
167170

168171
func parseDolbyE(d *decode.D) {
@@ -283,27 +286,19 @@ func parseDolbyAtmosSupplemental(d *decode.D) {
283286

284287
i := 0
285288
d.FieldStructNArray("trim_configs", "trim_config", 9, func(d *decode.D) {
286-
d.FieldRawLen("reserved", 7)
287-
d.FieldU1("type", scalar.UintMapSymStr{
289+
d.FieldRawLen("reserved0", 7)
290+
trimType := d.FieldU1("type", scalar.UintMapSymStr{
288291
0: "manual",
289292
1: "automatic",
290293
})
291294
d.FieldValueStr("config_name", trimConfigName[uint64(i)])
292295

293-
// TODO: this is null separted list of def strings?
294-
d.FieldUTF8("raw", 14)
295-
// str := d.UTF8(14)
296-
// bytes := []byte(str)
297-
// var nonZeroBytes []string
298-
// for _, b := range bytes {
299-
// if b != 0 {
300-
// nonZeroBytes = append(nonZeroBytes, fmt.Sprintf("%d", b))
301-
// }
302-
// }
303-
// TODO(jmarnell): I think the +3dB trim settings are here.
304-
// Would like this at least as an array of numbers, instead of this CSV string
305-
// d.FieldValueStr("trim_defs", strings.Join(nonZeroBytes, ", "))
306-
296+
if trimType == 1 {
297+
d.FieldUTF8("reserved1", 14)
298+
} else {
299+
// TODO: Reference MediaInfo's logic and Dolby pdf's
300+
d.FieldUTF8("manual_trim_raw_config", 14)
301+
}
307302
i++
308303
})
309304

format/riff/dolby_metadata.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ RIFF / WAV / Broadcast Wave Format (BWF) chunks:
2020
- https://tech.ebu.ch/publications/tech3285s5
2121
- https://tech.ebu.ch/files/live/sites/tech/files/shared/tech/tech3285s6.pdf
2222
- https://github.com/DolbyLaboratories/dbmd-atmos-parser
23-
- https://github.com/MediaArea/MediaInfoLib/tree/Source/MediaInfo/Audio/File_DolbyAudioMetadata.cpp
23+
- https://github.com/MediaArea/MediaInfoLib/blob/master/Source/MediaInfo/Audio/File_DolbyAudioMetadata.cpp

0 commit comments

Comments
 (0)