import os.path from glob import glob from typing import Dict, Any, cast from unittest import TestCase from .utils import all_files, ffprobe import wavinfo class TestWaveInfo(TestCase): def test_sanity(self): for wav_file in all_files(): info = wavinfo.WavInfoReader(wav_file) self.assertEqual(info.__repr__(), 'WavInfoReader({}, latin_1, ascii)'.format(os.path.abspath(wav_file))) self.assertIsNotNone(info) def test_fmt_against_ffprobe(self): for wav_file in all_files(): info = wavinfo.WavInfoReader(wav_file) ffprobe_info = ffprobe(wav_file) assert info.fmt is not None assert ffprobe_info is not None self.assertEqual(info.fmt.channel_count, ffprobe_info['streams'][0]['channels']) self.assertEqual(info.fmt.sample_rate, int(ffprobe_info['streams'][0]['sample_rate'])) self.assertEqual(info.fmt.bits_per_sample, int(ffprobe_info['streams'][0]['bits_per_sample'])) if info.fmt.audio_format == 1: self.assertTrue(ffprobe_info['streams'][0]['codec_name'].startswith('pcm')) streams = ffprobe_info['streams'][0] byte_rate = int(streams['sample_rate']) * streams['channels'] * int(streams['bits_per_sample']) / 8 self.assertEqual(info.fmt.byte_rate, byte_rate) def test_data_against_ffprobe(self): for wav_file in all_files(): info = wavinfo.WavInfoReader(wav_file) ffprobe_info = cast(Dict[str,Any], ffprobe(wav_file)) assert ffprobe_info is not None assert info.data is not None self.assertEqual(info.data.frame_count, int(ffprobe_info['streams'][0]['duration_ts'])) def test_bext_against_ffprobe(self): for wav_file in all_files(): info = wavinfo.WavInfoReader(wav_file) ffprobe_info = ffprobe(wav_file) assert ffprobe_info is not None if info.bext: if 'comment' in ffprobe_info['format']['tags']: self.assertEqual(info.bext.description, ffprobe_info['format']['tags']['comment']) else: self.assertEqual(info.bext.description, '') if 'encoded_by' in ffprobe_info['format']['tags']: self.assertEqual(info.bext.originator, ffprobe_info['format']['tags']['encoded_by']) else: self.assertEqual(info.bext.originator, '') if 'originator_reference' in ffprobe_info['format']['tags']: self.assertEqual(info.bext.originator_ref, ffprobe_info['format']['tags']['originator_reference']) else: self.assertEqual(info.bext.originator_ref, '') # these don't always reflect the bext info # self.assertEqual(info.bext.originator_date, ffprobe_info['format']['tags']['date']) # self.assertEqual(info.bext.originator_time, ffprobe_info['format']['tags']['creation_time']) self.assertEqual(info.bext.time_reference, int(ffprobe_info['format']['tags']['time_reference'])) if 'coding_history' in ffprobe_info['format']['tags']: self.assertEqual(info.bext.coding_history, ffprobe_info['format']['tags']['coding_history']) else: self.assertEqual(info.bext.coding_history, '') def test_ixml(self): expected = {'A101_4.WAV': {'project': 'BMH', 'scene': 'A101', 'take': '4', 'tape': '18Y12M31', 'family_uid': 'USSDVGR1112089007124015008231000'}, 'A101_3.WAV': {'project': 'BMH', 'scene': 'A101', 'take': '3', 'tape': '18Y12M31', 'family_uid': 'USSDVGR1112089007124014008228300'}, 'A101_2.WAV': {'project': 'BMH', 'scene': 'A101', 'take': '2', 'tape': '18Y12M31', 'family_uid': 'USSDVGR1112089007124004008218600'}, 'A101_1.WAV': {'project': 'BMH', 'scene': 'A101', 'take': '1', 'tape': '18Y12M31', 'family_uid': 'USSDVGR1112089007124001008206300'}, } for wav_file in all_files(): basename = os.path.basename(wav_file) if basename in expected: info = wavinfo.WavInfoReader(wav_file) e = expected[basename] self.assertIsNotNone(info.ixml) assert info.ixml is not None self.assertEqual(e['project'], info.ixml.project) self.assertEqual(e['scene'], info.ixml.scene) self.assertEqual(e['take'], info.ixml.take) self.assertEqual(e['tape'], info.ixml.tape) self.assertEqual(e['family_uid'], info.ixml.family_uid) for track in info.ixml.track_list: self.assertIsNotNone(track.channel_index) if basename == 'A101_4.WAV' and track.channel_index == '1': self.assertEqual(track.name, 'MKH516 A') def test_steinberg_ixml(self): nuendo_files = 'tests/test_files/nuendo/*.wav' for file in glob(nuendo_files): info = wavinfo.WavInfoReader(file) assert info.ixml is not None self.assertIsNotNone(info.ixml.steinberg) assert info.ixml.steinberg is not None self.assertIsNotNone(info.ixml.steinberg.audio_speaker_arrangement) self.assertEqual(info.ixml.steinberg.sample_format_size, 3) self.assertEqual(info.ixml.steinberg.media_company, "https://github.com/iluvcapra/wavinfo") self.assertFalse(info.ixml.steinberg.media_drop_frames) self.assertEqual(info.ixml.steinberg.media_duration, 1200.0) def test_steinberg_missing(self): file_with_no_nuendo = "tests/test_files/sounddevices/A101_1.WAV" info = wavinfo.WavInfoReader(file_with_no_nuendo) assert info.ixml is not None self.assertIsNone(info.ixml.steinberg) def test_info_metadata(self): file_with_metadata = 'tests/test_files/sound_grinder_pro/new_camera bumb 1.wav' self.assertTrue(os.path.exists(file_with_metadata)) info = wavinfo.WavInfoReader(file_with_metadata).info assert info is not None self.assertEqual(info.title, 'camera bumb 1') self.assertEqual(info.artist, 'Jamie Hardt') self.assertEqual(info.copyright, '© 2010 Jamie Hardt') self.assertEqual(info.product, 'Test Sounds') # album self.assertEqual(info.album, info.product) self.assertEqual(info.comment, 'Comments') self.assertEqual(info.software, 'Sound Grinder Pro') self.assertEqual(info.created_date, '2010-12-28') self.assertEqual(info.engineer, 'JPH') self.assertEqual(info.keywords, 'Sound Effect, movement, microphone, bump') self.assertEqual(info.title, 'camera bumb 1') self.assertEqual(type(info.to_dict()), dict) self.assertEqual(type(info.__repr__()), str)