mirror of
https://github.com/iluvcapra/wavinfo.git
synced 2025-12-31 17:00:41 +00:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
edbe748718 | ||
|
|
2019a4ec63 | ||
|
|
fb43838c7d | ||
|
|
4cd58b8ddd | ||
|
|
38dab7723f | ||
|
|
354d88a5b2 | ||
|
|
d8a405b6d2 | ||
|
|
5f7e467fbd | ||
|
|
3377ddb4b9 | ||
|
|
9cd6cf7f12 | ||
|
|
1f8ebe253b | ||
|
|
fe46d1b242 | ||
|
|
b213933ad8 | ||
|
|
7e314f7475 | ||
|
|
b2d6fd3c92 | ||
|
|
c4d8608c8f | ||
|
|
5605b05f9f | ||
|
|
5d71cabda7 | ||
|
|
c2f87b1fef | ||
|
|
3db40d4f12 | ||
|
|
40b30f5bd8 | ||
|
|
048f20c64c | ||
|
|
6a69df2ee8 | ||
|
|
ec327ee76f | ||
|
|
62a34cfee8 | ||
|
|
c966097e7d | ||
|
|
35311e394d | ||
|
|
0633a8685c | ||
|
|
f65665a06c | ||
|
|
261572cff3 | ||
|
|
623a8569fd | ||
|
|
31493f7cf4 | ||
|
|
4809bb4844 | ||
|
|
a76f3b1518 | ||
|
|
b8cb585d50 | ||
|
|
84a76f9c74 | ||
|
|
5a1a12e21e | ||
|
|
06835ffe11 | ||
|
|
1b25b8214d | ||
|
|
cfc1a451bc | ||
|
|
0788613ea3 | ||
|
|
e9e4b4bcbb | ||
|
|
c114eb7cf3 | ||
|
|
4576d65da6 |
13
.coveragerc
13
.coveragerc
@@ -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
42
.github/workflows/python-package.yml
vendored
Normal 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
|
||||||
2
.github/workflows/pythonpublish.yml
vendored
2
.github/workflows/pythonpublish.yml
vendored
@@ -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
3
.idea/.gitignore
generated
vendored
@@ -1,3 +0,0 @@
|
|||||||
|
|
||||||
# Default ignored files
|
|
||||||
/workspace.xml
|
|
||||||
9
.idea/dictionaries/jamiehardt.xml
generated
9
.idea/dictionaries/jamiehardt.xml
generated
@@ -1,9 +0,0 @@
|
|||||||
<component name="ProjectDictionaryState">
|
|
||||||
<dictionary name="jamiehardt">
|
|
||||||
<words>
|
|
||||||
<w>bext</w>
|
|
||||||
<w>ident</w>
|
|
||||||
<w>umid</w>
|
|
||||||
</words>
|
|
||||||
</dictionary>
|
|
||||||
</component>
|
|
||||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
6
.idea/inspectionProfiles/profiles_settings.xml
generated
@@ -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
5
.idea/misc.xml
generated
@@ -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
8
.idea/modules.xml
generated
@@ -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
6
.idea/vcs.xml
generated
@@ -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
6
.idea/wavinfo.iml
generated
@@ -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
107
.idea/workspace.xml
generated
Normal 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>
|
||||||
26
.travis.yml
26
.travis.yml
@@ -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"
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
[](https://travis-ci.com/iluvcapra/wavinfo)
|
|
||||||
[](https://codecov.io/gh/iluvcapra/wavinfo)
|
|
||||||
[](https://wavinfo.readthedocs.io/en/latest/?badge=latest)   [](https://pypi.org/project/wavinfo/) 
|
[](https://wavinfo.readthedocs.io/en/latest/?badge=latest)   [](https://pypi.org/project/wavinfo/) 
|
||||||
|

|
||||||
|
|
||||||
<!--  -->
|
<!--  -->
|
||||||
|
|
||||||
@@ -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
6
metadata.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
"""
|
||||||
|
Wavinfo
|
||||||
|
"""
|
||||||
|
__version__ = '1.7.0'
|
||||||
|
__author__ = 'Jamie Hardt <jamiehardt@gmail.com>'
|
||||||
|
__license__ = "MIT"
|
||||||
19
requirements.txt
Normal file
19
requirements.txt
Normal 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
|
||||||
11
setup.py
11
setup.py
@@ -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'
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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
188
wavinfo/dolby_parser.py
Normal 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...
|
||||||
9
wavinfo/wave_axml_reader.py
Normal file
9
wavinfo/wave_axml_reader.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from lxml import etree as ET
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
from ear.fileio.bw64 import Bw64Reader
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user