-
Notifications
You must be signed in to change notification settings - Fork 153
/
utils.py
111 lines (85 loc) · 2.56 KB
/
utils.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
import struct
from os import SEEK_CUR
def lz4_decompress(data, size):
try:
from lz4.block import decompress
except ImportError:
raise RuntimeError("python-lz4 >= 0.9 is required to read UnityFS files")
return decompress(data, size)
def extract_audioclip_samples(d) -> dict:
"""
Extract all the sample data from an AudioClip and
convert it from FSB5 if needed.
"""
ret = {}
if not d.data:
# eg. StreamedResource not available
return {}
try:
from fsb5 import FSB5
except ImportError as e:
raise RuntimeError("python-fsb5 is required to extract AudioClip")
af = FSB5(d.data)
for i, sample in enumerate(af.samples):
if i > 0:
filename = "%s-%i.%s" % (d.name, i, af.get_sample_extension())
else:
filename = "%s.%s" % (d.name, af.get_sample_extension())
try:
sample = af.rebuild_sample(sample)
except ValueError as e:
print("WARNING: Could not extract %r (%s)" % (d, e))
continue
ret[filename] = sample
return ret
class BinaryReader:
def __init__(self, buf, endian="<"):
self.buf = buf
self.endian = endian
def align(self):
old = self.tell()
new = (old + 3) & -4
if new > old:
self.seek(new - old, SEEK_CUR)
def read(self, *args):
return self.buf.read(*args)
def seek(self, *args):
return self.buf.seek(*args)
def tell(self):
return self.buf.tell()
def read_string(self, size=None, encoding="utf-8"):
if size is None:
ret = self.read_cstring()
else:
ret = struct.unpack(self.endian + "%is" % (size), self.read(size))[0]
try:
return ret.decode(encoding)
except UnicodeDecodeError:
return ret
def read_cstring(self) -> bytes:
ret = []
c = b""
while c != b"\0":
ret.append(c)
c = self.read(1)
if not c:
raise ValueError("Unterminated string: %r" % (ret))
return b"".join(ret)
def read_boolean(self) -> bool:
return bool(struct.unpack(self.endian + "b", self.read(1))[0])
def read_byte(self) -> int:
return struct.unpack(self.endian + "b", self.read(1))[0]
def read_ubyte(self) -> int:
return struct.unpack(self.endian + "B", self.read(1))[0]
def read_int16(self) -> int:
return struct.unpack(self.endian + "h", self.read(2))[0]
def read_uint16(self) -> int:
return struct.unpack(self.endian + "H", self.read(2))[0]
def read_int(self) -> int:
return struct.unpack(self.endian + "i", self.read(4))[0]
def read_uint(self) -> int:
return struct.unpack(self.endian + "I", self.read(4))[0]
def read_float(self) -> float:
return struct.unpack(self.endian + "f", self.read(4))[0]
def read_int64(self) -> int:
return struct.unpack(self.endian + "q", self.read(8))[0]