From 5a11d41aab04131f3131bd91212f64f62ceb823b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20St=C3=A5hl?= Date: Mon, 30 Aug 2021 11:09:53 +0200 Subject: [PATCH] wave: Read metadata from RIFF INFO chunk --- mutagen/wave.py | 53 +++++++++++++++++--- tests/data/silence-2s-PCM-16000-08-INFO.wav | Bin 0 -> 128186 bytes tests/test_wave.py | 14 ++++++ 3 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 tests/data/silence-2s-PCM-16000-08-INFO.wav diff --git a/mutagen/wave.py b/mutagen/wave.py index 29826034..f37d6b01 100644 --- a/mutagen/wave.py +++ b/mutagen/wave.py @@ -13,7 +13,7 @@ from mutagen import StreamInfo, FileType -from mutagen.id3 import ID3 +from mutagen.id3 import Encoding, ID3, TIT2, TPE1, TORY, TCON, TALB, TRCK from mutagen._riff import RiffFile, InvalidChunk from mutagen._iff import error as IffError from mutagen.id3._util import ID3NoHeaderError, error as ID3Error @@ -26,6 +26,15 @@ __all__ = ["WAVE", "Open", "delete"] +_INFO_TO_ID3_MAP = { + "INAM": TIT2, # Title + "IART": TPE1, # Artist + "ICRD": TORY, # Original release year + "IGNR": TCON, # Genre + "IPRD": TALB, # Album name + "IPRT": TRCK, # Track +} + class error(IffError): """WAVE stream parsing errors.""" @@ -151,10 +160,38 @@ def delete(self, filething): def delete(filething): """Completely removes the ID3 chunk from the RIFF/WAVE file""" - try: - _WaveFile(filething.fileobj).delete_chunk(u'id3') - except KeyError: - pass + for chunk in [u'id3', u'LIST']: + try: + _WaveFile(filething.fileobj).delete_chunk(chunk) + except KeyError: + pass + + +def _read_tags_from_riff_list(fileobj): + """Read metadata tags from RIFF LIST tag and convert to ID3 format.""" + wave_file = _WaveFile(fileobj) + + if u"LIST" not in wave_file: + return None + + list_chunk = wave_file[u"LIST"] + if list_chunk.name != u"INFO": + return None + + wave_id3 = _WaveID3() + for chunk in list_chunk.subchunks(): + try: + # Value is null-terminated and supposed to be ASCII, but not everyone + # respects that and puts unicode in there anyway + value = chunk.read()[:-1].decode("utf-8") + except UnicodeDecodeError: + continue + else: + id3_tag = _INFO_TO_ID3_MAP.get(chunk.id) + if id3_tag: + wave_id3.add(id3_tag(encoding=Encoding.UTF8, text=value)) + + return wave_id3 class WAVE(FileType): @@ -199,11 +236,11 @@ def load(self, filething, **kwargs): try: self.tags = _WaveID3(fileobj, **kwargs) except ID3NoHeaderError: - self.tags = None + self.tags = _read_tags_from_riff_list(fileobj) except ID3Error as e: raise error(e) - else: - self.tags.filename = self.filename + if self.tags: + self.tags.filename = self.filename Open = WAVE diff --git a/tests/data/silence-2s-PCM-16000-08-INFO.wav b/tests/data/silence-2s-PCM-16000-08-INFO.wav new file mode 100644 index 0000000000000000000000000000000000000000..3dc057b01c6621badbec4ff1cc4aee495eaff431 GIT binary patch literal 128186 zcmeIuze>YU6bIm2|A2!?7xz4XlvpfoLa{~ywXJE;IoebrwhBfECnq1sXLEA$Iy(6R z-<^Kvo^#;v6?v9@es#k2@ak;2YLjjVp%XU3`$-JnA#8QCE zSyk(UO>3;Ag=+KzwyG(Cz_=aXV5R`ceeUfrf!q6 zer}Ud)mCwPR+O8uoAzU#XXReZ