Text cleanup/red policing

This commit is contained in:
Jamie Hardt
2023-11-08 19:21:47 -08:00
parent 86a4edc983
commit 4f51584fe9
3 changed files with 37 additions and 21 deletions

View File

@@ -8,17 +8,20 @@ class WavBextReader:
""" """
Read Broadcast-WAV extended metadata. Read Broadcast-WAV extended metadata.
:param bext_data: The bytes-like data. :param bext_data: The bytes-like data.
:param encoding: The encoding to use when decoding the text fields of the :param encoding: The encoding to use when decoding the text fields of
BEXT metadata scope. According to EBU Rec 3285 this shall be ASCII. the BEXT metadata scope. According to EBU Rec 3285 this shall be
ASCII.
""" """
packstring = "<256s" + "32s" + "32s" + "10s" + "8s" + "QH" + "64s" + "hhhhh" + "180s" packstring = "<256s" + "32s" + "32s" + "10s" + "8s" + "QH" + "64s" + \
"hhhhh" + "180s"
rest_starts = struct.calcsize(packstring) rest_starts = struct.calcsize(packstring)
unpacked = struct.unpack(packstring, bext_data[:rest_starts]) unpacked = struct.unpack(packstring, bext_data[:rest_starts])
def sanitize_bytes(b : bytes) -> str: def sanitize_bytes(b : bytes) -> str:
# honestly can't remember why I'm stripping nulls this way # honestly can't remember why I'm stripping nulls this way
first_null = next((index for index, byte in enumerate(b) if byte == 0), None) first_null = next((index for index, byte in enumerate(b) \
if byte == 0), None)
trimmed = b if first_null is None else b[:first_null] trimmed = b if first_null is None else b[:first_null]
decoded = trimmed.decode(encoding) decoded = trimmed.decode(encoding)
return decoded return decoded
@@ -50,8 +53,8 @@ class WavBextReader:
#: BEXT version. #: BEXT version.
self.version : int = unpacked[6] self.version : int = unpacked[6]
#: SMPTE 330M UMID of this audio file, 64 bytes are allocated though the UMID #: SMPTE 330M UMID of this audio file, 64 bytes are allocated though
#: may only be 32 bytes long. #: the UMID may only be 32 bytes long.
self.umid : Optional[bytes] = None self.umid : Optional[bytes] = None
#: EBU R128 Integrated loudness, in LUFS. #: EBU R128 Integrated loudness, in LUFS.

View File

@@ -114,7 +114,8 @@ class CueEntry(NamedTuple):
@classmethod @classmethod
def read(cls, data: bytes) -> 'CueEntry': def read(cls, data: bytes) -> 'CueEntry':
assert len(data) == cls.format_size(), \ assert len(data) == cls.format_size(), \
f"cue data size incorrect, expected {calcsize(cls.Format)} found {len(data)}" (f"cue data size incorrect, expected {calcsize(cls.Format)} "
"found {len(data)}")
parsed = unpack(cls.Format, data) parsed = unpack(cls.Format, data)

View File

