mirror of
https://github.com/iluvcapra/wavinfo.git
synced 2025-12-31 17:00:41 +00:00
Compare commits
10 Commits
maint-poet
...
feature-sm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
299f79aeb3 | ||
|
|
a46590df29 | ||
|
|
c6f66b2d6e | ||
|
|
b8617a35e2 | ||
|
|
8a755b4466 | ||
|
|
f0353abd4e | ||
|
|
6304666d11 | ||
|
|
d2b0c68dd2 | ||
|
|
a0a9c38cb4 | ||
|
|
f68eea4cd9 |
@@ -31,6 +31,7 @@ it is not supported, please submit an issue!
|
||||
and Dolby Atmos `dbmd` metadata for re-renders and mixdowns.
|
||||
* Wave embedded [cue markers][cues], cue marker labels, notes and timed ranges as used
|
||||
by Zoom, iZotope RX, etc.
|
||||
* Wave embedded [sampler][smpl] and sample loop metadata.
|
||||
* The [wav format][format] is also parsed, so you can access the basic sample rate
|
||||
and channel count information.
|
||||
|
||||
@@ -38,6 +39,7 @@ it is not supported, please submit an issue!
|
||||
[format]:https://wavinfo.readthedocs.io/en/latest/classes.html#wavinfo.wave_reader.WavAudioFormat
|
||||
[cues]:https://wavinfo.readthedocs.io/en/latest/scopes/cue.html
|
||||
[bext]:https://wavinfo.readthedocs.io/en/latest/scopes/bext.html
|
||||
[smpl]:https://wavinfo.readthedocs.io/en/latest/scopes/smpl.html
|
||||
[smpte_330m2011]:https://wavinfo.readthedocs.io/en/latest/scopes/bext.html#wavinfo.wave_bext_reader.WavBextReader.umid
|
||||
[adm]:https://wavinfo.readthedocs.io/en/latest/scopes/adm.html
|
||||
[ebu3285s6]:https://wavinfo.readthedocs.io/en/latest/scopes/dolby.html
|
||||
|
||||
@@ -12,24 +12,25 @@
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
import importlib
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.abspath('../..'))
|
||||
sys.path.insert(0, os.path.abspath("../../.."))
|
||||
print(sys.path)
|
||||
|
||||
import wavinfo
|
||||
import importlib
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = u'wavinfo'
|
||||
copyright = u'2018-2023, Jamie Hardt'
|
||||
copyright = u'2018-2024, Jamie Hardt'
|
||||
author = u'Jamie Hardt'
|
||||
|
||||
# The short X.Y version
|
||||
version = wavinfo.__short_version__
|
||||
version = "3.1"
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = wavinfo.__version__
|
||||
release = importlib.metadata.version("wavinfo")
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
@@ -39,7 +39,7 @@ iXML
|
||||
Sampler Metadata
|
||||
----------------
|
||||
|
||||
* `RecordingBlogs.com — Sample chunk (of a Wave file)<https://www.recordingblogs.com/wiki/sample-chunk-of-a-wave-file>`_
|
||||
* `RecordingBlogs.com — Sample chunk (of a Wave file) <https://www.recordingblogs.com/wiki/sample-chunk-of-a-wave-file>`_
|
||||
|
||||
RIFF Metadata
|
||||
-------------
|
||||
|
||||
14
docs/source/scopes/smpl.rst
Normal file
14
docs/source/scopes/smpl.rst
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
Sampler Metadata
|
||||
=================
|
||||
|
||||
Class Reference
|
||||
---------------
|
||||
|
||||
.. automodule:: wavinfo.wave_smpl_reader
|
||||
|
||||
.. autoclass:: wavinfo.wave_smpl_reader.WavSmplReader
|
||||
:members:
|
||||
|
||||
.. autoclass:: wavinfo.wave_smpl_reader.WaveSmplLoop
|
||||
:members:
|
||||
@@ -6,7 +6,7 @@ build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.poetry]
|
||||
name = "wavinfo"
|
||||
version = "3.0.1"
|
||||
version = "3.1.0"
|
||||
description = "Probe WAVE files for all metadata"
|
||||
authors = ["Jamie Hardt <jamiehardt@me.com>"]
|
||||
license = "MIT"
|
||||
|
||||
BIN
tests/test_files/smpl/alarm_citizen_loop1_udata.wav
Normal file
BIN
tests/test_files/smpl/alarm_citizen_loop1_udata.wav
Normal file
Binary file not shown.
@@ -15,7 +15,7 @@ class MyJSONEncoder(json.JSONEncoder):
|
||||
if isinstance(o, Enum):
|
||||
return o._name_
|
||||
elif isinstance(o, bytes):
|
||||
return b64encode(o).decode('ascii')
|
||||
return 'base64:' + b64encode(o).decode('ascii')
|
||||
else:
|
||||
return super().default(o)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ class WaveSmplLoop(NamedTuple):
|
||||
loop_type: int
|
||||
start: int
|
||||
end: int
|
||||
fraction: int
|
||||
detune_cents: int
|
||||
repetition_count: int
|
||||
|
||||
def loop_type_desc(self):
|
||||
@@ -30,7 +30,7 @@ class WaveSmplLoop(NamedTuple):
|
||||
'loop_type_description': self.loop_type_desc(),
|
||||
'start_samples': self.start,
|
||||
'end_samples': self.end,
|
||||
'fraction': self.fraction,
|
||||
'detune_cents': self.detune_cents,
|
||||
'repetition_count': self.repetition_count,
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ class WavSmplReader:
|
||||
Read sampler metadata from smpl chunk.
|
||||
"""
|
||||
|
||||
header_field_fmt = "<IIIIIIbbbbII"
|
||||
loop_field_fmt = "<IIIIII"
|
||||
header_field_fmt = "<IIIIiIbbbbII"
|
||||
loop_field_fmt = "<IIIIiI"
|
||||
header_size = struct.calcsize(header_field_fmt)
|
||||
loop_size = struct.calcsize(loop_field_fmt)
|
||||
|
||||
@@ -65,7 +65,7 @@ class WavSmplReader:
|
||||
self.midi_note: int = unpacked_data[3]
|
||||
|
||||
#: The number of semitones above the MIDI note the loops tune for.
|
||||
self.midi_pitch_fraction_semis: int = unpacked_data[4]
|
||||
self.midi_pitch_detune_cents: int = unpacked_data[4]
|
||||
|
||||
#: SMPTE timecode format, one of (0, 24, 25, 29, 30)
|
||||
self.smpte_format: int = unpacked_data[5]
|
||||
@@ -89,13 +89,16 @@ class WavSmplReader:
|
||||
loop_type=unpacked_loop[1],
|
||||
start=unpacked_loop[2],
|
||||
end=unpacked_loop[3],
|
||||
fraction=unpacked_loop[4],
|
||||
detune_cents=unpacked_loop[4],
|
||||
repetition_count=unpacked_loop[5]))
|
||||
|
||||
#: Sampler-specific user data.
|
||||
self.sampler_udata: bytes = smpl_data[
|
||||
header_size + loop_size * loop_count:
|
||||
header_size + loop_size * loop_count + sampler_udata_length]
|
||||
self.sampler_udata: bytes | None = None
|
||||
|
||||
if sampler_udata_length > 0:
|
||||
self.sampler_udata = smpl_data[
|
||||
header_size + loop_size * loop_count:
|
||||
header_size + loop_size * loop_count + sampler_udata_length]
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
@@ -103,7 +106,7 @@ class WavSmplReader:
|
||||
'product': self.product,
|
||||
'sample_period_ns': self.sample_period_ns,
|
||||
'midi_note': self.midi_note,
|
||||
'midi_pitch_fraction_semis': self.midi_pitch_fraction_semis,
|
||||
'midi_pitch_detune_cents': self.midi_pitch_detune_cents,
|
||||
'smpte_format': self.smpte_format,
|
||||
'smpte_offset': "%02i:%02i:%02i:%02i" % self.smpte_offset,
|
||||
'loops': [x.to_dict() for x in self.sample_loops],
|
||||
|
||||
Reference in New Issue
Block a user