def test_drop_frame(self): tc = Timecode('29.97', '13:36:59;29') timecode = tc.next() self.assertEqual("13:37:00;02", timecode.__str__()) tc = Timecode('59.94', '13:36:59;59') self.assertEqual("13:36:59;59", tc.__str__()) timecode = tc.next() self.assertEqual("13:37:00;04", timecode.__str__()) tc = Timecode('59.94', '13:39:59;59') timecode = tc.next() self.assertEqual("13:40:00;00", timecode.__str__()) tc = Timecode('29.97', '13:39:59;29') timecode = tc.next() self.assertEqual("13:40:00;00", timecode.__str__())
def run(fps, realtime=True, duration=None, renderer=print): tc1 = Timecode(fps, '00:00:00:00') frame_size = 1 / fps app_start = time.time() while 1: if not realtime: tc1.next() renderer(tc1) else: now_time = time.time() - app_start if now_time > tc1.frame_number * frame_size: renderer(tc1) tc1.next() time.sleep(0.001) if tc1.frame_number * frame_size > duration: break
def test_drop_frame(self): tc = Timecode('29.97', '13:36:59:29') timecode = tc.next() self.assertEqual("13:37:00:02", timecode.__str__()) tc = Timecode('59.94', '13:36:59:59') self.assertEqual("13:36:59:59", tc.__str__()) timecode = tc.next() self.assertEqual("13:37:00:04", timecode.__str__()) tc = Timecode('59.94', '13:39:59:59') timecode = tc.next() self.assertEqual("13:40:00:00", timecode.__str__()) tc = Timecode('29.97', '13:39:59:29') timecode = tc.next() self.assertEqual("13:40:00:00", timecode.__str__())
def test_iteration(self): tc = Timecode('29.97', '03:36:09;23') self.assertEqual("03:36:09;23", tc) for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:11;23", t) self.assertEqual(388764, tc.frames) tc = Timecode('29.97', '03:36:09;23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:11;23", t) self.assertEqual(388764, tc.frames) tc = Timecode('30', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:11:23", t) self.assertEqual(389154, tc.frames) tc = Timecode('25', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:12:08", t) self.assertEqual(324309, tc.frames) tc = Timecode('59.94', '03:36:09;23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:10;23", t) self.assertEqual(777444, tc.frames) tc = Timecode('60', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:10:23", t) self.assertEqual(778224, tc.frames) tc = Timecode('59.94', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:10:23", t) self.assertEqual(777444, tc.frames) tc = Timecode('23.98', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:12:11", t) self.assertEqual(311340, tc.frames) tc = Timecode('24', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:12:11", t) self.assertEqual(311340, tc.frames) tc = Timecode('ms', '03:36:09.230') for x in range(60): t = tc.next() self.assertIsNotNone(t) self.assertEqual('03:36:09.290', t) self.assertEqual(12969291, tc.frames) tc = Timecode('24', frames=12000) for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("00:08:22:11", t) self.assertEqual(12060, tc.frames)
def make_ltc_wave(fps=24, duration=60, sample_rate=44100, sample_bits=8): max_val = 2**sample_bits - 1 # 2^8 - 1 = 0b11111111 # each frame has 80 bytes, and each byte is represented by two "notes" # to represent a 0, we use FF FF or 00 00 # to represent a 1, we use FF 00 or 00 FF # every double-note must start with the opposite of the previous half note # generate the timecode data for the entire duration tc = Timecode(fps, '00:01:00:00') tc_encoded = [] print('Generating Timecode Stream') for i in range(int(duration * fps) + 1): # this is the first frame e = ltc_encode(tc, as_string=True) tc_encoded.append(e) tc.next() # lists are faster than string concatenation even when joining them at the end tc_encoded = ''.join(tc_encoded) print('Generating "Double Pulse" Data Stream') double_pulse_data = '' next_is_up = True for byte_char in tc_encoded: if byte_char == '0': if next_is_up: double_pulse_data += '11' else: double_pulse_data += '00' next_is_up = not next_is_up else: double_pulse_data += '10' if next_is_up else '01' # at this point, we have a string of zeroes and ones # now, we just need to map them to pulse data over the # duration of the data stream print('Creating PCM Data Stream') total_samples = int(sample_rate * duration) data = bytearray(total_samples) for sample in range(total_samples): ratio = sample / total_samples pct = int(ratio * 100) if sample % 1000 == 0: print(f' COMPUTING: {total_samples}:{sample} -- {pct}%', end='\r') # how far along in the bytestream are we? # there are 160 double-pulses per frame double_pulse_position = len(double_pulse_data) * ratio dpp_intpart = int(double_pulse_position) this_val = int(double_pulse_data[dpp_intpart]) # # This code was used when I thought I needed to smooth # # out the pulses. Turns out that smoothing isn't needed # dpp_fracpart = double_pulse_position - dpp_intpart # try: # next_val = int(double_pulse_data[dpp_intpart+1]) # except: # next_val = this_val # #scale the value # if dpp_fracpart < .5: # dpp_fracpart *= .5 # else: # dpp_fracpart += (1 - dpp_fracpart) * .5 # inc = (next_val - this_val) * dpp_fracpart # scaled_val = int((this_val + inc) * max_val) # data[sample] = scaled_val data[sample] = this_val * max_val print() print('Writing WAV File') wave_file_name = 'ltc-{}fps-{}secs.wav'.format(fps, duration) f = open(wave_file_name, 'wb') write_wave_file(f, data) f.close()
# if dpp_fracpart < .5: # dpp_fracpart *= .5 # else: # dpp_fracpart += (1 - dpp_fracpart) * .5 # inc = (next_val - this_val) * dpp_fracpart # scaled_val = int((this_val + inc) * max_val) # data[sample] = scaled_val data[sample] = this_val * max_val print() print('Writing WAV File') wave_file_name = 'ltc-{}fps-{}secs.wav'.format(fps, duration) f = open(wave_file_name, 'wb') write_wave_file(f, data) f.close() tc = Timecode(24, '00:01:00:00') for i in range(24 * 100): tc.next() b = mtc_full_frame(tc) tmp = [] for j in range(10): tmp.append(hex(b[j])) print('full frame: ' + ' '.join(tmp)) for j in range(8): qf = mtc_quarter_frame(tc, j) print('{} {}'.format(hex((qf[0])), hex((qf[1]))))
def test_iteration(self): tc = Timecode('29.97', '03:36:09:23') self.assertEqual("03:36:09:23", tc) for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:11:23", t) self.assertEqual(388764, tc.frames) tc = Timecode('29.97', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:11:23", t) self.assertEqual(388764, tc.frames) tc = Timecode('30', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:11:23", t) self.assertEqual(389154, tc.frames) tc = Timecode('25', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:12:08", t) self.assertEqual(324309, tc.frames) tc = Timecode('59.94', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:10:23", t) self.assertEqual(777444, tc.frames) tc = Timecode('60', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:10:23", t) self.assertEqual(778224, tc.frames) tc = Timecode('59.94', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:10:23", t) self.assertEqual(777444, tc.frames) tc = Timecode('23.98', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:12:11", t) self.assertEqual(311340, tc.frames) tc = Timecode('24', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:12:11", t) self.assertEqual(311340, tc.frames) tc = Timecode('ms', '03:36:09:230') for x in range(60): t = tc.next() self.assertIsNotNone(t) self.assertEqual('03:36:09:290', t) self.assertEqual(12969291, tc.frames) tc = Timecode('24', frames=12000) for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("00:08:22:11", t) self.assertEqual(12060, tc.frames)
def start_mtc(outport, fps, start_string, duration, click_data=None): print(f'STARTING MTC: {fps}fps {start_string} {duration}s') tc = Timecode(fps, start_string) frametime = 1 / float(fps) start = time.time() end = start + int(duration) next_frame_time = start + tc.frame_number * frametime next_full_frame_time = start next_click_time = start do_click = False runuptimes = [] if click_data is not None: in_runup = True do_click = True clicktime = 60 / float(click_data['bpm']) click_divs = int(click_data['division']) click_bnote = int(click_data['base_note']) click_anote = int(click_data['accent_note']) if click_divs == 3: runuptimes = [ start, start + clicktime * 2, start + clicktime * 3, start + clicktime * 5 ] for i in range(6, click_divs + 6): runuptimes.append(start + clicktime * i) elif click_divs == 4: runuptimes = [start, start + clicktime * 2] for i in range(4, click_divs + 4): runuptimes.append(start + clicktime * i) elif click_divs == 6: runuptimes = [start, start + clicktime * 3] for i in range(6, click_divs + 6): runuptimes.append(start + clicktime * i) else: runuptimes = [] for i in range(click_divs * 2): runuptimes.append(start + clicktime * i) runuptime = runuptimes[-1] + clicktime start = runuptime next_click_time = runuptime click_counter = 0 while len(runuptimes) > 0: now = time.time() if now >= runuptimes[0]: send_click(outport, click_anote + 12) runuptimes = runuptimes[1:] else: time.sleep(runuptimes[0] - now) print('beginning') while 1: now = time.time() if do_click and now >= next_click_time: if click_counter % click_divs == 0: send_click(outport, click_anote) else: send_click(outport, click_bnote) click_counter += 1 next_click_time = start + click_counter * clicktime # send mtc if now > end: print('ENDING') break elif now >= next_full_frame_time: tc.next() send_full_frame(outport, tc) next_frame_time = start + tc.frame_number * frametime next_full_frame_time = next_frame_time + 10 * frametime elif now > next_frame_time: tc.next() send_quarter_frames(outport, tc) next_frame_time = start + tc.frame_number * frametime wait_until = min(next_frame_time, next_click_time, next_full_frame_time) time.sleep(max(0, wait_until - time.time()))
def test_iteration(self): tc = Timecode('29.97', '03:36:09;23') assert tc == "03:36:09;23" for x in range(60): t = tc.next() self.assertTrue(t) assert t == "03:36:11;23" assert tc.frames == 388764 # tc = Timecode('29.97', '03:36:09;23', force_drop_frame_to=False) # assert tc == '03:36:09;23' # for x in range(60): # t = tc.next() # self.assertTrue(t) # assert t == '' # assert tc.frames == 388764 tc = Timecode('29.97', '03:36:09;23') for x in range(60): t = tc.next() self.assertTrue(t) assert t == "03:36:11;23" self.assertEqual(388764, tc.frames) tc = Timecode('30', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) assert t == "03:36:11:23" self.assertEqual(389154, tc.frames) tc = Timecode('25', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) assert t == "03:36:12:08" self.assertEqual(324309, tc.frames) tc = Timecode('59.94', '03:36:09;23') for x in range(60): t = tc.next() self.assertTrue(t) assert t == "03:36:10;23" self.assertEqual(777444, tc.frames) tc = Timecode('60', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) assert t == "03:36:10:23" self.assertEqual(778224, tc.frames) tc = Timecode('59.94', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) assert t == "03:36:10:23" self.assertEqual(777444, tc.frames) tc = Timecode('23.98', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) assert t == "03:36:12:11" self.assertEqual(311340, tc.frames) tc = Timecode('24', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) assert t == "03:36:12:11" self.assertEqual(311340, tc.frames) tc = Timecode('ms', '03:36:09.230') for x in range(60): t = tc.next() self.assertIsNotNone(t) assert t == '03:36:09.290' self.assertEqual(12969291, tc.frames) tc = Timecode('24', frames=12000) for x in range(60): t = tc.next() self.assertTrue(t) assert t == "00:08:22:11" self.assertEqual(12060, tc.frames)