Skip to content

Commit

Permalink
Merge abec193 into 2b0d33f
Browse files Browse the repository at this point in the history
  • Loading branch information
mathiascode committed Aug 14, 2023
2 parents 2b0d33f + abec193 commit be8d7e3
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 12 deletions.
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@ tinytag is a library for reading music meta data of most common audio files in p

* Read tags, length and cover images of audio files
* Supported formats:
* MP3/MP2/MP1 (ID3 v1, v1.1, v2.2, v2.3+)
* Wave/RIFF
* OGG
* OPUS
* MP3 / MP2 / MP1 (ID3 v1, v1.1, v2.2, v2.3+)
* M4A (AAC / ALAC)
* Wave / RIFF
* OGG (Opus / Speex / Vorbis)
* FLAC
* WMA
* MP4/M4A/M4B/M4R/M4V/ALAC/AAX/AAXC
* AIFF/AIFF-C
* AIFF / AIFF-C
* Pure Python, no dependencies
* Supports Python 2.7 and 3.4 or higher
* High test coverage
Expand Down
Binary file added tinytag/tests/samples/test.spx
Binary file not shown.
6 changes: 4 additions & 2 deletions tinytag/tests/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,6 @@
'audio_offset': 0, 'bitrate': 112.0, 'duration': 3.684716553287982,
'genre': 'Some Genre', 'samplerate': 44100, 'title': 'A Title', 'track': '2',
'year': '2007', 'composer': 'some composer'}),

# OPUS
('samples/test.opus',
{'extra': {}, 'albumartist': 'Alstroemeria Records', 'samplerate': 48000, 'channels': 2,
'track': '1', 'disc': '1', 'title': 'Bad Apple!!', 'duration': 2.0, 'year': '2008.05.25',
Expand All @@ -233,6 +231,10 @@
'comment': 'ARCD0018 - Lovelight', 'disc_total': '1', 'track_total': '13'}),
('samples/8khz_5s.opus',
{'extra': {}, 'filesize': 7251, 'channels': 1, 'samplerate': 48000, 'duration': 5.0}),
('samples/test.spx',
{'extra': {}, 'filesize': 7921, 'channels': 1, 'samplerate': 16000, 'bitrate': -1,
'duration': 2.1445625, 'artist': 'test1', 'title': 'test2',
'comment': 'Encoded with Speex 1.2.0'}),

# WAV
('samples/test.wav',
Expand Down
24 changes: 20 additions & 4 deletions tinytag/tinytag.py
Original file line number Diff line number Diff line change
Expand Up @@ -909,11 +909,13 @@ def _determine_duration(self, fh):

def _parse_tag(self, fh):
page_start_pos = fh.tell() # set audio_offset later if its audio data
spx_second_packet = False
for packet in self._parse_pages(fh):
walker = BytesIO(packet)
if packet[0:7] == b"\x01vorbis":
walker.seek(11) # jump over header name and irrelevant fields
(channels, self.samplerate, max_bitrate, bitrate,
min_bitrate) = struct.unpack("<B4i", packet[11:28])
min_bitrate) = struct.unpack("<B4i", walker.read(17))
if not self.audio_offset:
self.bitrate = bitrate / 1000
self.audio_offset = page_start_pos
Expand All @@ -931,13 +933,25 @@ def _parse_tag(self, fh):
elif packet[0:8] == b'OpusTags' and self._parse_tags: # parse opus metadata:
walker.seek(8, os.SEEK_CUR) # jump over header name
self._parse_vorbis_comment(walker)
elif packet[0:8] == b'Speex ':
# https://speex.org/docs/manual/speex-manual/node8.html
walker.seek(36, os.SEEK_CUR) # jump over header name and irrelevant fields
(self.samplerate, _, _, self.channels,
self.bitrate) = struct.unpack("<5i", walker.read(20))
spx_second_packet = True
elif spx_second_packet:
length = struct.unpack('I', walker.read(4))[0] # starts with a comment string
comment = codecs.decode(walker.read(length), 'UTF-8')
self._set_field('comment', comment)
self._parse_vorbis_comment(walker, contains_vendor=False) # other tags
spx_second_packet = False
else:
if DEBUG:
stderr('Unsupported Ogg page type: ', packet[:16])
break
page_start_pos = fh.tell()

def _parse_vorbis_comment(self, fh):
def _parse_vorbis_comment(self, fh, contains_vendor=True):
# for the spec, see: http://xiph.org/vorbis/doc/v-comment.html
# discnumber tag based on: https://en.wikipedia.org/wiki/Vorbis_comment
# https://sno.phy.queensu.ca/~phil/exiftool/TagNames/Vorbis.html
Expand All @@ -946,6 +960,7 @@ def _parse_vorbis_comment(self, fh):
'albumartist': 'albumartist',
'title': 'title',
'artist': 'artist',
'author': 'artist',
'date': 'year',
'tracknumber': 'track',
'tracktotal': 'track_total',
Expand All @@ -957,8 +972,9 @@ def _parse_vorbis_comment(self, fh):
'description': 'comment',
'composer': 'composer',
}
vendor_length = struct.unpack('I', fh.read(4))[0]
fh.seek(vendor_length, os.SEEK_CUR) # jump over vendor
if contains_vendor:
vendor_length = struct.unpack('I', fh.read(4))[0]
fh.seek(vendor_length, os.SEEK_CUR) # jump over vendor
elements = struct.unpack('I', fh.read(4))[0]
for i in range(elements):
length = struct.unpack('I', fh.read(4))[0]
Expand Down

0 comments on commit be8d7e3

Please sign in to comment.