Documentation

This commit is contained in:
Jamie Hardt
2019-01-04 19:58:03 -08:00
parent 9e259e9d6c
commit 83bf656ad3
8 changed files with 223 additions and 132 deletions

View File

@@ -2,28 +2,12 @@ import struct
class WavBextReader:
def __init__(self,bext_data,encoding):
# description[256]
# originator[32]
# originatorref[32]
# originatordate[10] "YYYY:MM:DD"
# originatortime[8] "HH:MM:SS"
# lowtimeref U32
# hightimeref U32
# version U16
#
# V1 field
# umid[64]
#
# V2 fields
# loudnessvalue S16 (in LUFS*100)
# loudnessrange S16 (in LUFS*100)
# maxtruepeak S16 (in dbTB*100)
# maxmomentaryloudness S16 (LUFS*100)
# maxshorttermloudness S16 (LUFS*100)
#
# reserved[180]
# codinghistory []
"""
Read Broadcast-WAV extended metadata.
:param best_data: The bytes-like data.
"param encoding: The encoding to use when decoding the text fields of the
BEXT metadata scope. According to EBU Rec 3285 this shall be ASCII.
"""
packstring = "<256s"+ "32s" + "32s" + "10s" + "8s" + "QH" + "64s" + "hhhhh" + "180s"
rest_starts = struct.calcsize(packstring)
@@ -39,20 +23,38 @@ class WavBextReader:
decoded = trimmed.decode(encoding)
return decoded
#: Description. A free-text field up to 256 characters long.
self.description = sanatize_bytes(unpacked[0])
#: Originator. Usually the name of the encoding application, sometimes
#: a artist name.
self.originator = sanatize_bytes(unpacked[1])
#: A unique identifer for the file, a serial number.
self.originator_ref = sanatize_bytes(unpacked[2])
#: Date of the recording, in the format YYY-MM-DD
self.originator_date = sanatize_bytes(unpacked[3])
#: Time of the recording, in the format HH:MM:SS.
self.originator_time = sanatize_bytes(unpacked[4])
#: The sample offset of the start of the file relative to an
#: epoch, usually midnight the day of the recording.
self.time_reference = unpacked[5]
self.version = unpacked[6]
self.umid = None
self.loudness_value = None
self.loudness_range = None
self.max_true_peak = None
self.max_momentary_loudness = None
self.max_shortterm_loudness = None
#: A variable-length text field containing a list of processes and
#: and conversions performed on the file.
self.coding_history = sanatize_bytes(bext_data[rest_starts:])
#: BEXT version.
self.version = unpacked[6]
#: SMPTE 330M UMID of this audio file, 64 bytes are allocated though the UMID
#: may only be 32 bytes long.
self.umid = None
#: EBU R128 Integrated loudness, in LUFS.
self.loudness_value = None
#: EBU R128 Loudness rante, in LUFS.
self.loudness_range = None
#: True peak level, in dBFS TP
self.max_true_peak = None
#: EBU R128 Maximum momentary loudness, in LUFS
self.max_momentary_loudness = None
#: EBU R128 Maximum short-term loudness, in LUFS.
self.max_shortterm_loudness = None
if self.version > 0:
self.umid = unpacked[7]

View File

@@ -14,18 +14,30 @@ class WavInfoChunkReader:
self.info_chunk = next((chunk for chunk in list_chunks \
if chunk.signature == b'INFO'), None)
#: 'ICOP' Copyright
self.copyright = self._get_field(f,b'ICOP')
#: 'IPRD' Product
self.product = self._get_field(f,b'IPRD')
#: 'IGNR' Genre
self.genre = self._get_field(f,b'IGNR')
#: 'IART' Artist, composer, author
self.artist = self._get_field(f,b'IART')
#: 'ICMT' Comment
self.comment = self._get_field(f,b'ICMT')
#: 'ISFT' Software, encoding application
self.software = self._get_field(f,b'ISFT')
#: 'ICRD' Created date
self.created_date = self._get_field(f,b'ICRD')
#: 'IENG' Engineer
self.engineer = self._get_field(f,b'IENG')
#: 'IKEY' Keywords, keyword list
self.keywords = self._get_field(f,b'IKEY')
#: 'INAM' Name, title
self.title = self._get_field(f,b'INAM')
#: 'ISRC' Source
self.source = self._get_field(f,b'ISRC')
#: 'TAPE' Tape
self.tape = self._get_field(f,b'TAPE')
@@ -43,6 +55,9 @@ class WavInfoChunkReader:
def to_dict(self):
"""
A dictionary with all of the key/values read from the INFO scope.
"""
return {'copyright': self.copyright,
'product': self.product,
'genre': self.genre,

View File

@@ -3,9 +3,13 @@ import io
class WavIXMLFormat:
"""
iXML recorder metadata, as defined by iXML 2.0
iXML recorder metadata.
"""
def __init__(self, xml):
"""
Parse iXML.
:param xml: A bytes-like object containing the iXML payload.
"""
self.source = xml
xmlBytes = io.BytesIO(xml)
self.parsed = ET.parse(xmlBytes)
@@ -17,26 +21,45 @@ class WavIXMLFormat:
@property
def project(self):
"""
The project/film name entered for the recording.
"""
return self._get_text_value("PROJECT")
@property
def scene(self):
"""
Scene/slate.
"""
return self._get_text_value("SCENE")
@property
def take(self):
"""
Take number.
"""
return self._get_text_value("TAKE")
@property
def tape(self):
"""
Tape name.
"""
return self._get_text_value("TAPE")
@property
def family_uid(self):
"""
The globally-unique ID for this file family. This may be in the format
of a GUID, or an EBU Rec 9 source identifier, or some other dumb number.
"""
return self._get_text_value("FILE_SET/FAMILY_UID")
@property
def family_name(self):
"""
The name of this file's file family.
"""
return self._get_text_value("FILE_SET/FAMILY_NAME")