def test_is_complete(self): # All headers are specified in this header. hdr = mp3_header.MP3Header(sampling_rate_hz=44100, bit_rate_kbps=128, padding=False, protected=True, channels=mp3_header.JOINT_STEREO) self.assertTrue(hdr.is_complete()) # This is an incomplete header. hdr = mp3_header.MP3Header(sampling_rate_hz=44100) self.assertFalse(hdr.is_complete())
def tuple_to_audio_file(au_file_tuple): """Convert a tuple into a new AudioFile object. This is the inverse of audio_file_to_tuple. """ au_file = audio_file.AudioFile() (au_file.volume, au_file.import_timestamp, au_file.fingerprint, raw_album_id, sampling_rate_hz, bit_rate_kbps, channels, au_file.frame_count, au_file.frame_size, au_file.duration_ms) = au_file_tuple au_file.album_id = int(raw_album_id) au_file.mp3_header = mp3_header.MP3Header( sampling_rate_hz=sampling_rate_hz, bit_rate_kbps=bit_rate_kbps, channels=channels) return au_file
def __init__(self, src): message.MessageConsumer.__init__(self, src) message.MessageSource.__init__(self) self._expected_hdr = mp3_header.MP3Header( sampling_rate_hz=self.sampling_rate_hz) self._buffered = [] # This is the starting ms timestamp of the first block that # goes through the splitter. self._start_timestamp_ms = None # This tracks the number of elapsed ms, based on the MP3 frames # that we observe passing through the splitter. self._elapsed_frame_ms = 0 # Normally we expect that the elapsed wall-clock time and the # elapsed time based on counting up frame durations will be # approximately equal. This is not always the case, though: # when we first connect to a Barix, it will occasionally # return up to ~1s of buffered audio almost immediately. When # this happens, it can take 200-300ms before the system gets # back into equilibrium of 1 second of audio per second of # wall-clock time. Since there is no time sync in the stream # returned by the Barix, we need to introduce a fudge factor # to avoid systematic bias when assigning our own start and end # times to the messages we produce by splitting the blocks. self._start_adjustment_ms = 0
def get_test_audio_file(n): """Generates a test AudioFile object. Args: n: An integer >= 0; a distinct AudioFile object is generated for each value of n. Returns: An AudioFile object, all of whose fields have been populated with test data. """ au_file = audio_file.AudioFile() au_file.volume = n au_file.import_timestamp = 1229997336 + n au_file.fingerprint = "%016x" % n au_file.album_id = abs(hash("TALB %d" % n)) au_file.frame_count = 12345 + (n % 10) au_file.frame_size = (8 << 20) + (n << 10) au_file.mp3_header = mp3_header.MP3Header(bit_rate_kbps=192 + n, sampling_rate_hz=44100 + n, channels=(n % 4)) au_file.duration_ms = (180 + n) * 1000 # Assemble fake ID3 tags. au_file.mutagen_id3 = mutagen.id3.ID3() tpe1 = mutagen.id3.TPE1(text=["TPE1 %d" % n]) au_file.mutagen_id3.add(tpe1) tit2 = mutagen.id3.TIT2(text=["TIT2 %d" % n]) au_file.mutagen_id3.add(tit2) talb = mutagen.id3.TALB(text=["TALB %d" % n]) au_file.mutagen_id3.add(talb) trck = mutagen.id3.TRCK(text=["%d/7" % ((n % 7) + 1)]) au_file.mutagen_id3.add(trck) talb = mutagen.id3.TPUB(text=[" Bad whitespace "]) au_file.mutagen_id3.add(talb) # Finally return the thing. return au_file
def test_match(self): a = mp3_header.MP3Header(sampling_rate_hz=44100, bit_rate_kbps=128) self.assertTrue(a.match(a)) self.assertTrue(a.match(mp3_header.MP3Header(sampling_rate_hz=44100))) self.assertFalse(a.match(mp3_header.MP3Header(bit_rate_kbps=192)))
#!/usr/bin/env python ### ### A unit test for mp3_header.py ### import unittest import sys import mutagen.mp3 from chirp.common import mp3_header VALID_MP3_HEADERS = { '\xff\xfb\x90\x64': mp3_header.MP3Header(bit_rate_kbps=128, sampling_rate_hz=44100, channels=mp3_header.JOINT_STEREO, padding=False, protected=False), '\xff\xfb\xb0\x00': mp3_header.MP3Header(bit_rate_kbps=192, sampling_rate_hz=44100, channels=mp3_header.STEREO, padding=False, protected=False), '\xff\xfb\xb2\x00': mp3_header.MP3Header(bit_rate_kbps=192, sampling_rate_hz=44100, channels=mp3_header.STEREO, padding=True, protected=False), } INVALID_MP3_HEADERS = ( '', 'GARBAGE',
def test_basic_injection(self): # A mock MP3 frame. mock_frame = message.Message() mock_frame.message_type = message.FRAME mock_frame.payload = "mock frame" mock_frame.mp3_header = mp3_header.MP3Header() mock_frame.mp3_header.duration_ms = 14000 # A 14-second-long frame # A mock block. mock_block = message.Message() mock_block.message_type = message.BLOCK mock_block.payload = "mock block" src = message.MessageSource() inj = block_injector.BlockInjector(src) inj.loop_in_thread() # Add 3 frames; since we haven't set a block payload yet, the # injector should just let these pass through for _ in xrange(3): src._add_message(mock_frame) src.wait_until_empty() # Define a block to be injected. injected_one = "Injected Payload" inj.set_block_payload(injected_one) # Now add 5 more frames. A block should be injected after the first # (i.e. immediately) and fourth (i.e. after >30s elapse) frames. for _ in xrange(5): src._add_message(mock_frame) src._add_message(mock_block) # Also add our mock block. Blocks should pass through the # injector without having any effect. src.wait_until_empty() # Define another block to be injected. injected_two = "Another injected payload" inj.set_block_payload(injected_two) # Now add 5 more frames. Once again, a block should be # injected after the first and fourth frames. for _ in xrange(5): src._add_message(mock_frame) src.wait_until_empty() # Clear out the injected block. inj.set_block_payload(None) # Now add 10 more frames. Since we cleared our injected block # payload, nothing should be injected. for _ in xrange(10): src._add_message(mock_frame) # Stop the source, and wait for the injector to settle. src._add_stop_message() inj.wait() # Now pull all of the messages out of our injector, and check that # we got what we expected. all_messages = list(inj.get_all_messages()) # Our initial three frames, plus one more. for _ in xrange(4): self.assertTrue(all_messages.pop(0) is mock_frame) # Our first injected block. msg = all_messages.pop(0) self.assertEqual(message.BLOCK, msg.message_type) self.assertEqual(injected_one, msg.payload) # Three more frames. for _ in xrange(3): self.assertTrue(all_messages.pop(0) is mock_frame) # The next injected block. msg = all_messages.pop(0) self.assertEqual(message.BLOCK, msg.message_type) self.assertEqual(injected_one, msg.payload) # Another frame. self.assertTrue(all_messages.pop(0) is mock_frame) # Our mock block self.assertTrue(all_messages.pop(0) is mock_block) # Another frame. self.assertTrue(all_messages.pop(0) is mock_frame) # Another injected block, this time with our second payload. msg = all_messages.pop(0) self.assertEqual(message.BLOCK, msg.message_type) self.assertEqual(injected_two, msg.payload) # Three more frames. for _ in xrange(3): self.assertTrue(all_messages.pop(0) is mock_frame) # The next injected block. msg = all_messages.pop(0) self.assertEqual(message.BLOCK, msg.message_type) self.assertEqual(injected_two, msg.payload) # Eleven more frames. for _ in xrange(11): self.assertTrue(all_messages.pop(0) is mock_frame) # Finally, our end-of-stream marker. msg = all_messages.pop(0) self.assertTrue(msg.is_end_of_stream()) # That's all folks! self.assertEqual(0, len(all_messages))