tinytag 2.3.0__tar.gz → 2.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tinytag might be problematic. Click here for more details.
- tinytag-2.3.1/.editorconfig +19 -0
- tinytag-2.3.1/CONTRIBUTING.md +24 -0
- tinytag-2.3.1/LICENSES/CC0-1.0.txt +121 -0
- tinytag-2.3.1/LICENSES/MIT.txt +1 -0
- {tinytag-2.3.0 → tinytag-2.3.1}/PKG-INFO +17 -8
- {tinytag-2.3.0 → tinytag-2.3.1}/README.md +6 -0
- tinytag-2.3.1/SECURITY.md +17 -0
- {tinytag-2.3.0 → tinytag-2.3.1}/pyproject.toml +11 -3
- {tinytag-2.3.0 → tinytag-2.3.1}/tinytag/__init__.py +1 -1
- {tinytag-2.3.0 → tinytag-2.3.1}/tinytag/tinytag.py +17 -21
- {tinytag-2.3.0 → tinytag-2.3.1}/LICENSE +0 -0
- {tinytag-2.3.0 → tinytag-2.3.1}/tinytag/__main__.py +0 -0
- {tinytag-2.3.0 → tinytag-2.3.1}/tinytag/py.typed +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2025 tinytag Contributors
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
root = true
|
|
5
|
+
|
|
6
|
+
[*]
|
|
7
|
+
charset = utf-8
|
|
8
|
+
end_of_line = lf
|
|
9
|
+
indent_size = 4
|
|
10
|
+
indent_style = space
|
|
11
|
+
insert_final_newline = true
|
|
12
|
+
max_line_length = 79
|
|
13
|
+
trim_trailing_whitespace = true
|
|
14
|
+
|
|
15
|
+
[*.md]
|
|
16
|
+
trim_trailing_whitespace = false
|
|
17
|
+
|
|
18
|
+
[*.yml]
|
|
19
|
+
indent_size = 2
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 tinytag Contributors
|
|
3
|
+
SPDX-License-Identifier: MIT
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Contributing
|
|
7
|
+
|
|
8
|
+
Before submitting a PR, please discuss the change you wish to make in an issue
|
|
9
|
+
report or discussion thread, in order to see if it fits the direction of the
|
|
10
|
+
project. If you skip this step, a PR containing anything other than a trivial
|
|
11
|
+
bug fix will likely be rejected.
|
|
12
|
+
|
|
13
|
+
Contributions generated or co-authored by LLMs or AI coding tools are not
|
|
14
|
+
allowed. Your contribution must be licensed as original work that is personally
|
|
15
|
+
authored by you under the terms of the
|
|
16
|
+
[MIT License](https://github.com/tinytag/tinytag/blob/HEAD/LICENSE).
|
|
17
|
+
Every part of your contribution must be written, thoroughly tested and fully
|
|
18
|
+
understood by you so that any queries about the logic of your contribution can
|
|
19
|
+
be answered during the review process.
|
|
20
|
+
|
|
21
|
+
You may only use AI assistants or tooling for learning purposes, including
|
|
22
|
+
guided research of the codebase and exploring concepts. Your contribution must
|
|
23
|
+
not include any content produced by generative AI (code, text snippets, images
|
|
24
|
+
nor other media).
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
Creative Commons Legal Code
|
|
2
|
+
|
|
3
|
+
CC0 1.0 Universal
|
|
4
|
+
|
|
5
|
+
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
|
6
|
+
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
|
7
|
+
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
|
8
|
+
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
|
9
|
+
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
|
10
|
+
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
|
11
|
+
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
|
12
|
+
HEREUNDER.
|
|
13
|
+
|
|
14
|
+
Statement of Purpose
|
|
15
|
+
|
|
16
|
+
The laws of most jurisdictions throughout the world automatically confer
|
|
17
|
+
exclusive Copyright and Related Rights (defined below) upon the creator
|
|
18
|
+
and subsequent owner(s) (each and all, an "owner") of an original work of
|
|
19
|
+
authorship and/or a database (each, a "Work").
|
|
20
|
+
|
|
21
|
+
Certain owners wish to permanently relinquish those rights to a Work for
|
|
22
|
+
the purpose of contributing to a commons of creative, cultural and
|
|
23
|
+
scientific works ("Commons") that the public can reliably and without fear
|
|
24
|
+
of later claims of infringement build upon, modify, incorporate in other
|
|
25
|
+
works, reuse and redistribute as freely as possible in any form whatsoever
|
|
26
|
+
and for any purposes, including without limitation commercial purposes.
|
|
27
|
+
These owners may contribute to the Commons to promote the ideal of a free
|
|
28
|
+
culture and the further production of creative, cultural and scientific
|
|
29
|
+
works, or to gain reputation or greater distribution for their Work in
|
|
30
|
+
part through the use and efforts of others.
|
|
31
|
+
|
|
32
|
+
For these and/or other purposes and motivations, and without any
|
|
33
|
+
expectation of additional consideration or compensation, the person
|
|
34
|
+
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
|
35
|
+
is an owner of Copyright and Related Rights in the Work, voluntarily
|
|
36
|
+
elects to apply CC0 to the Work and publicly distribute the Work under its
|
|
37
|
+
terms, with knowledge of his or her Copyright and Related Rights in the
|
|
38
|
+
Work and the meaning and intended legal effect of CC0 on those rights.
|
|
39
|
+
|
|
40
|
+
1. Copyright and Related Rights. A Work made available under CC0 may be
|
|
41
|
+
protected by copyright and related or neighboring rights ("Copyright and
|
|
42
|
+
Related Rights"). Copyright and Related Rights include, but are not
|
|
43
|
+
limited to, the following:
|
|
44
|
+
|
|
45
|
+
i. the right to reproduce, adapt, distribute, perform, display,
|
|
46
|
+
communicate, and translate a Work;
|
|
47
|
+
ii. moral rights retained by the original author(s) and/or performer(s);
|
|
48
|
+
iii. publicity and privacy rights pertaining to a person's image or
|
|
49
|
+
likeness depicted in a Work;
|
|
50
|
+
iv. rights protecting against unfair competition in regards to a Work,
|
|
51
|
+
subject to the limitations in paragraph 4(a), below;
|
|
52
|
+
v. rights protecting the extraction, dissemination, use and reuse of data
|
|
53
|
+
in a Work;
|
|
54
|
+
vi. database rights (such as those arising under Directive 96/9/EC of the
|
|
55
|
+
European Parliament and of the Council of 11 March 1996 on the legal
|
|
56
|
+
protection of databases, and under any national implementation
|
|
57
|
+
thereof, including any amended or successor version of such
|
|
58
|
+
directive); and
|
|
59
|
+
vii. other similar, equivalent or corresponding rights throughout the
|
|
60
|
+
world based on applicable law or treaty, and any national
|
|
61
|
+
implementations thereof.
|
|
62
|
+
|
|
63
|
+
2. Waiver. To the greatest extent permitted by, but not in contravention
|
|
64
|
+
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
|
65
|
+
irrevocably and unconditionally waives, abandons, and surrenders all of
|
|
66
|
+
Affirmer's Copyright and Related Rights and associated claims and causes
|
|
67
|
+
of action, whether now known or unknown (including existing as well as
|
|
68
|
+
future claims and causes of action), in the Work (i) in all territories
|
|
69
|
+
worldwide, (ii) for the maximum duration provided by applicable law or
|
|
70
|
+
treaty (including future time extensions), (iii) in any current or future
|
|
71
|
+
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
|
72
|
+
including without limitation commercial, advertising or promotional
|
|
73
|
+
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
|
74
|
+
member of the public at large and to the detriment of Affirmer's heirs and
|
|
75
|
+
successors, fully intending that such Waiver shall not be subject to
|
|
76
|
+
revocation, rescission, cancellation, termination, or any other legal or
|
|
77
|
+
equitable action to disrupt the quiet enjoyment of the Work by the public
|
|
78
|
+
as contemplated by Affirmer's express Statement of Purpose.
|
|
79
|
+
|
|
80
|
+
3. Public License Fallback. Should any part of the Waiver for any reason
|
|
81
|
+
be judged legally invalid or ineffective under applicable law, then the
|
|
82
|
+
Waiver shall be preserved to the maximum extent permitted taking into
|
|
83
|
+
account Affirmer's express Statement of Purpose. In addition, to the
|
|
84
|
+
extent the Waiver is so judged Affirmer hereby grants to each affected
|
|
85
|
+
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
|
86
|
+
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
|
87
|
+
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
|
88
|
+
maximum duration provided by applicable law or treaty (including future
|
|
89
|
+
time extensions), (iii) in any current or future medium and for any number
|
|
90
|
+
of copies, and (iv) for any purpose whatsoever, including without
|
|
91
|
+
limitation commercial, advertising or promotional purposes (the
|
|
92
|
+
"License"). The License shall be deemed effective as of the date CC0 was
|
|
93
|
+
applied by Affirmer to the Work. Should any part of the License for any
|
|
94
|
+
reason be judged legally invalid or ineffective under applicable law, such
|
|
95
|
+
partial invalidity or ineffectiveness shall not invalidate the remainder
|
|
96
|
+
of the License, and in such case Affirmer hereby affirms that he or she
|
|
97
|
+
will not (i) exercise any of his or her remaining Copyright and Related
|
|
98
|
+
Rights in the Work or (ii) assert any associated claims and causes of
|
|
99
|
+
action with respect to the Work, in either case contrary to Affirmer's
|
|
100
|
+
express Statement of Purpose.
|
|
101
|
+
|
|
102
|
+
4. Limitations and Disclaimers.
|
|
103
|
+
|
|
104
|
+
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
|
105
|
+
surrendered, licensed or otherwise affected by this document.
|
|
106
|
+
b. Affirmer offers the Work as-is and makes no representations or
|
|
107
|
+
warranties of any kind concerning the Work, express, implied,
|
|
108
|
+
statutory or otherwise, including without limitation warranties of
|
|
109
|
+
title, merchantability, fitness for a particular purpose, non
|
|
110
|
+
infringement, or the absence of latent or other defects, accuracy, or
|
|
111
|
+
the present or absence of errors, whether or not discoverable, all to
|
|
112
|
+
the greatest extent permissible under applicable law.
|
|
113
|
+
c. Affirmer disclaims responsibility for clearing rights of other persons
|
|
114
|
+
that may apply to the Work or any use thereof, including without
|
|
115
|
+
limitation any person's Copyright and Related Rights in the Work.
|
|
116
|
+
Further, Affirmer disclaims responsibility for obtaining any necessary
|
|
117
|
+
consents, permissions or other rights required for any use of the
|
|
118
|
+
Work.
|
|
119
|
+
d. Affirmer understands and acknowledges that Creative Commons is not a
|
|
120
|
+
party to this document and has no duty or obligation with respect to
|
|
121
|
+
this CC0 or use of the Work.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
../LICENSE
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tinytag
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.1
|
|
4
4
|
Summary: Read audio file metadata
|
|
5
5
|
Keywords: metadata,audio,music,mp3,m4a,wav,ogg,opus,flac,wma,aiff
|
|
6
6
|
Author: Tom Wallroth, Mat (mathiascode)
|
|
@@ -28,14 +28,17 @@ Classifier: Topic :: Multimedia :: Sound/Audio
|
|
|
28
28
|
Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
|
|
29
29
|
Classifier: Typing :: Typed
|
|
30
30
|
License-File: LICENSE
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist:
|
|
33
|
-
Requires-Dist:
|
|
34
|
-
Requires-Dist:
|
|
35
|
-
Requires-Dist:
|
|
36
|
-
Requires-Dist:
|
|
31
|
+
Requires-Dist: build ; extra == "dev"
|
|
32
|
+
Requires-Dist: coverage ; extra == "dev"
|
|
33
|
+
Requires-Dist: flit_core ; extra == "dev"
|
|
34
|
+
Requires-Dist: mypy ; extra == "dev"
|
|
35
|
+
Requires-Dist: mypy<1.19.0 ; extra == "dev" and ( platform_python_implementation == 'PyPy')
|
|
36
|
+
Requires-Dist: pycodestyle ; extra == "dev"
|
|
37
|
+
Requires-Dist: pylint ; extra == "dev"
|
|
38
|
+
Requires-Dist: pyright ; extra == "dev"
|
|
39
|
+
Requires-Dist: wheel ; extra == "dev"
|
|
37
40
|
Project-URL: Homepage, https://github.com/tinytag/tinytag
|
|
38
|
-
Provides-Extra:
|
|
41
|
+
Provides-Extra: dev
|
|
39
42
|
|
|
40
43
|
<!--
|
|
41
44
|
SPDX-FileCopyrightText: 2014-2026 tinytag Contributors
|
|
@@ -527,6 +530,12 @@ UnsupportedFormatError # File format is not supported
|
|
|
527
530
|
|
|
528
531
|
## Changelog
|
|
529
532
|
|
|
533
|
+
### 2.3.1 (2026-08-30)
|
|
534
|
+
|
|
535
|
+
- Don't open unrecognized files when disabling magic byte detection
|
|
536
|
+
- MPEG: Fix parsing of some files with incorrect headers
|
|
537
|
+
- OGG/WAV: Read sizes as little endian instead of native byte order
|
|
538
|
+
|
|
530
539
|
### 2.3.0 (2026-07-31)
|
|
531
540
|
|
|
532
541
|
- Add 'mime_type' attribute for audio MIME type/codec
|
|
@@ -488,6 +488,12 @@ UnsupportedFormatError # File format is not supported
|
|
|
488
488
|
|
|
489
489
|
## Changelog
|
|
490
490
|
|
|
491
|
+
### 2.3.1 (2026-08-30)
|
|
492
|
+
|
|
493
|
+
- Don't open unrecognized files when disabling magic byte detection
|
|
494
|
+
- MPEG: Fix parsing of some files with incorrect headers
|
|
495
|
+
- OGG/WAV: Read sizes as little endian instead of native byte order
|
|
496
|
+
|
|
491
497
|
### 2.3.0 (2026-07-31)
|
|
492
498
|
|
|
493
499
|
- Add 'mime_type' attribute for audio MIME type/codec
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 tinytag Contributors
|
|
3
|
+
SPDX-License-Identifier: MIT
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Security Policy
|
|
7
|
+
|
|
8
|
+
## Supported Versions
|
|
9
|
+
|
|
10
|
+
tinytag follows a `A.B.C` versioning scheme. We only support the latest
|
|
11
|
+
released `A.B.x` series.
|
|
12
|
+
|
|
13
|
+
## Reporting a Vulnerability
|
|
14
|
+
|
|
15
|
+
Please report a vulnerability under the Security tab in the GitHub repository.
|
|
16
|
+
Since tinytag is a volunteer-driven project, your report will be reviewed and
|
|
17
|
+
addressed when the maintainers have time.
|
|
@@ -57,20 +57,28 @@ dynamic = ["version"]
|
|
|
57
57
|
Homepage = "https://github.com/tinytag/tinytag"
|
|
58
58
|
|
|
59
59
|
[project.optional-dependencies]
|
|
60
|
-
|
|
60
|
+
dev = [
|
|
61
|
+
"build",
|
|
61
62
|
"coverage",
|
|
63
|
+
"flit_core",
|
|
62
64
|
"mypy",
|
|
63
65
|
"mypy<1.19.0; platform_python_implementation == 'PyPy'",
|
|
64
66
|
"pycodestyle",
|
|
65
67
|
"pylint",
|
|
66
|
-
"pyright"
|
|
68
|
+
"pyright",
|
|
69
|
+
"wheel"
|
|
67
70
|
]
|
|
68
71
|
|
|
69
72
|
[tool.flit.sdist]
|
|
73
|
+
include = [
|
|
74
|
+
"LICENSES/",
|
|
75
|
+
".editorconfig",
|
|
76
|
+
"CONTRIBUTING.md",
|
|
77
|
+
"SECURITY.md"
|
|
78
|
+
]
|
|
70
79
|
exclude = [
|
|
71
80
|
".gitignore",
|
|
72
81
|
".github/",
|
|
73
|
-
"tinytag/icons/",
|
|
74
82
|
"tinytag/tests/"
|
|
75
83
|
]
|
|
76
84
|
|
|
@@ -134,12 +134,16 @@ class TinyTag:
|
|
|
134
134
|
check_magic_bytes: bool = True) -> TinyTag:
|
|
135
135
|
"""Return a tag object for an audio file."""
|
|
136
136
|
should_close_file = file_obj is None
|
|
137
|
+
parser_class = None
|
|
137
138
|
filename_str = None
|
|
138
139
|
if filename:
|
|
140
|
+
filename_str = fsdecode(filename)
|
|
141
|
+
if not check_magic_bytes:
|
|
142
|
+
# Raises UnsupportedFormatError
|
|
143
|
+
parser_class = cls._get_parser_class(filename_str)
|
|
139
144
|
if should_close_file:
|
|
140
145
|
# pylint: disable=consider-using-with
|
|
141
146
|
file_obj = open(filename, 'rb')
|
|
142
|
-
filename_str = fsdecode(filename)
|
|
143
147
|
if file_obj is None:
|
|
144
148
|
raise ValueError(
|
|
145
149
|
'Either filename or file_obj argument is required')
|
|
@@ -149,14 +153,13 @@ class TinyTag:
|
|
|
149
153
|
warn('ignore_errors argument is obsolete, and will be removed in '
|
|
150
154
|
'the future', DeprecationWarning, stacklevel=2)
|
|
151
155
|
try:
|
|
152
|
-
|
|
156
|
+
if parser_class is None: # check_magic_bytes is True
|
|
157
|
+
# Raises UnsupportedFormatError
|
|
158
|
+
parser_class = cls._get_parser_class(filename_str, file_obj)
|
|
153
159
|
file_obj.seek(0, SEEK_END)
|
|
154
160
|
filesize = file_obj.tell()
|
|
155
161
|
file_obj.seek(0)
|
|
156
|
-
|
|
157
|
-
parser_class = cls._get_parser_class(filename_str, file_obj)
|
|
158
|
-
else:
|
|
159
|
-
parser_class = cls._get_parser_class(filename_str)
|
|
162
|
+
# pylint: disable=protected-access
|
|
160
163
|
tag = parser_class()
|
|
161
164
|
tag._filehandler = file_obj
|
|
162
165
|
tag._default_encoding = encoding
|
|
@@ -232,7 +235,6 @@ class TinyTag:
|
|
|
232
235
|
) -> type[TinyTag] | None:
|
|
233
236
|
# https://en.wikipedia.org/wiki/List_of_file_signatures
|
|
234
237
|
header = filehandle.read(30)
|
|
235
|
-
filehandle.seek(0)
|
|
236
238
|
if header.startswith(b'ID3'):
|
|
237
239
|
return _ID3
|
|
238
240
|
if (len(header) >= 2
|
|
@@ -244,8 +246,6 @@ class TinyTag:
|
|
|
244
246
|
except OSError:
|
|
245
247
|
# File smaller than ID3v1 tag size
|
|
246
248
|
pass
|
|
247
|
-
finally:
|
|
248
|
-
filehandle.seek(0)
|
|
249
249
|
if footer == b'TAG':
|
|
250
250
|
return _ID3
|
|
251
251
|
return _MPEG
|
|
@@ -420,7 +420,7 @@ class Images:
|
|
|
420
420
|
for other_key, other_values in value.items():
|
|
421
421
|
other_images = images.get(other_key)
|
|
422
422
|
if not isinstance(other_images, list):
|
|
423
|
-
|
|
423
|
+
images[other_key] = other_values
|
|
424
424
|
else:
|
|
425
425
|
other_images += other_values
|
|
426
426
|
return images
|
|
@@ -1471,7 +1471,6 @@ class _MPEG(TinyTag):
|
|
|
1471
1471
|
_MAX_ESTIMATION_SEC = 30
|
|
1472
1472
|
_CBR_DETECTION_FRAME_COUNT = 5
|
|
1473
1473
|
_USE_XING_HEADER = True # much faster, but can be deactivated for testing
|
|
1474
|
-
_MAX_INVALID_FRAMES = 200
|
|
1475
1474
|
|
|
1476
1475
|
# see this page for the magic values used in mp3:
|
|
1477
1476
|
# http://www.mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm
|
|
@@ -1532,7 +1531,6 @@ class _MPEG(TinyTag):
|
|
|
1532
1531
|
max_estimation_frames = 0
|
|
1533
1532
|
frame_size_accu = 0
|
|
1534
1533
|
frames = 0 # count frames for determining mp3 duration
|
|
1535
|
-
invalid_frames = 0
|
|
1536
1534
|
bitrate_accu = 0 # add up bitrates to find average bitrate to detect
|
|
1537
1535
|
last_bitrates: set[int] = set() # CBR mp3s (many frames with same brs)
|
|
1538
1536
|
# seek to first position after id3 tag (speedup for large header)
|
|
@@ -1568,9 +1566,6 @@ class _MPEG(TinyTag):
|
|
|
1568
1566
|
fh.seek(idx - header_len, SEEK_CUR)
|
|
1569
1567
|
if frames == 0:
|
|
1570
1568
|
audio_offset += next_offset
|
|
1571
|
-
invalid_frames += 1
|
|
1572
|
-
if invalid_frames > self._MAX_INVALID_FRAMES:
|
|
1573
|
-
raise ParseError("Invalid MPEG frame header")
|
|
1574
1569
|
continue
|
|
1575
1570
|
self.channels = self._CHANNELS_PER_CHANNEL_MODE[channel_mode]
|
|
1576
1571
|
frame_br = self._BITRATE_VERSION_LAYERS[mpeg_id][layer_id][br_id]
|
|
@@ -1840,11 +1835,11 @@ class _Ogg(TinyTag):
|
|
|
1840
1835
|
# for the spec, see: http://xiph.org/vorbis/doc/v-comment.html
|
|
1841
1836
|
# discnumber tag based on: https://en.wikipedia.org/wiki/Vorbis_comment
|
|
1842
1837
|
# https://sno.phy.queensu.ca/~phil/exiftool/TagNames/Vorbis.html
|
|
1843
|
-
vendor_length = unpack('I', fh.read(4))[0]
|
|
1838
|
+
vendor_length = unpack('<I', fh.read(4))[0]
|
|
1844
1839
|
fh.seek(vendor_length, SEEK_CUR) # jump over vendor
|
|
1845
|
-
elements = unpack('I', fh.read(4))[0]
|
|
1840
|
+
elements = unpack('<I', fh.read(4))[0]
|
|
1846
1841
|
for _i in range(elements):
|
|
1847
|
-
length = unpack('I', fh.read(4))[0]
|
|
1842
|
+
length = unpack('<I', fh.read(4))[0]
|
|
1848
1843
|
if not read_data:
|
|
1849
1844
|
fh.seek(length, SEEK_CUR)
|
|
1850
1845
|
continue
|
|
@@ -2000,7 +1995,7 @@ class _Wave(TinyTag):
|
|
|
2000
1995
|
header_len = 8
|
|
2001
1996
|
chunk_header = fh.read(header_len)
|
|
2002
1997
|
while len(chunk_header) == header_len:
|
|
2003
|
-
subchunk_size = unpack_from('I', chunk_header, 4)[0]
|
|
1998
|
+
subchunk_size = unpack_from('<I', chunk_header, 4)[0]
|
|
2004
1999
|
subchunk_size_unpadded = subchunk_size
|
|
2005
2000
|
# IFF chunks are padded to an even number of bytes
|
|
2006
2001
|
subchunk_size += subchunk_size % 2
|
|
@@ -2025,7 +2020,7 @@ class _Wave(TinyTag):
|
|
|
2025
2020
|
fh.seek(subchunk_size, SEEK_CUR)
|
|
2026
2021
|
elif self._parse_duration and chunk_header.startswith(b'fact'):
|
|
2027
2022
|
chunk = fh.read(subchunk_size)
|
|
2028
|
-
num_samples = unpack_from('I', chunk)[0]
|
|
2023
|
+
num_samples = unpack_from('<I', chunk)[0]
|
|
2029
2024
|
elif self._parse_tags and chunk_header.startswith(b'LIST'):
|
|
2030
2025
|
chunk = fh.read(subchunk_size)
|
|
2031
2026
|
if chunk.startswith(b'INFO'):
|
|
@@ -2033,7 +2028,7 @@ class _Wave(TinyTag):
|
|
|
2033
2028
|
walker.seek(4) # skip header
|
|
2034
2029
|
field = walker.read(4)
|
|
2035
2030
|
while len(field) == 4:
|
|
2036
|
-
data_length = unpack('I', walker.read(4))[0]
|
|
2031
|
+
data_length = unpack('<I', walker.read(4))[0]
|
|
2037
2032
|
# IFF chunks are padded to an even size
|
|
2038
2033
|
data_length += data_length % 2
|
|
2039
2034
|
data = self._unpad_bytes(walker.read(data_length))
|
|
@@ -2498,6 +2493,7 @@ class _Aiff(TinyTag):
|
|
|
2498
2493
|
self.bitrate = bitrate
|
|
2499
2494
|
self.samplerate, self.duration = sr, duration
|
|
2500
2495
|
except OverflowError:
|
|
2496
|
+
# Invalid sample rate
|
|
2501
2497
|
pass
|
|
2502
2498
|
compression_type = chunk[18:22].decode('latin-1')
|
|
2503
2499
|
if not compression_type:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|