@@ -208,8 +208,8 @@ class DolbyDigitalPlusMetadata:
class PreferredDownMixMode(Enum): class PreferredDownMixMode(Enum):
""" """
Indicates the creating engineer's preference of what the receiver should Indicates the creating engineer's preference of what the receiver
downmix. should downmix.
§ 4.3.8.1 § 4.3.8.1
""" """
NOT_INDICATED = 0b00 NOT_INDICATED = 0b00
@@ -386,7 +386,8 @@ class DolbyDigitalPlusMetadata:
# downmix_mode, ltrt_center_downmix_level, ltrt_surround_downmix_level # downmix_mode, ltrt_center_downmix_level, ltrt_surround_downmix_level
def ext_bsi1_word2(b): def ext_bsi1_word2(b):
return DolbyDigitalPlusMetadata.PreferredDownMixMode(b & 0xC0 >> 6), \ return DolbyDigitalPlusMetadata\
.PreferredDownMixMode(b & 0xC0 >> 6), \
DolbyDigitalPlusMetadata.DownMixLevelToken(b & 0x38 >> 3), \ DolbyDigitalPlusMetadata.DownMixLevelToken(b & 0x38 >> 3), \
DolbyDigitalPlusMetadata.DownMixLevelToken(b & 0x7) DolbyDigitalPlusMetadata.DownMixLevelToken(b & 0x7)
@@ -423,14 +424,19 @@ class DolbyDigitalPlusMetadata:
pid = program_id(buffer[0]) pid = program_id(buffer[0])
lfe_on, bitstream_mode, audio_coding_mode = program_info(buffer[1]) lfe_on, bitstream_mode, audio_coding_mode = program_info(buffer[1])
ddplus_reserved1(buffer[2:2]) ddplus_reserved1(buffer[2:2])
center_downmix_level, surround_downmix_level, dolby_surround_encoded = surround_config(buffer[4]) center_downmix_level, surround_downmix_level, \
langcode_present, copyright_bitstream, original_bitstream, dialnorm = dialnorm_info(buffer[5]) dolby_surround_encoded = surround_config(buffer[4])
langcode_present, copyright_bitstream, original_bitstream, \
dialnorm = dialnorm_info(buffer[5])
langcode = langcod(buffer[6]) langcode = langcod(buffer[6])
prod_info_exists, mixlevel, roomtype = audio_prod_info(buffer[7]) prod_info_exists, mixlevel, roomtype = audio_prod_info(buffer[7])
loro_center_downmix_level, loro_surround_downmix_level = ext_bsi1_word1(buffer[8]) loro_center_downmix_level, \
downmix_mode, ltrt_center_downmix_level, ltrt_surround_downmix_level = ext_bsi1_word2(buffer[9]) loro_surround_downmix_level = ext_bsi1_word1(buffer[8])
surround_ex_mode, dolby_headphone_encoded, ad_converter_type = ext_bsi2_word1(buffer[10]) downmix_mode, ltrt_center_downmix_level, \
ltrt_surround_downmix_level = ext_bsi1_word2(buffer[9])
surround_ex_mode, dolby_headphone_encoded, \
ad_converter_type = ext_bsi2_word1(buffer[10])
ddplus_reserved2(buffer[11:14]) ddplus_reserved2(buffer[11:14])
compression = compr1(buffer[14]) compression = compr1(buffer[14])
@@ -494,8 +500,9 @@ class DolbyAtmosMetadata:
@classmethod @classmethod
def load(cls, data: bytes): def load(cls, data: bytes):
assert len(data) == cls.SEGMENT_LENGTH, "DolbyAtmosMetadata segment "\ assert len(data) == cls.SEGMENT_LENGTH, ("DolbyAtmosMetadata segment "
"is incorrect length, expected %i actual was %i" % (cls.SEGMENT_LENGTH, len(data)) "is incorrect length, "
"expected %i actual was %i") % (cls.SEGMENT_LENGTH, len(data))
h = BytesIO(data) h = BytesIO(data)
@@ -513,7 +520,9 @@ class DolbyAtmosMetadata:
warp_mode = a_val & 0x7 warp_mode = a_val & 0x7
return DolbyAtmosMetadata(tool_name=toolname, return DolbyAtmosMetadata(tool_name=toolname,
tool_version=(major, minor, fix), warp_mode=DolbyAtmosMetadata.WarpMode(warp_mode)) tool_version=(major, minor, fix),
warp_mode=DolbyAtmosMetadata\
.WarpMode(warp_mode))
@dataclass @dataclass
@@ -521,7 +530,8 @@ class DolbyAtmosSupplementalMetadata:
""" """
Dolby Atmos supplemental metadata segment. Dolby Atmos supplemental metadata segment.
https://github.com/DolbyLaboratories/dbmd-atmos-parser/blob/master/dbmd_atmos_parse/src/dbmd_atmos_parse.c https://github.com/DolbyLaboratories/dbmd-atmos-parser/blob/
master/dbmd_atmos_parse/src/dbmd_atmos_parse.c
""" """
class BinauralRenderMode(Enum): class BinauralRenderMode(Enum):
@@ -617,7 +627,8 @@ class WavDolbyMetadataReader:
else: else:
seg_size = unpack("<H", h.read(2))[0] seg_size = unpack("<H", h.read(2))[0]
seg_payload = h.read(seg_size) seg_payload = h.read(seg_size)
expected_checksum = WavDolbyMetadataReader.segment_checksum(seg_payload, seg_size) expected_checksum = WavDolbyMetadataReader\
.segment_checksum(seg_payload, seg_size)
checksum = unpack("B", h.read(1))[0] checksum = unpack("B", h.read(1))[0]
segment = seg_payload segment = seg_payload
@@ -628,7 +639,8 @@ class WavDolbyMetadataReader:
elif stype == SegmentType.DolbyAtmosSupplemental: elif stype == SegmentType.DolbyAtmosSupplemental:
segment = DolbyAtmosSupplementalMetadata.load(segment) segment = DolbyAtmosSupplementalMetadata.load(segment)
self.segment_list.append( (stype, checksum == expected_checksum, segment) ) self.segment_list\
.append((stype, checksum == expected_checksum, segment))
def dolby_digital_plus(self) -> List[DolbyDigitalPlusMetadata]: def dolby_digital_plus(self) -> List[DolbyDigitalPlusMetadata]:
""" """