mirror of
https://github.com/Escartem/AnimeWwise.git
synced 2026-06-04 23:40:25 +08:00
improve error handling
This commit is contained in:
@@ -153,7 +153,7 @@ class WwiseExtract:
|
|||||||
}
|
}
|
||||||
|
|
||||||
wem_data = data[file_data["offset"]:file_data["offset"]+file_data["size"]]
|
wem_data = data[file_data["offset"]:file_data["offset"]+file_data["size"]]
|
||||||
parsed_wem = wwise.parse_wwise(FileReader(io.BytesIO(wem_data), "little"))
|
parsed_wem = wwise.parse_wwise(FileReader(io.BytesIO(wem_data), "little", name=f"{file[0]}:{file[1]}"))
|
||||||
|
|
||||||
file_data["metadata"] = parsed_wem
|
file_data["metadata"] = parsed_wem
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ class FileReader:
|
|||||||
File reader for files, not much too say
|
File reader for files, not much too say
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, file, endianness:str):
|
def __init__(self, file, endianness:str, name:str=None):
|
||||||
self.stream = file
|
self.stream = file
|
||||||
self.endianness = endianness
|
self.endianness = endianness
|
||||||
|
if name:
|
||||||
|
self.name = name
|
||||||
|
|
||||||
def _read(self, mode:str, bufferLength:int, endianness:str=None) -> bytes:
|
def _read(self, mode:str, bufferLength:int, endianness:str=None) -> bytes:
|
||||||
# endianness override
|
# endianness override
|
||||||
@@ -76,3 +78,8 @@ class FileReader:
|
|||||||
|
|
||||||
def GetRemainingLength(self) -> int:
|
def GetRemainingLength(self) -> int:
|
||||||
return self.GetStreamLength() - self.GetBufferPos()
|
return self.GetStreamLength() - self.GetBufferPos()
|
||||||
|
|
||||||
|
def GetName(self) -> str:
|
||||||
|
if self.name:
|
||||||
|
return self.name
|
||||||
|
return ""
|
||||||
|
|||||||
7
gui.ui
7
gui.ui
@@ -186,8 +186,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>10</x>
|
<x>10</x>
|
||||||
<y>10</y>
|
<y>10</y>
|
||||||
<width>1166</width>
|
<width>1041</width>
|
||||||
<height>111</height>
|
<height>131</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="hdiffGrid">
|
<layout class="QGridLayout" name="hdiffGrid">
|
||||||
@@ -233,6 +233,9 @@ Subfolders are disabled in this mode, make sure to be in the correct place. For
|
|||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|||||||
133
wwise.py
133
wwise.py
@@ -2,60 +2,14 @@
|
|||||||
# thanks to hcs and bnnm work
|
# thanks to hcs and bnnm work
|
||||||
|
|
||||||
def parse_wwise(reader):
|
def parse_wwise(reader):
|
||||||
header = reader.ReadBytes(4)
|
# default meta config
|
||||||
|
|
||||||
# endian check header
|
|
||||||
if header == b"RIFX":
|
|
||||||
reader.endianness = "big"
|
|
||||||
elif header == b"RIFF":
|
|
||||||
reader.endianness = "little"
|
|
||||||
else:
|
|
||||||
raise Exception("invalid header")
|
|
||||||
|
|
||||||
# additional check
|
|
||||||
reader.SetBufferPos(0x08)
|
|
||||||
check = reader.ReadBytes(4)
|
|
||||||
|
|
||||||
if check != b"WAVE" and check != "XWMA":
|
|
||||||
raise Exception("invalid file")
|
|
||||||
|
|
||||||
# read chunks
|
|
||||||
reader.SetBufferPos(0x0C)
|
|
||||||
|
|
||||||
chunks = {}
|
|
||||||
|
|
||||||
while reader.GetBufferPos() < reader.GetStreamLength():
|
|
||||||
# relevants chunks types
|
|
||||||
# "fmt "
|
|
||||||
# "data"
|
|
||||||
# "JUNK"
|
|
||||||
|
|
||||||
chunk_type = reader.ReadBytes(4)
|
|
||||||
|
|
||||||
if chunk_type not in [b"fmt ", b"JUNK", b"data"]:
|
|
||||||
raise Exception("invalid chunk")
|
|
||||||
|
|
||||||
formatted_chunk_type = chunk_type.decode("utf-8").replace(" ", "")
|
|
||||||
chunk_length = reader.ReadUInt32()
|
|
||||||
chunks[formatted_chunk_type] = {
|
|
||||||
"length": chunk_length,
|
|
||||||
"offset": reader.GetBufferPos(),
|
|
||||||
"data": reader.ReadBytes(chunk_length)
|
|
||||||
}
|
|
||||||
|
|
||||||
# reader fmt header
|
|
||||||
if chunks["fmt"]["length"] < 0x10:
|
|
||||||
raise Exception("invalid fmt chunk length")
|
|
||||||
|
|
||||||
reader.SetBufferPos(chunks["fmt"]["offset"])
|
|
||||||
|
|
||||||
metadata = {
|
metadata = {
|
||||||
"format": reader.ReadUInt16(),
|
"format": 0,
|
||||||
"channels": reader.ReadUInt16(),
|
"channels": 0,
|
||||||
"sampleRate": reader.ReadUInt32(),
|
"sampleRate": 0,
|
||||||
"avgBitrate": reader.ReadUInt32(),
|
"avgBitrate": 0,
|
||||||
"blockSize": reader.ReadUInt16(),
|
"blockSize": 0,
|
||||||
"bitsPerSample": reader.ReadUInt16(),
|
"bitsPerSample": 0,
|
||||||
"extraSize": 0,
|
"extraSize": 0,
|
||||||
"channelLayout": None,
|
"channelLayout": None,
|
||||||
"channelType": None,
|
"channelType": None,
|
||||||
@@ -64,9 +18,70 @@ def parse_wwise(reader):
|
|||||||
"layoutType": None,
|
"layoutType": None,
|
||||||
"interleaveBlockSize": None,
|
"interleaveBlockSize": None,
|
||||||
"numSamples": None,
|
"numSamples": None,
|
||||||
"duration": None
|
"duration": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if reader.GetStreamLength() == 0:
|
||||||
|
print(f"[WARNING] null stream size at {reader.GetName()}, unreadable block")
|
||||||
|
return metadata
|
||||||
|
|
||||||
|
header = reader.ReadBytes(4)
|
||||||
|
|
||||||
|
# endian check header
|
||||||
|
if header == b"RIFX":
|
||||||
|
reader.endianness = "big"
|
||||||
|
elif header == b"RIFF":
|
||||||
|
reader.endianness = "little"
|
||||||
|
else:
|
||||||
|
print(f"[WARNING] invalid header {header} at {reader.GetName()}, assuming unreadable")
|
||||||
|
return metadata
|
||||||
|
|
||||||
|
# additional check
|
||||||
|
reader.SetBufferPos(0x08)
|
||||||
|
check = reader.ReadBytes(4)
|
||||||
|
|
||||||
|
if check != b"WAVE" and check != "XWMA":
|
||||||
|
print(f"[WARNING] invalid check mark {check}, assuming unreadable")
|
||||||
|
return metadata
|
||||||
|
|
||||||
|
# read chunks
|
||||||
|
reader.SetBufferPos(0x0C)
|
||||||
|
|
||||||
|
chunks = {}
|
||||||
|
|
||||||
|
while reader.GetBufferPos() < reader.GetStreamLength():
|
||||||
|
chunk_type = reader.ReadBytes(4)
|
||||||
|
|
||||||
|
if chunk_type not in [b"fmt ", b"JUNK", b"data", b"akd ", b"cue ", b"LIST", b"smpl"]:
|
||||||
|
print(f"[WARNING] unexpected chunk {chunk_type} at {reader.GetName()}")
|
||||||
|
|
||||||
|
formatted_chunk_type = chunk_type.decode("utf-8").replace(" ", "")
|
||||||
|
chunk_length = reader.ReadUInt32()
|
||||||
|
|
||||||
|
if chunk_type == b"data" and chunk_length > reader.GetRemainingLength():
|
||||||
|
chunk_length = reader.GetRemainingLength()
|
||||||
|
|
||||||
|
chunks[formatted_chunk_type] = {
|
||||||
|
"length": chunk_length,
|
||||||
|
"offset": reader.GetBufferPos(),
|
||||||
|
"data": reader.ReadBytes(chunk_length)
|
||||||
|
}
|
||||||
|
|
||||||
|
# reader fmt header
|
||||||
|
fmt_length = chunks["fmt"]["length"]
|
||||||
|
if fmt_length < 0x10:
|
||||||
|
print(f"[WARNING] invalid fmt chunk length {fmt_length} at {reader.GetName()}, skipping")
|
||||||
|
return metadata
|
||||||
|
|
||||||
|
reader.SetBufferPos(chunks["fmt"]["offset"])
|
||||||
|
|
||||||
|
metadata["format"] = reader.ReadUInt16()
|
||||||
|
metadata["channels"] = reader.ReadUInt16()
|
||||||
|
metadata["sampleRate"] = reader.ReadUInt32()
|
||||||
|
metadata["avgBitrate"] = reader.ReadUInt32()
|
||||||
|
metadata["blockSize"] = reader.ReadUInt16()
|
||||||
|
metadata["bitsPerSample"] = reader.ReadUInt16()
|
||||||
|
|
||||||
if chunks["fmt"]["length"] > 0x10 and metadata["format"] != 0x0165 and metadata["format"] != 0x0166:
|
if chunks["fmt"]["length"] > 0x10 and metadata["format"] != 0x0165 and metadata["format"] != 0x0166:
|
||||||
metadata["extraSize"] = reader.ReadUInt16()
|
metadata["extraSize"] = reader.ReadUInt16()
|
||||||
|
|
||||||
@@ -78,7 +93,8 @@ def parse_wwise(reader):
|
|||||||
metadata["channelLayout"] = metadata["channelLayout"] >> 12
|
metadata["channelLayout"] = metadata["channelLayout"] >> 12
|
||||||
|
|
||||||
if metadata["format"] == 0x0166:
|
if metadata["format"] == 0x0166:
|
||||||
raise Exception("XMA2WAVEFORMATEX in fmt")
|
print(f"[WARNING] XMA2WAVEFORMATEX in fmt at {reader.GetName()}")
|
||||||
|
return metadata
|
||||||
|
|
||||||
# parse codec
|
# parse codec
|
||||||
codecs = {
|
codecs = {
|
||||||
@@ -101,16 +117,17 @@ def parse_wwise(reader):
|
|||||||
0x8311: "PTADPCM"
|
0x8311: "PTADPCM"
|
||||||
}
|
}
|
||||||
|
|
||||||
# genshin should be PTADPCM
|
# genshin should be *mostly* PTADPCM
|
||||||
# hsr and zzz should be VORBIS
|
# hsr and zzz should be VORBIS
|
||||||
|
|
||||||
if metadata["format"] not in codecs:
|
if metadata["format"] not in codecs:
|
||||||
raise Exception("unknown codec")
|
print(f'[WARNING] unknown codec {metadata["format"]} at {reader.GetName()}')
|
||||||
|
return metadata
|
||||||
|
|
||||||
codec = codecs[metadata["format"]]
|
codec = codecs[metadata["format"]]
|
||||||
|
|
||||||
if codec not in ["PTADPCM", "VORBIS"]: # Platinum "PtADPCM" custom ADPCM for Wwise
|
if codec not in ["PTADPCM", "VORBIS"]: # Platinum "PtADPCM" custom ADPCM for Wwise
|
||||||
print(f"unhandled codec -> {codec}")
|
print(f"[WARNING] unhandled codec {codec}, need to implement this later")
|
||||||
|
|
||||||
metadata["codec"] = codec
|
metadata["codec"] = codec
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user