forked from spadev/cdrip-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fixoffset.py
executable file
·125 lines (104 loc) · 4 KB
/
fixoffset.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/python
from __future__ import print_function
import os
import sys
import signal
from subprocess import Popen, PIPE
from argparse import ArgumentParser
from os.path import basename, dirname, exists, splitext, join
import utils
BIN = {'metaflac': None,
'ffprobe': 'avprobe',
'sox': None,
'splitaudio': None,
}
PROGNAME = 'fixoffset'
VERSION = '0.2'
REQUIRED = ['ffprope', 'sox', 'splitaudio']
PROCS = []
TEMPDIRS = []
def process_arguments():
parser = \
ArgumentParser(description='Fix sample offsets of CD rips.',
prog=PROGNAME)
parser.add_argument('offset', help='offset to correct', type=int)
parser.add_argument('paths', metavar='file', nargs='+',
type=utils.isfile,
help='lossless audio file')
parser.add_argument('-f', '--format',
default='wav',
choices=['wav', 'flac', 'aiff'],
help='format of generated output file(s)')
utils.add_common_arguments(parser, VERSION)
return parser.parse_args()
def fix_offset(sources, offset, fmt='wav', verbose=False):
output_dir = None
i = 0
while not output_dir:
a = '_%i' % i if i > 0 else ''
output_dir = join(dirname(sources[0]['path']),
'fixedoffset_%i%s' % (offset, a))
if exists(output_dir):
output_dir = None
i += 1
TEMPDIRS.append(output_dir)
os.mkdir(output_dir)
common_args = ['-t', 'raw',
'-b16',
'-c2',
'-r44100',
'-e', 'signed-integer',
'-',
]
sox_args = [BIN['sox']]+[s['path'] for s in sources]+common_args
total_samples = sum([s['num_samples'] for s in sources])
if offset > 0:
sox_args += ['pad', '0', '%is' % offset,
'trim', '%is' % offset, '%is' % total_samples]
else:
sox_args += ['pad', '%is' % -offset, '0',
'trim', '0', '%is' % total_samples]
splitaudio_args = [BIN['splitaudio'], '2' if fmt == 'aiff' else '1' if fmt == 'flac' else '0']
for s in sources:
splitaudio_args += [str(s['num_samples'])]
if verbose:
print('format: %s' % fmt)
print('%s | %s' % (' '.join(sox_args), ' '.join(splitaudio_args)))
devnull = open(os.devnull, 'w')
PROCS.append(Popen(sox_args, stdout=PIPE, stderr=devnull))
PROCS.append(Popen(splitaudio_args, stdin=PROCS[-1].stdout, cwd=output_dir))
p = PROCS[-1]
while p.poll() is None:
utils.show_status('Fixing offset (%i samples)', offset)
out, err = p.communicate()
devnull.close()
print('', file=sys.stderr, end='\n')
for pr in PROCS:
if pr.returncode:
raise utils.SubprocessError('sox had an error (returned %i)' %
pr.returncode)
TEMPDIRS.remove(output_dir)
for i, s in enumerate(sources):
src = join(output_dir, 'fixed%03i.%s' % (i,fmt))
outpath = join(output_dir,
'%s.%s' % (splitext(basename(s['path']))[0], fmt))
os.rename(src, outpath)
return output_dir
def print_summary(sources, output_dir):
s = 's' if len(sources) > 1 else ''
print('Fixed file%s saved to directory %s' % (s, output_dir))
def main(options):
utils.check_dependencies(BIN, REQUIRED)
sources = [dict(path=p) for p in options.paths]
for s in sources:
s['num_samples'] = utils.get_num_samples(BIN, s['path'])
if s['num_samples'] % 588 != 0:
msg = "%s not from CD (%i samples)\n" % (s['path'],
s['num_samples'])
raise utils.NotFromCDError(msg)
output_dir = fix_offset(sources, options.offset, options.format,
options.verbose)
print_summary(sources, output_dir)
return 0
if __name__ == '__main__':
utils.execute(main, process_arguments, PROCS, tempdirs=TEMPDIRS)