-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcdmaker.py
More file actions
executable file
·59 lines (47 loc) · 1.72 KB
/
Copy pathcdmaker.py
File metadata and controls
executable file
·59 lines (47 loc) · 1.72 KB
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
#!/usr/bin/python3
# Copyright (c) 2025 iiPython
# Modules
import sys
import wave
from math import ceil
from pathlib import Path
# Initialization
args = [Path(_) for _ in sys.argv]
if len(args) < 4:
print(f"cdmaker (c) 2025 iiPython\nusage: ./{args[0].name} <output bin> <output cue> <input wav(s)>")
exit(1)
# Constants
CD_SECTOR_SIZE = 2352
CD_FRAMES_PER_SECOND = 75
# Handle everything
def main(bin_file: Path, cue_file: Path, *wav_files: Path) -> None:
def pad(pcm_data: bytes) -> bytes:
remainder = len(pcm_data) % 2352
return (pcm_data + b"\x00" * (2352 - remainder)) if remainder else pcm_data
def calculate_index(offset: int) -> str:
def clean(item: float) -> str:
return str(int(item)).zfill(2)
seconds = offset // 75
minutes = seconds // 60
return f"{clean(minutes)}:{clean(seconds - (minutes * 60))}:{clean(offset - ((seconds - (minutes * 60)) * 75) - (minutes * (75 * 60)))}"
# Initialize .CUE file
cue_lines = [f"FILE \"{bin_file.name}\" BINARY"]
# Generate .BIN file
bin_data, offset = bytearray(), 0
for index, file in enumerate(wav_files):
with wave.open(str(file), "rb") as wav:
number_frames = wav.getnframes()
pcm_data = wav.readframes(number_frames)
bin_data.extend(pad(pcm_data))
# Save track to .CUE
cue_lines += [
f" TRACK {str(index + 1).zfill(2)} AUDIO",
f" TITLE \"{file.with_suffix('').name}\"",
f" INDEX 01 {calculate_index(offset)}"
]
offset += ceil(number_frames // 588)
# Cleanup
bin_file.write_bytes(bin_data)
cue_file.write_text("\n".join(cue_lines))
if __name__ == "__main__":
main(*args[1:])