mirror of
https://github.com/ssb22/bits-and-bobs.git
synced 2023-06-08 10:22:44 +00:00
79 lines
3.4 KiB
Python
79 lines
3.4 KiB
Python
#!/usr/bin/env python
|
|
# (should work in either Python 2 or Python 3)
|
|
|
|
# cdrdao track padder, 2012, 2020 Silas S. Brown. Public domain.
|
|
# Version 1.4
|
|
|
|
# Where to find history:
|
|
# on GitHub at https://github.com/ssb22/bits-and-bobs
|
|
# and on GitLab at https://gitlab.com/ssb22/bits-and-bobs
|
|
# and on BitBucket https://bitbucket.org/ssb22/bits-and-bobs
|
|
# and at https://gitlab.developers.cam.ac.uk/ssb22/bits-and-bobs
|
|
# and in China: https://gitee.com/ssb22/bits-and-bobs
|
|
|
|
cd_frames = 359845 # 79min 57sec 70/75 frames, typical for 700M "80min" CDs
|
|
|
|
absolute_minimum_silent_frames = 2 * 75
|
|
|
|
import os,sys,os.path
|
|
if len(sys.argv) < 2:
|
|
print ("Syntax: cdrdao.py sound-files")
|
|
sys.exit(1)
|
|
|
|
filelist = []
|
|
frames_this_cd = 0 ; cd_starts = [] # 1st try: pack them as they come
|
|
total_frames = 0
|
|
for f in sys.argv[1:]:
|
|
f2 = "rawfile%d" % len(filelist)
|
|
print ("Converting "+f)
|
|
ret = os.system("sox \"%s\" -t raw -B -b 16 -e signed-integer -c 2 -r 44100 %s" % (f,f2))
|
|
assert not ret, "sox error"
|
|
frames = int((os.stat(f2).st_size+2351)/2352) # round up
|
|
if frames_this_cd: frames_this_cd += absolute_minimum_silent_frames
|
|
if not cd_starts or frames_this_cd + frames > cd_frames:
|
|
cd_starts.append(len(filelist))
|
|
frames_this_cd = 0
|
|
frames_this_cd += frames
|
|
total_frames += frames
|
|
f = os.path.basename(f)
|
|
if '.' in f: f=f[:f.rindex('.')]
|
|
filelist.append((frames,f2,f))
|
|
|
|
print ("Fitting onto %d CDs" % len(cd_starts))
|
|
|
|
average_frames = total_frames/len(cd_starts)
|
|
i = len(cd_starts)-1 ; topF = len(filelist)
|
|
def totframes(start,end): return sum([f for f,f2,_ in filelist[start:end]])
|
|
while i:
|
|
# if CD 'i' has above average gaps (below average total
|
|
# frames), try to get it as close as possible to the
|
|
# average by pulling tracks over from CD i-1
|
|
while totframes(cd_starts[i],topF) < average_frames and abs(average_frames-totframes(cd_starts[i],topF)) > abs(average_frames-totframes(cd_starts[i]-1,topF)) and totframes(cd_starts[i]-1,topF) < cd_frames-absolute_minimum_silent_frames*(topF-cd_starts[i]-2): # (-2 as 1st track doesn't need lead-in)
|
|
cd_starts[i] -= 1
|
|
assert cd_starts[i], "non-1st CD reached 0 ?!?"
|
|
j = i
|
|
while j and cd_starts[j-1] >= cd_starts[j]:
|
|
j -= 1
|
|
assert cd_starts[j],"second CD reached 0 ?!?"
|
|
cd_starts[j] -= 1
|
|
topF = cd_starts[i]
|
|
i -= 1
|
|
|
|
for i in range(len(cd_starts)):
|
|
fn = "cd%d.toc" % (i+1,)
|
|
o=open(fn,"w")
|
|
if i==len(cd_starts)-1: topF = len(filelist)
|
|
else: topF = cd_starts[i+1]
|
|
o.write("CD_DA\nCD_TEXT {\n LANGUAGE_MAP {\n 0 : EN\n }\n LANGUAGE 0 {\n TITLE \"CD %d (%s to %s)\"\n }\n}\n\n" % (i,filelist[cd_starts[i]][2],filelist[topF-1][2]))
|
|
pregap = 0
|
|
for track in range(cd_starts[i],topF):
|
|
if pregap: pgstr = "PREGAP %d:%d:%d\n" % (pregap/(60*75),(pregap%(60*75))/75,(pregap%75))
|
|
else: pgstr = ""
|
|
o.write("TRACK AUDIO\nCD_TEXT {\n LANGUAGE 0 {\n TITLE \"%s\"\n }\n}\n%sFILE \"%s\" 0\n\n" % (filelist[track][2],pgstr,filelist[track][1]))
|
|
if not pregap and topF>cd_starts[i]+1: pregap = (cd_frames-totframes(track,topF))/(topF-cd_starts[i]-1)
|
|
o.close()
|
|
if cd_starts[i]: trackinfo="-%d" % cd_starts[i]
|
|
else: trackinfo=""
|
|
print ("You can now do: cdrdao write "+fn+(" # (%d to %d, track=number%s)" % (cd_starts[i]+1,topF,trackinfo)))
|
|
print ("When finished, you can do: rm *.toc rawfile*")
|