44 Commits
v1.6 ... v1.7.0

Author SHA1 Message Date
Jamie Hardt
edbe748718 Update metadata.py 2022-11-15 11:17:02 -08:00
Jamie Hardt
2019a4ec63 Update pythonpublish.yml
Switched to pypi token authentication
2022-11-15 11:12:00 -08:00
Jamie Hardt
fb43838c7d Update README.md 2022-11-15 11:06:28 -08:00
Jamie Hardt
4cd58b8ddd Delete .travis.yml 2022-11-15 11:04:30 -08:00
Jamie Hardt
38dab7723f Update python-package.yml
Changed action name
2022-11-15 11:02:14 -08:00
Jamie Hardt
354d88a5b2 Update python-package.yml
Removed 3.6 and 3.7 from test grid
2022-11-15 10:58:51 -08:00
Jamie Hardt
d8a405b6d2 Update setup.py
Dropping 3.6 and 3.7, there seems to be a lxml conflict with its dependencies on numpy.
2022-11-15 10:58:12 -08:00
Jamie Hardt
5f7e467fbd Update python-package.yml 2022-11-15 10:56:11 -08:00
Jamie Hardt
3377ddb4b9 Updated ear to latest version 2022-11-15 10:53:12 -08:00
Jamie Hardt
9cd6cf7f12 Relieved requirements for attrs package 2022-11-15 10:51:02 -08:00
Jamie Hardt
1f8ebe253b Updated requirements for pytest 2022-11-15 10:49:18 -08:00
Jamie Hardt
fe46d1b242 Update python-package.yml 2022-11-15 10:37:04 -08:00
Jamie Hardt
b213933ad8 Update README.md 2022-11-15 10:35:59 -08:00
Jamie Hardt
7e314f7475 Update README.md 2022-11-15 10:34:41 -08:00
Jamie Hardt
b2d6fd3c92 Update README.md 2022-11-15 10:34:07 -08:00
Jamie Hardt
c4d8608c8f Create python-package.yml 2022-11-15 10:33:36 -08:00
Jamie Hardt
5605b05f9f Update README.md 2022-11-15 10:32:11 -08:00
Jamie Hardt
5d71cabda7 Delete .coveragerc 2022-11-15 10:30:31 -08:00
Jamie Hardt
c2f87b1fef Update README.md 2022-11-15 10:29:58 -08:00
Jamie Hardt
3db40d4f12 Added dosctring 2022-11-13 22:43:22 +00:00
Jamie Hardt
40b30f5bd8 Merge pull request #11 from soundappraisal/master
Make wavinfo work with filehandles.
2022-11-03 18:03:51 -07:00
Ronald van Elburg
048f20c64c Move version and author information to separate file. The current location leads to problems with dependencies which are only resolved after running pip. 2022-10-17 15:18:24 +02:00
Ronald van Elburg
6a69df2ee8 Move version and author information to separate file. The current location leads to problems with dependencies which are only resolved after running pip. 2022-10-17 13:28:28 +02:00
Ronald van Elburg
ec327ee76f Move version and author information to separate file. The current location leads to problems with dependencies which are only resolved after running pip. 2022-10-17 13:25:41 +02:00
Ronald van Elburg
62a34cfee8 Make it possible to pass file handles or in memory wav data to wavinfo. Some of the fields for the __repr__ where not available for files. For these the url member is set to "about:blank", and the self.path to the representation of the incoming object. The formating in __repr__ turned out to be broken, with fixing that we also had to fix the test on __repr__. 2022-08-30 11:42:47 +02:00
Jamie Hardt
c966097e7d Nudged version to 1.6.3 2022-01-06 11:45:39 -08:00
Jamie Hardt
35311e394d Merge branch 'master' of https://github.com/iluvcapra/wavinfo 2022-01-06 11:13:43 -08:00
Jamie Hardt
0633a8685c Deleted .idea dir 2022-01-06 11:11:33 -08:00
Jamie Hardt
f65665a06c Delete python-package.yml 2022-01-06 11:08:48 -08:00
Jamie Hardt
261572cff3 Delete python-package-conda.yml 2022-01-06 11:06:47 -08:00
Jamie Hardt
623a8569fd Create python-package.yml 2022-01-06 11:06:31 -08:00
Jamie Hardt
31493f7cf4 Create python-package-conda.yml 2022-01-06 11:05:17 -08:00
Jamie Hardt
4809bb4844 Bumped lxml requirements re CVE-2021-43818 2022-01-06 11:01:28 -08:00
Jamie Hardt
a76f3b1518 Fixed idea interpreter again 2020-12-09 20:16:35 -08:00
Jamie Hardt
b8cb585d50 idea target stuff 2020-12-09 19:47:23 -08:00
Jamie Hardt
84a76f9c74 Update __init__.py
Version 1.6.2
2020-10-19 21:29:40 -07:00
Jamie Hardt
5a1a12e21e Update __init__.py
Version 1.6.1
2020-10-19 21:28:58 -07:00
Jamie Hardt
06835ffe11 Update setup.py
Added 3.9
2020-10-19 21:26:22 -07:00
Jamie Hardt
1b25b8214d Update .travis.yml
Added 3.9
2020-10-19 21:25:44 -07:00
Jamie Hardt
cfc1a451bc Update .travis.yml 2020-10-08 21:37:50 -07:00
Jamie Hardt
0788613ea3 Update setup.py 2020-10-08 21:37:01 -07:00
Jamie Hardt
e9e4b4bcbb Made quick fixes of these to get tests working 2020-10-08 21:31:32 -07:00
Jamie Hardt
c114eb7cf3 Create dolby_parser.py 2020-08-27 13:37:49 -07:00
Jamie Hardt
4576d65da6 Update wave_reader.py
Removed needless sys import
2020-08-21 22:39:52 -07:00
22 changed files with 428 additions and 120 deletions

