This commit is contained in:
Jamie Hardt
2023-11-07 00:10:48 -08:00
parent 6f6a90a262
commit 96f79b5dc7
2 changed files with 134 additions and 245 deletions

View File

@@ -6,12 +6,21 @@
"source": [ "source": [
"# `wavinfo` Demonstration\n", "# `wavinfo` Demonstration\n",
"\n", "\n",
"The entry point for wavinfo is the WavInfoReader class." "The `wavinfo` module allows you to read most of the metadata formats that are available for WAV files."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Opening a WAV file for reading metadata\n",
"\n",
"The entry point for wavinfo is the `WavInfoReader` class:"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 3,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@@ -26,14 +35,32 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Basic WAV Data\n", "Once you have a `WavInfoReader`, you can access different metadata systems or \"scopes.\"\n",
"\n",
"The scopes that are presently supported are: `fmt`, `data`, `ixml`, `bext`, `info`, `adm`, `cues`, and `dolby`. Each of these is an attribute of a `WavInfoReader` object.\n",
"\n",
"Each scope roughly corresponds to a vendor-defined metadata system. Many scopes directly represent a specific file *chunk*, like `fmt` or `ixml`, and some may involve data read from many chunks. Examples of this would include `cues` or `adm`.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Metadata Scopes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `data` and `fmt`: Basic WAV Data\n",
"\n", "\n",
"The length of the file in frames (interleaved samples) and bytes is available, as is the contents of the format chunk." "The length of the file in frames (interleaved samples) and bytes is available, as is the contents of the format chunk."
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": 4,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@@ -42,7 +69,7 @@
"(240239, 1441434)" "(240239, 1441434)"
] ]
}, },
"execution_count": 2, "execution_count": 4,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
@@ -51,9 +78,16 @@
"(info.data.frame_count, info.data.byte_count)" "(info.data.frame_count, info.data.byte_count)"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `fmt` scope allows the client to read metadata from the WAVE format description."
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 5,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@@ -62,7 +96,7 @@
"(48000, 2, 6, 24)" "(48000, 2, 6, 24)"
] ]
}, },
"execution_count": 3, "execution_count": 5,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
@@ -75,29 +109,31 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Broadcast WAV Extension" "### `bext`: Broadcast WAV Extension\n",
"\n",
"The `bext` scope allows the client to access Broadcast-WAV metadata. "
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 6,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"sSPEED=023.976-ND\r\n", "sSPEED=023.976-ND\n",
"sTAKE=1\r\n", "sTAKE=1\n",
"sUBITS=$12311801\r\n", "sUBITS=$12311801\n",
"sSWVER=2.67\r\n", "sSWVER=2.67\n",
"sPROJECT=BMH\r\n", "sPROJECT=BMH\n",
"sSCENE=A101\r\n", "sSCENE=A101\n",
"sFILENAME=A101_1.WAV\r\n", "sFILENAME=A101_1.WAV\n",
"sTAPE=18Y12M31\r\n", "sTAPE=18Y12M31\n",
"sTRK1=MKH516 A\r\n", "sTRK1=MKH516 A\n",
"sTRK2=Boom\r\n", "sTRK2=Boom\n",
"sNOTE=\r\n", "sNOTE=\n",
"\n", "\n",
"----------\n", "----------\n",
"Originator: Sound Dev: 702T S#GR1112089007\n", "Originator: Sound Dev: 702T S#GR1112089007\n",
@@ -105,7 +141,7 @@
"Originator Date: 2018-12-31\n", "Originator Date: 2018-12-31\n",
"Originator Time: 12:40:00\n", "Originator Time: 12:40:00\n",
"Time Reference: 2190940753\n", "Time Reference: 2190940753\n",
"A=PCM,F=48000,W=24,M=stereo,R=48000,T=2 Ch\r\n", "A=PCM,F=48000,W=24,M=stereo,R=48000,T=2 Ch\n",
"\n" "\n"
] ]
} }
@@ -125,12 +161,12 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## iXML Production Recorder Metadata" "### `ixml`: iXML Production Recorder Metadata"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 7,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@@ -156,11 +192,79 @@
] ]
}, },
{ {
"cell_type": "code", "cell_type": "markdown",
"execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [], "source": [
"source": [] "### `cues`: Cues Metadata\n",
"\n",
"Cue time markers are accessible through the `cues` scope. The `each_cue` method returns an iterator that yields a tuple of each cue \"name\" or integer UID, and sample location. "
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Cue ID: 1\n",
"Cue Offset: 29616\n",
"Cue ID: 2\n",
"Cue Offset: 74592\n",
"Cue ID: 3\n",
"Cue Offset: 121200\n"
]
}
],
"source": [
"path = \"../tests/test_files/cue_chunks/STE-000.wav\"\n",
"info = WavInfoReader(path)\n",
"\n",
"for cue in info.cues.each_cue():\n",
" print(f\"Cue ID: {cue[0]}\")\n",
" print(f\"Cue Offset: {cue[1]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are also convenience methods to get the appropriate label and note for a given marker. (Note here also `WavInfoReader`'s facility for overriding default text encodings.)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Cue ID: 1\n",
" Label: Marker 1\n",
" Note: <NO NOTE>\n",
"Cue ID: 2\n",
" Label: Marker 2\n",
" Note: Marker Comment 1\n",
"Cue ID: 3\n",
" Label: Marker 3\n",
" Note: Лорем ипсум долор сит амет, тимеам вивендум хас ет, цу адолесценс дефинитионес еам.\n"
]
}
],
"source": [
"path = \"../tests/test_files/cue_chunks/izotoperx_cues_test.wav\"\n",
"info = WavInfoReader(path, info_encoding=\"utf-8\")\n",
"\n",
"for cue in info.cues.each_cue():\n",
" print(f\"Cue ID: {cue[0]}\")\n",
" label, note = info.cues.label_and_note(cue[0])\n",
" print(f\" Label: {label}\")\n",
" print(f\" Note: {note or '<NO NOTE>'}\")"
]
}, },
{ {
"cell_type": "code", "cell_type": "code",
@@ -172,7 +276,7 @@
], ],
"metadata": { "metadata": {
"kernelspec": { "kernelspec": {
"display_name": "Python 3", "display_name": "Python 3 (ipykernel)",
"language": "python", "language": "python",
"name": "python3" "name": "python3"
}, },
@@ -186,9 +290,9 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.2" "version": "3.11.5"
} }
}, },
"nbformat": 4, "nbformat": 4,
"nbformat_minor": 2 "nbformat_minor": 4
} }

