tictacsync 0.98a0__py3-none-any.whl → 1.4.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tictacsync might be problematic. Click here for more details.
- tictacsync/device_scanner.py +62 -268
- tictacsync/entry.py +57 -166
- tictacsync/load_fieldr_reaper.py +352 -0
- tictacsync/mamconf.py +157 -0
- tictacsync/mamdav.py +642 -0
- tictacsync/mamreap.py +481 -0
- tictacsync/mamsync.py +343 -0
- tictacsync/multi2polywav.py +4 -3
- tictacsync/new-sound-resolve.py +469 -0
- tictacsync/newmix.py +483 -0
- tictacsync/remrgmx.py +6 -10
- tictacsync/splitmix.py +87 -0
- tictacsync/timeline.py +154 -98
- tictacsync/yaltc.py +359 -31
- {tictacsync-0.98a0.dist-info → tictacsync-1.4.0b0.dist-info}/METADATA +5 -6
- tictacsync-1.4.0b0.dist-info/RECORD +24 -0
- tictacsync-1.4.0b0.dist-info/entry_points.txt +7 -0
- tictacsync-0.98a0.dist-info/RECORD +0 -16
- tictacsync-0.98a0.dist-info/entry_points.txt +0 -4
- {tictacsync-0.98a0.dist-info → tictacsync-1.4.0b0.dist-info}/LICENSE +0 -0
- {tictacsync-0.98a0.dist-info → tictacsync-1.4.0b0.dist-info}/WHEEL +0 -0
- {tictacsync-0.98a0.dist-info → tictacsync-1.4.0b0.dist-info}/top_level.txt +0 -0
tictacsync/device_scanner.py
CHANGED
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
# while inotifywait --recursive -e close_write . ; do python entry.py tests/multi2/; done
|
|
4
4
|
# above for linux
|
|
5
5
|
|
|
6
|
-
TRACKSFN = 'tracks.txt'
|
|
7
|
-
SILENT_TRACK_TOKENS = '-0n'
|
|
8
6
|
|
|
9
7
|
av_file_extensions = \
|
|
10
8
|
"""webm mkv flv flv vob ogv ogg drc gif gifv mng avi MTS M2TS TS mov qt
|
|
@@ -18,8 +16,10 @@ M4V SVI 3GP 3G2 MXF ROQ NSV FLV F4V F4P F4A F4B 3GP AA AAC AAX ACT AIFF ALAC
|
|
|
18
16
|
AMR APE AU AWB DSS DVF FLAC GSM IKLAX IVS M4A M4B M4P MMF MP3 MPC MSV NMF
|
|
19
17
|
OGG OGA MOGG OPUS RA RM RAW RF64 SLN TTA VOC VOX WAV WMA WV WEBM 8SVX CDA MOV AVI BWF""".split()
|
|
20
18
|
|
|
19
|
+
audio_ext = 'aiff wav mp3'.split()
|
|
20
|
+
|
|
21
21
|
from dataclasses import dataclass
|
|
22
|
-
import ffmpeg, os, sys
|
|
22
|
+
import ffmpeg, os, sys, shutil
|
|
23
23
|
from os import listdir
|
|
24
24
|
from os.path import isfile, join, isdir
|
|
25
25
|
from collections import namedtuple
|
|
@@ -28,7 +28,7 @@ from pprint import pformat
|
|
|
28
28
|
# from collections import defaultdict
|
|
29
29
|
from loguru import logger
|
|
30
30
|
# import pathlib, os.path
|
|
31
|
-
import sox, tempfile
|
|
31
|
+
import sox, tempfile, platformdirs, filecmp
|
|
32
32
|
# from functools import reduce
|
|
33
33
|
from rich import print
|
|
34
34
|
from itertools import groupby
|
|
@@ -36,8 +36,14 @@ from itertools import groupby
|
|
|
36
36
|
# import distance
|
|
37
37
|
try:
|
|
38
38
|
from . import multi2polywav
|
|
39
|
+
from . import mamsync
|
|
40
|
+
from . import mamconf
|
|
41
|
+
from . import yaltc
|
|
39
42
|
except:
|
|
40
43
|
import multi2polywav
|
|
44
|
+
import mamsync
|
|
45
|
+
import mamconf
|
|
46
|
+
import yaltc
|
|
41
47
|
|
|
42
48
|
MCCDIR = 'SyncedMulticamClips'
|
|
43
49
|
SYNCEDFOLDER = 'SyncedMedia'
|
|
@@ -58,10 +64,9 @@ def print_grby(grby):
|
|
|
58
64
|
print('\ngrouped by %s:'%key)
|
|
59
65
|
for e in keylist:
|
|
60
66
|
print(' ', e)
|
|
61
|
-
|
|
62
67
|
@dataclass
|
|
63
68
|
class Tracks:
|
|
64
|
-
# track numbers start at 1 for first track (as needed by sox)
|
|
69
|
+
# track numbers start at 1 for first track (as needed by sox,1 Based Index)
|
|
65
70
|
ttc: int # track number of TicTacCode signal
|
|
66
71
|
unused: list # of unused tracks
|
|
67
72
|
stereomics: list # of stereo mics track tuples (Lchan#, Rchan#)
|
|
@@ -69,7 +74,9 @@ class Tracks:
|
|
|
69
74
|
others: list #of all other tags: (tag, track#) tuples
|
|
70
75
|
rawtrx: list # list of strings read from file
|
|
71
76
|
error_msg: str # 'None' if none
|
|
72
|
-
lag_values: list # list of
|
|
77
|
+
lag_values: list # list of lags in ms, entry is None if not specified.
|
|
78
|
+
# UTC_timestamp: str # to the nearest minute ISO 8601 date and time e.g.: "2007-04-05T14:30Z"
|
|
79
|
+
|
|
73
80
|
|
|
74
81
|
@dataclass
|
|
75
82
|
class Device:
|
|
@@ -210,10 +217,8 @@ class Scanner:
|
|
|
210
217
|
top_directory : string
|
|
211
218
|
String of path where to start searching for media files.
|
|
212
219
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
found_media_files: list of Media objects
|
|
220
|
+
found_media_files: list of dataclass Media instances encapsulating
|
|
221
|
+
the pathlibPath and the device (of Device dataclass).
|
|
217
222
|
"""
|
|
218
223
|
|
|
219
224
|
def __init__(
|
|
@@ -244,16 +249,7 @@ class Scanner:
|
|
|
244
249
|
CAMs = [d for d in devices if d.dev_type == 'CAM']
|
|
245
250
|
return len(set(CAMs))
|
|
246
251
|
|
|
247
|
-
def
|
|
248
|
-
"""
|
|
249
|
-
Return a device name taken from folders in path of a_media if and only
|
|
250
|
-
if all media files below it are from the same device. Goes up max two
|
|
251
|
-
levels from media; e.g., in /FOLDER2/FOLDER1/DSC00234.MOV will test up
|
|
252
|
-
to FOLDER2 as candidate.
|
|
253
|
-
"""
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
def scan_media_and_build_devices_UID(self, recursive=True):
|
|
252
|
+
def scan_media_and_build_devices_UID(self, synced_root = None):
|
|
257
253
|
"""
|
|
258
254
|
Scans Scanner.top_directory recursively for files with known audio-video
|
|
259
255
|
extensions. For each file found, a device fingerprint is obtained from
|
|
@@ -269,16 +265,36 @@ class Scanner:
|
|
|
269
265
|
Sets Scanner.input_structure = 'loose'|'ordered'
|
|
270
266
|
|
|
271
267
|
"""
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
p
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
]
|
|
280
|
-
|
|
281
|
-
|
|
268
|
+
logger.debug(f'on entry synced_root: {synced_root}')
|
|
269
|
+
if synced_root != None: # mam mode
|
|
270
|
+
p = Path(platformdirs.user_data_dir('mamsync', 'plutz'))/mamconf.LOG_FILE
|
|
271
|
+
with open(p, 'r') as fh:
|
|
272
|
+
done = set(fh.read().split()) # sets of strings of abs path
|
|
273
|
+
logger.debug(f'done clips: {pformat(done)}')
|
|
274
|
+
files = Path(self.top_directory).rglob('*')
|
|
275
|
+
clip_paths = []
|
|
276
|
+
some_done = False
|
|
277
|
+
for raw_path in files:
|
|
278
|
+
if raw_path.suffix[1:] in av_file_extensions:
|
|
279
|
+
if SYNCEDFOLDER not in raw_path.parts: # SyncedMedia
|
|
280
|
+
if MCCDIR not in raw_path.parts: # SyncedMulticamClips
|
|
281
|
+
if '_ISO' not in [part[-4:] for part in raw_path.parts]: # exclude ISO wav files
|
|
282
|
+
if synced_root != None and str(raw_path) in done:
|
|
283
|
+
logger.debug(f'{raw_path} done')
|
|
284
|
+
some_done = True
|
|
285
|
+
continue
|
|
286
|
+
else:
|
|
287
|
+
clip_paths.append(raw_path)
|
|
288
|
+
if some_done:
|
|
289
|
+
print('Somme media files were already synced...')
|
|
290
|
+
logger.debug('found media files %s'%clip_paths)
|
|
291
|
+
if len(clip_paths) == 0:
|
|
292
|
+
print('No media found, bye.')
|
|
293
|
+
sys.exit(0)
|
|
294
|
+
# self.found_media_files = []
|
|
295
|
+
# self.input_structure = 'loose'
|
|
296
|
+
# return
|
|
297
|
+
parents = [p.parent for p in clip_paths]
|
|
282
298
|
logger.debug('found parents %s'%pformat(parents))
|
|
283
299
|
# True if all elements are identical
|
|
284
300
|
AV_files_have_same_parent = parents.count(parents[0]) == len(parents)
|
|
@@ -292,7 +308,7 @@ class Scanner:
|
|
|
292
308
|
# check later if inside each folder, media have same device
|
|
293
309
|
# for now, we'll guess structure is 'ordered'
|
|
294
310
|
self.input_structure = 'ordered'
|
|
295
|
-
for p in
|
|
311
|
+
for p in clip_paths:
|
|
296
312
|
new_media = media_at_path(self.input_structure, p) # dev UID set here
|
|
297
313
|
self.found_media_files.append(new_media)
|
|
298
314
|
# for non UIDed try building UID from filenam
|
|
@@ -334,17 +350,19 @@ class Scanner:
|
|
|
334
350
|
logger.debug('Scanner.found_media_files = %s'%pformat(self.found_media_files))
|
|
335
351
|
if self.input_structure == 'ordered':
|
|
336
352
|
self._confirm_folders_have_same_device()
|
|
337
|
-
#
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
for
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
353
|
+
# [TODO] move this where Recordings have been TCed for any tracks timestamps
|
|
354
|
+
# <begin>
|
|
355
|
+
# devices = set([m.device for m in self.found_media_files])
|
|
356
|
+
# audio_devices = [d for d in devices if d.dev_type == 'REC']
|
|
357
|
+
# for recorder in audio_devices:
|
|
358
|
+
# # process tracks.txt for audio recorders
|
|
359
|
+
# recorder.tracks = self._get_tracks_from_file(recorder)
|
|
360
|
+
# # logging only:
|
|
361
|
+
# if recorder.tracks:
|
|
362
|
+
# if not all([lv == None for lv in recorder.tracks.lag_values]):
|
|
363
|
+
# logger.debug('%s has lag_values %s'%(
|
|
364
|
+
# recorder.name, recorder.tracks.lag_values))
|
|
365
|
+
# </end>
|
|
348
366
|
# check if device is in fact two parents up (and parent = ROLLxx):
|
|
349
367
|
# Group media by folder 2up and verify all media for each
|
|
350
368
|
# group have same device.
|
|
@@ -371,11 +389,10 @@ class Scanner:
|
|
|
371
389
|
for m in self.found_media_files:
|
|
372
390
|
if m.device.UID == UID:
|
|
373
391
|
m.device.name = name
|
|
374
|
-
# logger.debug('renamed device media: %s'%pformat(self.found_media_files))
|
|
375
392
|
no_name_devices = [m.device for m in self.found_media_files
|
|
376
393
|
if not m.device.name]
|
|
377
394
|
# possible if self.input_structure == 'loose'
|
|
378
|
-
def _try_name_from_metadata(media):
|
|
395
|
+
def _try_name_from_metadata(media): # unused for now
|
|
379
396
|
# search model and make from fprobe
|
|
380
397
|
file = Path(media.path)
|
|
381
398
|
logger.debug('trying to find maker model for %s'%file)
|
|
@@ -391,7 +408,6 @@ class Scanner:
|
|
|
391
408
|
# could reside in ['format','tags','com.apple.quicktime.model'],
|
|
392
409
|
# or ['format','tags','model'],
|
|
393
410
|
# or ['streams'][0]['tags']['vendor_id']) :-(
|
|
394
|
-
|
|
395
411
|
for anon_dev in no_name_devices:
|
|
396
412
|
medias = self.get_media_for_device(anon_dev)
|
|
397
413
|
guess_name = _try_name_from_files(medias)
|
|
@@ -405,50 +421,6 @@ class Scanner:
|
|
|
405
421
|
if not any(dev_is_REC): # no audio recordings!
|
|
406
422
|
print('\rNo audio recording found, nothing to sync, bye.')
|
|
407
423
|
sys.exit(0)
|
|
408
|
-
# print('devices 312 %s'%set([m.device for m in self.found_media_files]))
|
|
409
|
-
|
|
410
|
-
def _get_tracks_from_file(self, device) -> Tracks:
|
|
411
|
-
"""
|
|
412
|
-
Look for eventual track names in TRACKSFN file, stored inside the
|
|
413
|
-
recorder folder alongside the audio files. If there, returns a Tracks
|
|
414
|
-
object, if not returns None.
|
|
415
|
-
"""
|
|
416
|
-
source_audio_folder = device.folder
|
|
417
|
-
tracks_file = source_audio_folder/TRACKSFN
|
|
418
|
-
track_names = False
|
|
419
|
-
a_recording = [m for m in self.found_media_files
|
|
420
|
-
if m.device == device][0]
|
|
421
|
-
logger.debug('a_recording for device %s : %s'%(device, a_recording))
|
|
422
|
-
nchan = sox.file_info.channels(str(a_recording.path))
|
|
423
|
-
if os.path.isfile(tracks_file):
|
|
424
|
-
logger.debug('found file: %s'%(TRACKSFN))
|
|
425
|
-
tracks = self._parse_track_values(tracks_file)
|
|
426
|
-
if tracks.error_msg:
|
|
427
|
-
print('\nError parsing [gold1]%s[/gold1] file: %s, quitting.\n'%
|
|
428
|
-
(tracks_file, tracks.error_msg))
|
|
429
|
-
sys.exit(1)
|
|
430
|
-
logger.debug('parsed tracks %s'%tracks)
|
|
431
|
-
ntracks = 2*len(tracks.stereomics)
|
|
432
|
-
ntracks += len(tracks.mix)
|
|
433
|
-
ntracks += len(tracks.unused)
|
|
434
|
-
ntracks += len(tracks.others)
|
|
435
|
-
ntracks += 1 # for ttc track
|
|
436
|
-
logger.debug(' n chan: %i n tracks file: %i'%(nchan, ntracks))
|
|
437
|
-
if ntracks != nchan:
|
|
438
|
-
print('\nError parsing %s content'%tracks_file)
|
|
439
|
-
print('incoherent number of tracks, %i vs %i quitting\n'%
|
|
440
|
-
(nchan, ntracks))
|
|
441
|
-
sys.exit(1)
|
|
442
|
-
err_msg = tracks.error_msg
|
|
443
|
-
if err_msg != None:
|
|
444
|
-
print('\nError, quitting: in file %s, %s'%(tracks_file, err_msg))
|
|
445
|
-
raise Exception
|
|
446
|
-
else:
|
|
447
|
-
logger.debug('tracks object%s'%tracks)
|
|
448
|
-
return tracks
|
|
449
|
-
else:
|
|
450
|
-
logger.debug('no tracks.txt file found')
|
|
451
|
-
return None
|
|
452
424
|
|
|
453
425
|
def _confirm_folders_have_same_device(self):
|
|
454
426
|
"""
|
|
@@ -586,184 +558,6 @@ class Scanner:
|
|
|
586
558
|
logger.debug('n_CAM_folder %i'%n_CAM_folder)
|
|
587
559
|
return
|
|
588
560
|
|
|
589
|
-
def _parse_track_values(self, tracks_file) -> Tracks:
|
|
590
|
-
"""
|
|
591
|
-
read track names for naming separated ISOs
|
|
592
|
-
from tracks_file.
|
|
593
|
-
|
|
594
|
-
tokens looked for: mix; mix L; mix R; 0 and TC
|
|
595
|
-
|
|
596
|
-
repeating "mic*" pattern signals a stereo track
|
|
597
|
-
and entries will correspondingly panned into
|
|
598
|
-
a stero mix named mixL.wav and mixL.wav
|
|
599
|
-
|
|
600
|
-
mic L # spaces are ignored |
|
|
601
|
-
mic R | stereo pair
|
|
602
|
-
micB L
|
|
603
|
-
micB R
|
|
604
|
-
|
|
605
|
-
Returns: a Tracks instance:
|
|
606
|
-
# track numbers start at 1 for first track (as needed by sox)
|
|
607
|
-
ttc: int # track number of TicTacCode signal
|
|
608
|
-
unused: list # of unused tracks
|
|
609
|
-
stereomics: list # of stereo mics track tuples (Lchan#, Rchan#)
|
|
610
|
-
mix: list # of mixed tracks, if a pair, order is L than R
|
|
611
|
-
others: list #of all other tags: (tag, track#) tuples
|
|
612
|
-
rawtrx: list # list of strings read from file
|
|
613
|
-
error_msg: str # 'None' if none
|
|
614
|
-
e.g.: Tracks( ttc=2,
|
|
615
|
-
unused=[],
|
|
616
|
-
stereomics=[('mic', (4, 3)), ('mic2', (6, 5))],
|
|
617
|
-
mix=[], others=[('clics', 1)],
|
|
618
|
-
rawtrx=['clics', 'TC', 'micL', 'micR', 'mic2L;1000', 'mic2R;1000', 'mixL', 'mixR'],
|
|
619
|
-
error_msg=None, lag_values=[None, None, None, None, '1000', '1000', None, None])
|
|
620
|
-
"""
|
|
621
|
-
def _WOspace(chaine):
|
|
622
|
-
ch = [c for c in chaine if c != ' ']
|
|
623
|
-
return ''.join(ch)
|
|
624
|
-
# def _WO_LR(chaine):
|
|
625
|
-
# ch = [c for c in chaine if c not in 'LR']
|
|
626
|
-
# return ''.join(ch)
|
|
627
|
-
# def _seemsStereoMic(tag):
|
|
628
|
-
# # is tag likely a stereo pair tag?
|
|
629
|
-
# # should starts with 'mic' and ends with 'l' or 'r'
|
|
630
|
-
# return tag[1:4]=='mic' and tag[0] in 'lr'
|
|
631
|
-
file=open(tracks_file,"r")
|
|
632
|
-
whole_txt = file.read()
|
|
633
|
-
logger.debug('file %s all_lines:\n%s'%(tracks_file, whole_txt))
|
|
634
|
-
tracks_lines_wspaces = [l.split('#')[0] for l in whole_txt.splitlines()
|
|
635
|
-
if len(l) > 0 ]
|
|
636
|
-
tracks_lines = [_WOspace(l) for l in tracks_lines_wspaces if len(l) > 0 ]
|
|
637
|
-
rawtrx = [l for l in tracks_lines_wspaces if len(l) > 0 ]
|
|
638
|
-
# add index with tuples, starting at 1
|
|
639
|
-
logger.debug('tracks_lines whole: %s'%tracks_lines)
|
|
640
|
-
def _detach_lag_value(line):
|
|
641
|
-
# look for ";number" ending any line, returns a two-list
|
|
642
|
-
splt = line.split(';')
|
|
643
|
-
if len(splt) == 1:
|
|
644
|
-
splt += [None]
|
|
645
|
-
if len(splt) != 2:
|
|
646
|
-
# error
|
|
647
|
-
print('\nText error in %s, line %s has too many ";"'%(
|
|
648
|
-
tracks_file, line))
|
|
649
|
-
return splt
|
|
650
|
-
tracks_lines, lag_values = zip(*[_detach_lag_value(l) for l
|
|
651
|
-
in tracks_lines])
|
|
652
|
-
lag_values = [e for e in lag_values] # from tuple to list
|
|
653
|
-
# logger.debug('tracks_lines WO lag: %s'%tracks_lines)
|
|
654
|
-
tracks_lines = [l.lower() for l in tracks_lines]
|
|
655
|
-
logger.debug('tracks_lines lower case: %s'%tracks_lines)
|
|
656
|
-
# print(lag_values)
|
|
657
|
-
logger.debug('lag_values: %s'%lag_values)
|
|
658
|
-
tagsWOl_r = [e[:-1] for e in tracks_lines] # skip last letter
|
|
659
|
-
logger.debug('tags WO LR letter %s'%tagsWOl_r)
|
|
660
|
-
# find idx of start of pairs
|
|
661
|
-
# ['clics', 'TC', 'micL', 'micR', 'mic2L', 'mic2R', 'mixL', 'mixR']
|
|
662
|
-
def _micOrmix(a,b):
|
|
663
|
-
# test if same and mic mic or mix mix
|
|
664
|
-
if len(a) == 0:
|
|
665
|
-
return False
|
|
666
|
-
return (a == b) and (a in 'micmix')
|
|
667
|
-
pair_idx_start =[i for i, same in enumerate([_micOrmix(a,b) for a,b
|
|
668
|
-
in zip(tagsWOl_r,tagsWOl_r[1:])]) if same]
|
|
669
|
-
logger.debug('pair_idx_start %s'%pair_idx_start)
|
|
670
|
-
def LR_OK(idx):
|
|
671
|
-
# in tracks_lines, check if idx ends a LR pair
|
|
672
|
-
# delays, if any, have been removed
|
|
673
|
-
a = tracks_lines[idx][-1]
|
|
674
|
-
b = tracks_lines[idx+1][-1]
|
|
675
|
-
return a+b in ['lr', 'rl']
|
|
676
|
-
LR_OKs = [LR_OK(p) for p in pair_idx_start]
|
|
677
|
-
logger.debug('LR_OKs %s'%LR_OKs)
|
|
678
|
-
if not all(LR_OKs):
|
|
679
|
-
print('\nError in %s'%tracks_file)
|
|
680
|
-
print('Some tracks are paired but not L and R: %s'%rawtrx)
|
|
681
|
-
print('quitting...')
|
|
682
|
-
quit()
|
|
683
|
-
complete_pairs_idx = pair_idx_start + [i + 1 for i in pair_idx_start]
|
|
684
|
-
singles = set(range(len(tracks_lines))).difference(complete_pairs_idx)
|
|
685
|
-
logger.debug('complete_pairs_idx %s'%complete_pairs_idx)
|
|
686
|
-
logger.debug('singles %s'%singles)
|
|
687
|
-
singles_tag = [tracks_lines[i] for i in singles]
|
|
688
|
-
logger.debug('singles_tag %s'%singles_tag)
|
|
689
|
-
n_tc_token = sum([t == 'tc' for t in singles_tag])
|
|
690
|
-
logger.debug('n tc tags %s'%n_tc_token)
|
|
691
|
-
if n_tc_token == 0:
|
|
692
|
-
print('\nError in %s'%tracks_file)
|
|
693
|
-
print('with %s'%rawtrx)
|
|
694
|
-
print('no TC track found, quitting...')
|
|
695
|
-
quit()
|
|
696
|
-
if n_tc_token > 1:
|
|
697
|
-
print('\nError in %s'%tracks_file)
|
|
698
|
-
print('with %s'%rawtrx)
|
|
699
|
-
print('more than one TC track, quitting...')
|
|
700
|
-
quit()
|
|
701
|
-
output_tracks = Tracks(None,[],[],[],[],rawtrx,None,[])
|
|
702
|
-
output_tracks.ttc = tracks_lines.index('tc') + 1 # 1st = 1
|
|
703
|
-
logger.debug('ttc_chan %s'%output_tracks.ttc)
|
|
704
|
-
zeroed = [i+1 for i, t in enumerate(tracks_lines) if t == '0']
|
|
705
|
-
logger.debug('zeroed %s'%zeroed)
|
|
706
|
-
output_tracks.unused = zeroed
|
|
707
|
-
output_tracks.others = [(st, tracks_lines.index(st)+1) for st
|
|
708
|
-
in singles_tag if st not
|
|
709
|
-
in ['tc', 'monomix', '0']]
|
|
710
|
-
logger.debug('output_tracks.others %s'%output_tracks.others)
|
|
711
|
-
# check for monomix
|
|
712
|
-
if 'monomix' in tracks_lines:
|
|
713
|
-
output_tracks.mix = [tracks_lines.index('monomix')+1]
|
|
714
|
-
else:
|
|
715
|
-
output_tracks.mix = []
|
|
716
|
-
# check for stereo mix
|
|
717
|
-
def _findLR(i_first):
|
|
718
|
-
# returns L R indexes (+1 for sox non zero based indexing)
|
|
719
|
-
i_2nd = i_first + 1
|
|
720
|
-
a = tracks_lines[i_first][-1] # l|r at end
|
|
721
|
-
b = tracks_lines[i_2nd][-1] # l|r at end
|
|
722
|
-
if a == 'l':
|
|
723
|
-
if b == 'r':
|
|
724
|
-
# sequence is mixL mixR
|
|
725
|
-
return i_first+1, i_2nd+1
|
|
726
|
-
else:
|
|
727
|
-
print('\nError in %s'%tracks_file)
|
|
728
|
-
print('with %s'%rawtrx)
|
|
729
|
-
print('can not find stereo mix')
|
|
730
|
-
quit()
|
|
731
|
-
elif a == 'r':
|
|
732
|
-
if b == 'l':
|
|
733
|
-
# sequence is mixR mixL
|
|
734
|
-
return i_2nd+1, i_first+1
|
|
735
|
-
else:
|
|
736
|
-
print('\nError in %s'%tracks_file)
|
|
737
|
-
print('with %s'%rawtrx)
|
|
738
|
-
print('can not find stereo mix')
|
|
739
|
-
quit()
|
|
740
|
-
logger.debug('for now, output_tracks.mix %s'%output_tracks.mix)
|
|
741
|
-
mix_pair = [p for p in pair_idx_start if tracks_lines[p][1:] == 'mix']
|
|
742
|
-
if len(mix_pair) == 1:
|
|
743
|
-
# one stereo mix, remove it from other pairs
|
|
744
|
-
i = mix_pair[0]
|
|
745
|
-
LR_pair = _findLR(i)
|
|
746
|
-
logger.debug('LR_pair %s'%str(LR_pair))
|
|
747
|
-
pair_idx_start.remove(i)
|
|
748
|
-
# consistency check
|
|
749
|
-
if output_tracks.mix != []:
|
|
750
|
-
# already found a mono mix above!
|
|
751
|
-
print('\nError in %s'%tracks_file)
|
|
752
|
-
print('with %s'%rawtrx)
|
|
753
|
-
print('found a mono mix AND a stereo mix')
|
|
754
|
-
quit()
|
|
755
|
-
output_tracks.mix = LR_pair
|
|
756
|
-
logger.debug('finally, output_tracks.mix %s'%str(output_tracks.mix))
|
|
757
|
-
logger.debug('remaining pairs %s'%pair_idx_start)
|
|
758
|
-
# those are stereo pairs
|
|
759
|
-
stereo_pairs = []
|
|
760
|
-
for first_in_pair in pair_idx_start:
|
|
761
|
-
suffix = tracks_lines[first_in_pair][:-1]
|
|
762
|
-
stereo_pairs.append((suffix, _findLR(first_in_pair)))
|
|
763
|
-
logger.debug('stereo_pairs %s'%stereo_pairs)
|
|
764
|
-
output_tracks.stereomics = stereo_pairs
|
|
765
|
-
logger.debug('finished: %s'%output_tracks)
|
|
766
|
-
return output_tracks
|
|
767
561
|
|
|
768
562
|
|
|
769
563
|
|