View File

@@ -1,13 +0,0 @@
[run]
branch = True
source = wavinfo
[report]
exclude_lines =
if self.debug:
pragma: no cover
raise NotImplementedError
if __name__ == .__main__.:
ignore_errors = True
omit =
tests/*

42
.github/workflows/python-package.yml vendored Normal file
View File

@@ -0,0 +1,42 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Python Lint and Test
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10"]
steps:
- uses: actions/checkout@v2.5.0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4.3.0
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Setup FFmpeg
uses: FedericoCarboni/setup-ffmpeg@v2
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest

View File

@@ -19,7 +19,7 @@ jobs:
pip install setuptools wheel twine lxml pip install setuptools wheel twine lxml
- name: Build and publish - name: Build and publish
env: env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: | run: |
python setup.py sdist bdist_wheel python setup.py sdist bdist_wheel

3
.idea/.gitignore generated vendored
View File

@@ -1,3 +0,0 @@
# Default ignored files
/workspace.xml

View File

@@ -1,9 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="jamiehardt">
<words>
<w>bext</w>
<w>ident</w>
<w>umid</w>
</words>
</dictionary>
</component>

View File

@@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

5
.idea/misc.xml generated
View File

@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8 (wavinfo)" project-jdk-type="Python SDK" /> <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (wavinfo)" project-jdk-type="Python SDK" />
<component name="PyPackaging">
<option name="earlyReleasesAsUpgrades" value="true" />
</component>
</project> </project>

8
.idea/modules.xml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/wavinfo.iml" filepath="$PROJECT_DIR$/.idea/wavinfo.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

6
.idea/wavinfo.iml generated
View File

@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4"> <module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" /> <content url="file://$MODULE_DIR$">
<orderEntry type="jdk" jdkName="Python 3.8 (wavinfo)" jdkType="Python SDK" /> <excludeFolder url="file://$MODULE_DIR$/venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.7 (wavinfo)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
</module> </module>

107
.idea/workspace.xml generated Normal file
View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="fb29ad56-fffe-478f-9c0e-1718aa04342e" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/.idea/dictionaries/jamiehardt.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dictionaries/jamiehardt.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/wavinfo.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/wavinfo.iml" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FavoritesManager">
<favorites_list name="wavinfo" />
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Python Script" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
<option name="UPDATE_TYPE" value="MERGE" />
</component>
<component name="ProjectId" id="1VtfP9ukGK4GNIXS2m0hRLG9d7w" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
<option name="showMembers" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="TODO_SCOPE" value="Project Files" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="project-level" UseSingleDictionary="true" transferred="true" />
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="fb29ad56-fffe-478f-9c0e-1718aa04342e" name="Default Changelist" comment="" />
<created>1578077284420</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1578077284420</updated>
</task>
<servers />
</component>
<component name="Vcs.Log.History.Properties">
<option name="COLUMN_ORDER">
<list>
<option value="0" />
<option value="2" />
<option value="3" />
<option value="1" />
</list>
</option>
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
<option name="oldMeFiltersMigrated" value="true" />
</component>
<component name="WindowStateProjectService">
<state x="655" y="287" key="#com.intellij.openapi.updateSettings.impl.PluginUpdateInfoDialog" timestamp="1598547965709">
<screen x="0" y="0" width="1920" height="1080" />
</state>
<state x="655" y="287" key="#com.intellij.openapi.updateSettings.impl.PluginUpdateInfoDialog/1920.0.1920.1080/0.0.1920.1080/3840.0.1920.1080@0.0.1920.1080" timestamp="1598547965709" />
<state x="0" y="0" key="#com.intellij.refactoring.rename.AutomaticRenamingDialog" timestamp="1598555737671">
<screen x="0" y="0" width="1920" height="1080" />
</state>
<state x="0" y="0" key="#com.intellij.refactoring.rename.AutomaticRenamingDialog/1920.0.1920.1080/0.0.1920.1080/3840.0.1920.1080@0.0.1920.1080" timestamp="1598555737671" />
<state x="476" y="183" key="SettingsEditor" timestamp="1598548365517">
<screen x="0" y="0" width="1920" height="1080" />
</state>
<state x="476" y="183" key="SettingsEditor/1920.0.1920.1080/0.0.1920.1080/3840.0.1920.1080@0.0.1920.1080" timestamp="1598548365517" />
<state x="114" y="123" width="1706" height="842" key="com.intellij.history.integration.ui.views.FileHistoryDialog" timestamp="1597689482054">
<screen x="0" y="0" width="1920" height="1080" />
</state>
<state x="114" y="123" width="1706" height="842" key="com.intellij.history.integration.ui.views.FileHistoryDialog/1920.0.1920.1080/0.0.1920.1080/3840.0.1920.1080@0.0.1920.1080" timestamp="1597689482054" />
<state x="577" y="376" key="com.intellij.ide.util.TipDialog" timestamp="1601767353495">
<screen x="0" y="0" width="1920" height="1080" />
</state>
<state x="577" y="376" key="com.intellij.ide.util.TipDialog/1920.0.1920.1080/0.0.1920.1080/3840.0.1920.1080@0.0.1920.1080" timestamp="1598550975228" />
<state x="577" y="376" key="com.intellij.ide.util.TipDialog/1920.0.1920.1080/0.0.1920.1080@0.0.1920.1080" timestamp="1601767353495" />
<state x="772" y="468" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2" timestamp="1598547948993">
<screen x="0" y="0" width="1920" height="1080" />
</state>
<state x="772" y="468" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2/1920.0.1920.1080/0.0.1920.1080/3840.0.1920.1080@0.0.1920.1080" timestamp="1598547948993" />
<state x="632" y="254" width="670" height="676" key="search.everywhere.popup" timestamp="1598554315633">
<screen x="0" y="0" width="1920" height="1080" />
</state>
<state x="632" y="254" width="670" height="676" key="search.everywhere.popup/1920.0.1920.1080/0.0.1920.1080/3840.0.1920.1080@0.0.1920.1080" timestamp="1598554315633" />
</component>
</project>

View File

@@ -1,26 +0,0 @@
dist: xenial
language: python
python:
# - "2.7"
- "3.5"
- "3.6"
- "3.7"
- "3.8"
script:
- "gunzip tests/test_files/rf64/*.gz"
- "python setup.py test"
- "python -m pytest tests/ -v --cov wavinfo --cov-report term-missing"
before_install:
- "sudo apt-get update"
- "sudo add-apt-repository universe"
- "sudo apt-get install -y ffmpeg"
- "pip install pytest"
- "pip install lxml"
- "pip install coverage"
- "pip install codecov"
- "pip install pytest-cov==2.5.0"
- "pip install coverage==4.4"
install:
- "pip install setuptools"
after_success:
- "codecov"

View File

@@ -1,6 +1,5 @@
[![Build Status](https://travis-ci.com/iluvcapra/wavinfo.svg?branch=master)](https://travis-ci.com/iluvcapra/wavinfo)
[![codecov](https://codecov.io/gh/iluvcapra/wavinfo/branch/master/graph/badge.svg)](https://codecov.io/gh/iluvcapra/wavinfo)
[![Documentation Status](https://readthedocs.org/projects/wavinfo/badge/?version=latest)](https://wavinfo.readthedocs.io/en/latest/?badge=latest) ![](https://img.shields.io/github/license/iluvcapra/wavinfo.svg) ![](https://img.shields.io/pypi/pyversions/wavinfo.svg) [![](https://img.shields.io/pypi/v/wavinfo.svg)](https://pypi.org/project/wavinfo/) ![](https://img.shields.io/pypi/wheel/wavinfo.svg) [![Documentation Status](https://readthedocs.org/projects/wavinfo/badge/?version=latest)](https://wavinfo.readthedocs.io/en/latest/?badge=latest) ![](https://img.shields.io/github/license/iluvcapra/wavinfo.svg) ![](https://img.shields.io/pypi/pyversions/wavinfo.svg) [![](https://img.shields.io/pypi/v/wavinfo.svg)](https://pypi.org/project/wavinfo/) ![](https://img.shields.io/pypi/wheel/wavinfo.svg)
![Lint and Test](https://github.com/iluvcapra/wavinfo/actions/workflows/python-package.yml/badge.svg)
<!-- ![Test](https://github.com/iluvcapra/wavinfo/workflows/Upload%20Python%20Package/badge.svg) --> <!-- ![Test](https://github.com/iluvcapra/wavinfo/workflows/Upload%20Python%20Package/badge.svg) -->
@@ -60,10 +59,6 @@ The length of the file in frames (interleaved samples) and bytes is available, a
>>> (48000, 2, 6, 24) >>> (48000, 2, 6, 24)
``` ```
## Platform Lifecycle Stuff
Python 3.5 support is deprecated.
## Other Resources ## Other Resources
* For other file formats and ID3 decoding, look at [audio-metadata](https://github.com/thebigmunch/audio-metadata). * For other file formats and ID3 decoding, look at [audio-metadata](https://github.com/thebigmunch/audio-metadata).

6
metadata.py Normal file
View File

@@ -0,0 +1,6 @@
"""
Wavinfo
"""
__version__ = '1.7.0'
__author__ = 'Jamie Hardt <jamiehardt@gmail.com>'
__license__ = "MIT"

19
requirements.txt Normal file
View File

@@ -0,0 +1,19 @@
attrs==21.4.0
ear==2.1.0
enum34==1.1.10
exceptiongroup==1.0.4
iniconfig==1.1.1
lxml==4.9.1
multipledispatch==0.6.0
numpy==1.23.3
packaging==21.3
pluggy==1.0.0
pyparsing==3.0.9
pytest==7.2.0
ruamel.yaml==0.17.21
ruamel.yaml.clib==0.2.6
scipy==1.9.1
six==1.16.0
style==1.1.0
tomli==2.0.1
update==0.0.1

View File

@@ -1,5 +1,5 @@
from setuptools import setup from setuptools import setup
from wavinfo import __author__, __license__, __version__ from metadata import __author__, __license__, __version__
with open("README.md", "r") as fh: with open("README.md", "r") as fh:
long_description = fh.read() long_description = fh.read()
@@ -26,12 +26,11 @@ setup(name='wavinfo',
'License :: OSI Approved :: MIT License', 'License :: OSI Approved :: MIT License',
'Topic :: Multimedia', 'Topic :: Multimedia',
'Topic :: Multimedia :: Sound/Audio', 'Topic :: Multimedia :: Sound/Audio',
"Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.10"],
"Programming Language :: Python :: 3.8"],
keywords='waveform metadata audio ebu smpte avi library film tv editing editorial', keywords='waveform metadata audio ebu smpte avi library film tv editing editorial',
install_requires=['lxml'], install_requires=['lxml', 'ear'],
entry_points={ entry_points={
'console_scripts': [ 'console_scripts': [
'wavinfo = wavinfo.__main__:main' 'wavinfo = wavinfo.__main__:main'

View File

@@ -12,7 +12,7 @@ class TestWaveInfo(TestCase):
def test_sanity(self): def test_sanity(self):
for wav_file in all_files(): for wav_file in all_files():
info = wavinfo.WavInfoReader(wav_file) info = wavinfo.WavInfoReader(wav_file)
self.assertEqual(info.__repr__(), 'WavInfoReader(%s, %s, %s)'.format(wav_file, 'latin_1', 'ascii')) self.assertEqual(info.__repr__(), 'WavInfoReader({}, latin_1, ascii)'.format(os.path.abspath(wav_file)))
self.assertIsNotNone(info) self.assertIsNotNone(info)
def test_fmt_against_ffprobe(self): def test_fmt_against_ffprobe(self):

View File

@@ -7,6 +7,3 @@ Go to the documentation for wavinfo.WavInfoReader for more information.
from .wave_reader import WavInfoReader from .wave_reader import WavInfoReader
from .riff_parser import WavInfoEOFError from .riff_parser import WavInfoEOFError
__version__ = '1.6'
__author__ = 'Jamie Hardt <jamiehardt@gmail.com>'
__license__ = "MIT"

188
wavinfo/dolby_parser.py Normal file
View File

@@ -0,0 +1,188 @@
# Dolby RMU Metadata per EBU Tech 3285 Supp 6
#
# https://tech.ebu.ch/docs/tech/tech3285s6.pdf
#
from struct import unpack, calcsize
from enum import (Enum, IntEnum)
CHUNK_IDENT = "dbmd"
DOLBY_VERSION = "1.0.0.6"
class _DPPGenericDownMixLevel(Enum):
PLUS_3DB = 0b000
PLUS_1_5DB = 0b001
UNITY = 0b010
MINUS_1_5DB = 0b011
MINUS_3DB = 0b100
MINUS_4_5DB = 0b101
MINUS_6DB = 0b110
MUTE = 0b111
class DPPDolbySurroundEncodingMode(Enum):
RESERVED = 0b11
IN_USE = 0b10
NOT_IN_USE = 0b01
NOT_INDICATED = 0b00
# DPPLoRoDownMixCenterLevel
# DPPLtRtCenterMixLevel
# DPPLtRtSurroundMixLevel
class DolbyMetadataSegmentTypes(IntEnum):
END_MARKER = 0
DOLBY_E_METADATA = 1
DOLBY_DIGITAL_METADATA = 3
DOLBY_DIGITAL_PLUS_METADATA = 7
AUDIO_INFO = 8
class DDPBitStreamMode(Enum):
"""
Dolby Digital Plus `bsmod` field
§ 4.3.2.2
"""
COMPLETE_MAIN = 0b000
MUSIC_AND_EFFECTS = 0b001
VISUALLY_IMPAIRED = 0b010
HEARING_IMPAIRED = 0b011
DIALOGUE_ONLY = 0b100
COMMENTARY = 0b101
EMERGENCY = 0b110
VOICEOVER = 0b111 # if audioconfigmode is 1_0
KARAOKE = 0b1000 # if audioconfigmode is not 1_0
class DDPAudioCodingMode(Enum):
"""
Dolby Digital Plus `acmod` field
§ 4.3.2.3
"""
RESERVED = 0b000
CH_ORD_1_0 = 0b001
CH_ORD_2_0 = 0b010
CH_ORD_3_0 = 0b011
CH_ORD_2_1 = 0b100
CH_ORD_3_1 = 0b101
CH_ORD_2_2 = 0b110
CH_ORD_3_2 = 0b111
class DPPCenterDownMixLevel(Enum):
"""
§ 4.3.3.1
"""
DOWN_3DB = 0b00
DOWN_45DB = 0b01
DOWN_6DB = 0b10
RESERVED = 0b11
class DPPSurroundDownMixLevel(Enum):
"""
Dolby Digital Plus `surmixlev` field
§ 4.3.3.2
"""
DOWN_3DB = 0b00
DOWN_6DB = 0b01
MUTE = 0b10
RESERVED = 0b11
class DPPLanguageCode(Enum):
"""
§ 4.3.4.1 , 4.3.5 (always 0xFF)
"""
# this is removed in https://www.atsc.org/wp-content/uploads/2015/03/A52-201212-17.pdf § 5.4.2.12
# It should just be 0xff
pass
class DPPMixLevel(int):
pass
class DPPDialnormLevel(int):
pass
class DPPRoomTime(Enum):
"""
`roomtyp` 4.3.6.3
"""
NOT_INDICATED = 0b00
LARGE_ROOM_X_CURVE = 0b01
SMALL_ROOM_FLAT_CURVE = 0b10
RESERVED = 0b11
class DPPPreferredDownMixMode(Enum):
"""
§ 4.3.8.1
"""
NOT_INDICATED = 0b00
PRO_LOGIC = 0b01
STEREO = 0b10
PRO_LOGIC_2 = 0b11
# class DPPLtRtCenterMixLevel(_DPPGenericDownMixLevel):
# pass
#
#
# class DPPLtRtSurroundMixLevel(_DPPGenericDownMixLevel):
# pass
#
#
# class DPPSurroundEXMode(_DPPGenericInUseIndicator):
# pass
#
#
# class DPPHeadphoneMode(_DPPGenericInUseIndicator):
# pass
class DPPADConverterType(Enum):
STANDARD = 0
HDCD = 1
class DDPStreamDependency(Enum):
"""
Encodes `ddplus_info1.stream_type` field § 4.3.12.1
"""
INDEPENDENT = 0
DEPENDENT = 1
INDEPENDENT_FROM_DOLBY_DIGITAL = 2
RESERVED = 3
class DDPDataRate(int):
pass
class DPPRFCompressionProfile(Enum):
NONE = 0
FILM_STANDARD = 1
FILM_LIGHT = 2
MUSIC_STANDARD = 3
MUSIC_LIGHT = 4
SPEECH = 5
class DolbyDigitalPlusMetadata:
@classmethod
def parse(cls, binary_data):
binary_format = "<BBxxBBBBBBBBBBBBBxxxBxxxxxH"
assert len(binary_data >= calcsize(binary_format))
fields = unpack(binary_format, binary_data)
class WavDolbyReader:
def __init__(self, dolby_data):
version, remainder = unpack("<U", dolby_data[0]), dolby_data[1:]
## FIXME continues...

View File

@@ -0,0 +1,9 @@
from lxml import etree as ET
from collections import namedtuple
from ear.fileio.bw64 import Bw64Reader

View File

@@ -1,4 +1,3 @@
# import xml.etree.ElementTree as ET
from lxml import etree as ET from lxml import etree as ET
import io import io
from collections import namedtuple from collections import namedtuple

View File

@@ -1,7 +1,6 @@
#-*- coding: utf-8 -*- #-*- coding: utf-8 -*-
import struct import struct
import os import os
import sys
from collections import namedtuple from collections import namedtuple
import pathlib import pathlib
@@ -28,43 +27,57 @@ class WavInfoReader:
""" """
Create a new reader object. Create a new reader object.
:param path: A filesystem path to the wav file you wish to probe. :param path:
A filesystem path to the wav file you wish to probe or a
file handle to an open file.
:param info_encoding: The text encoding of the INFO metadata fields. :param info_encoding:
latin_1/Win CP1252 has always been a pretty good guess for this. The text encoding of the INFO metadata fields.
latin_1/Win CP1252 has always been a pretty good guess for this.
:param bext_encoding: The text encoding to use when decoding the string :param bext_encoding:
fields of the Broadcast-WAV extension. Per EBU 3285 this is ASCII The text encoding to use when decoding the string
but this parameter is available to you if you encounter a weirdo. fields of the Broadcast-WAV extension. Per EBU 3285 this is ASCII
but this parameter is available to you if you encounter a weirdo.
""" """
absolute_path = os.path.abspath(path)
#: `file://` url for the file.
self.url = pathlib.Path(absolute_path).as_uri()
# for __repr__()
self.path = absolute_path
self.info_encoding = info_encoding self.info_encoding = info_encoding
self.bext_encoding = bext_encoding self.bext_encoding = bext_encoding
if hasattr(path, 'read'):
self.get_wav_info(path)
self.url = 'about:blank'
self.path = repr(path)
else:
absolute_path = os.path.abspath(path)
with open(path, 'rb') as f: #: `file://` url for the file.
chunks = parse_chunk(f) self.url = pathlib.Path(absolute_path).as_uri()
self.main_list = chunks.children # for __repr__()
f.seek(0) self.path = absolute_path
with open(path, 'rb') as f:
self.get_wav_info(f)
def get_wav_info(self, wavfile):
chunks = parse_chunk(wavfile)
#: :class:`wavinfo.wave_reader.WavAudioFormat` self.main_list = chunks.children
self.fmt = self._get_format(f) wavfile.seek(0)
#: :class:`wavinfo.wave_bext_reader.WavBextReader` with Broadcast-WAV metadata #: :class:`wavinfo.wave_reader.WavAudioFormat`
self.bext = self._get_bext(f, encoding=bext_encoding) self.fmt = self._get_format(wavfile)
#: :class:`wavinfo.wave_ixml_reader.WavIXMLFormat` with iXML metadata #: :class:`wavinfo.wave_bext_reader.WavBextReader` with Broadcast-WAV metadata
self.ixml = self._get_ixml(f) self.bext = self._get_bext(wavfile, encoding=self.bext_encoding)
#: :class:`wavinfo.wave_info_reader.WavInfoChunkReader` with RIFF INFO metadata #: :class:`wavinfo.wave_ixml_reader.WavIXMLFormat` with iXML metadata
self.info = self._get_info(f, encoding=info_encoding) self.ixml = self._get_ixml(wavfile)
self.data = self._describe_data()
#: :class:`wavinfo.wave_info_reader.WavInfoChunkReader` with RIFF INFO metadata
self.info = self._get_info(wavfile, encoding=self.info_encoding)
self.data = self._describe_data()
def _find_chunk_data(self, ident, from_stream, default_none=False): def _find_chunk_data(self, ident, from_stream, default_none=False):
top_chunks = (chunk for chunk in self.main_list if type(chunk) is ChunkDescriptor and chunk.ident == ident) top_chunks = (chunk for chunk in self.main_list if type(chunk) is ChunkDescriptor and chunk.ident == ident)
@@ -147,4 +160,4 @@ class WavInfoReader:
yield 'info', key, info_dict[key] yield 'info', key, info_dict[key]
def __repr__(self): def __repr__(self):
return 'WavInfoReader(%s, %s, %s)'.format(self.path, self.info_encoding, self.bext_encoding) return 'WavInfoReader({}, {}, {})'.format(self.path, self.info_encoding, self.bext_encoding)