View File

@@ -1,215 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import wavinfo\n",
"import pprint"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"pp = pprint.PrettyPrinter(indent=4)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"path = '../tests/test_files/protools/PT A101_4.A1.wav'\n",
"\n",
"info = wavinfo.WavInfoReader(path)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[ ChunkDescriptor(ident=b'bext', start=20, length=858),\n",
" ChunkDescriptor(ident=b'iXML', start=886, length=5226),\n",
" ChunkDescriptor(ident=b'fmt ', start=6120, length=16),\n",
" ChunkDescriptor(ident=b'data', start=6144, length=864840),\n",
" ChunkDescriptor(ident=b'umid', start=870992, length=24),\n",
" ChunkDescriptor(ident=b'minf', start=871024, length=16),\n",
" ChunkDescriptor(ident=b'regn', start=871048, length=92)]\n"
]
}
],
"source": [
"import wavinfo.wave_parser\n",
"\n",
"with open(path,'rb') as f:\n",
" chunk_tree = wavinfo.wave_parser.parse_chunk(f)\n",
"\n",
"pp.pprint(chunk_tree.children)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00*\\xfd\\xf5\\x0c$\\xe4s\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n",
"000000000000002afdf50c24e47380000000000000000000\n",
"24\n"
]
}
],
"source": [
"with open(path,'rb') as f:\n",
" f.seek( chunk_tree.children[4].start )\n",
" umid_bin = f.read(chunk_tree.children[4].length)\n",
" f.seek( chunk_tree.children[6].start )\n",
" regn_bin = f.read(chunk_tree.children[6].length)\n",
" \n",
"print(umid_bin)\n",
"print(umid_bin.hex())\n",
"print(len(umid_bin))"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<wavinfo.wave_bext_reader.WavBextReader object at 0x10d5f8ac8>\n"
]
}
],
"source": [
"print(info.bext)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00*\\xfd\\xf5\\x0c$\\xe4s\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c3\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00T\\xd5\\xa2\\x82\\x00\\x00\\x00\\x00\\x10PT A101_4.A1.wavGK\\xaa\\xaf\\x7f\\x00\\x00@ }\\x06\\x00`\\x00\\x00'\n",
"01000000000000000000002afdf50c24e473800000000000000000000c330200000000000000000000000000000000000000000054d5a2820000000010505420413130315f342e41312e776176474baaaf7f000040207d0600600000\n",
"92\n"
]
}
],
"source": [
"\n",
"print(regn_bin)\n",
"print(regn_bin.hex())\n",
"print(len(regn_bin))"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{ 'artist': 'Frank Bry',\n",
" 'comment': 'BULLET Impact Plastic LCD TV Screen Shatter Debris 2x',\n",
" 'copyright': '2018 Creative Sound Design, LLC (The Recordist Christmas '\n",
" '2018) www.therecordist.com',\n",
" 'created_date': '2018-11-15',\n",
" 'engineer': None,\n",
" 'genre': 'Bullets',\n",
" 'keywords': None,\n",
" 'product': 'The Recordist Christmas 2018',\n",
" 'software': 'Soundminer',\n",
" 'source': None,\n",
" 'tape': None,\n",
" 'title': None}\n",
"{ 'coding_history': '',\n",
" 'description': 'BULLET Impact Plastic LCD TV Screen Shatter Debris 2x',\n",
" 'loudness_range': None,\n",
" 'loudness_value': None,\n",
" 'max_momentary_loudness': None,\n",
" 'max_shortterm_loudness': None,\n",
" 'max_true_peak': None,\n",
" 'originator': 'TheRecordist',\n",
" 'originator_date': '2018-12-20',\n",
" 'originator_ref': 'aaiAKt3fCGTk',\n",
" 'originator_time': '12:15:37',\n",
" 'time_reference': 57882,\n",
" 'version': 0}\n"
]
}
],
"source": [
"path = '../tests/test_files/BULLET Impact Plastic LCD TV Screen Shatter Debris 2x.wav'\n",
"\n",
"info = wavinfo.WavInfoReader(path)\n",
"\n",
"with open(path,'rb') as f:\n",
" chunk_tree = wavinfo.wave_parser.parse_chunk(f)\n",
" \n",
"pp.pprint(info.info.to_dict())\n",
"pp.pprint(info.bext.to_dict())"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}