Skip to content
This repository was archived by the owner on Feb 6, 2026. It is now read-only.

Commit dcdd6d4

Browse files
committed
hca: Improve WAV compatibility
1 parent 902bac2 commit dcdd6d4

File tree

6 files changed

+123
-83
lines changed

6 files changed

+123
-83
lines changed

PyCriCodecsEx/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.0.2"
1+
__version__ = "0.0.3"

PyCriCodecsEx/hca.py

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -209,32 +209,28 @@ def _Pyparse_header(self) -> None:
209209
raise ValueError(f"WAV bitdepth of {self.fmtBitCount} is not supported, only 16 bit WAV files are supported.")
210210
elif self.fmtSize != 16:
211211
raise ValueError(f"WAV file has an FMT chunk of an unsupported size: {self.fmtSize}, the only supported size is 16.")
212-
if self.stream.read(4) == b"smpl":
213-
self.stream.seek(-4, 1)
214-
self.looping = True
215-
# Will just be naming the important things here.
216-
smplsig, smplesize, _, _, _, _, _, _, _, self.LoopCount, _, _, _, self.LoopStartSample, self.LoopEndSample, _, _ = WavSmplHeaderStruct.unpack(
217-
self.stream.read(WavSmplHeaderStruct.size)
218-
)
219-
if self.LoopCount != 1:
220-
self.looping = False # Unsupported multiple looping points, so backtracks, and ignores looping data.
221-
self.stream.seek(-WavSmplHeaderStruct.size, 1)
222-
self.stream.seek(8 + smplesize, 1)
223-
else:
224-
self.stream.seek(-4, 1)
225-
self.looping = False
226-
if self.stream.read(4) == b"note": # There's no use for this on ADX.
227-
len = self.stream.read(4)
228-
self.stream.seek(len+4) # + 1? + padding maybe?
229-
else:
230-
self.stream.seek(-4, 1)
231-
if self.stream.read(4) == b"data":
232-
self.stream.seek(-4, 1)
233-
self.dataSig, self.dataSize = WavDataHeaderStruct.unpack(
234-
self.stream.read(WavDataHeaderStruct.size)
235-
)
236-
else:
237-
raise ValueError("Invalid or an unsupported wav file.")
212+
while (hdr := self.stream.read(4)):
213+
size = int.from_bytes(self.stream.read(4), 'little')
214+
size += (size & 1) # padding
215+
offset = self.stream.tell()
216+
match hdr:
217+
case b"smpl":
218+
self.stream.seek(-4, 1)
219+
self.looping = True
220+
# Will just be naming the important things here.
221+
smplsig, smplesize, _, _, _, _, _, _, _, self.LoopCount, _, _, _, self.LoopStartSample, self.LoopEndSample, _, _ = WavSmplHeaderStruct.unpack(
222+
self.stream.read(WavSmplHeaderStruct.size)
223+
)
224+
if self.LoopCount != 1:
225+
self.looping = False # Unsupported multiple looping points, so backtracks, and ignores looping data.
226+
self.stream.seek(-WavSmplHeaderStruct.size, 1)
227+
self.stream.seek(8 + smplesize, 1)
228+
case b"data":
229+
self.stream.seek(-4, 1)
230+
self.dataSig, self.dataSize = WavDataHeaderStruct.unpack(
231+
self.stream.read(WavDataHeaderStruct.size)
232+
)
233+
self.stream.seek(offset + size, 0)
238234
else:
239235
raise ValueError("Invalid HCA or WAV file.")
240236
self.stream.seek(0)

README.md

Lines changed: 3 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,9 @@
1-
# PyCriCodecsEx
1+
PyCriCodecsEx
2+
---
23
A continuation of @Youjose's work on Criware formats. Feautres are still in flux and subject to change. When in doubt, Refer to the [original repo](https://github.com/Youjose/PyCriCodecs) for more information.
34

4-
# Installation
5-
```bash
6-
pip install PyCriCodecsEx
7-
```
5+
Detailed documentation, installation instructions are available at https://mos9527.com/PyCriCodecsEx
86

9-
For USM features, you need `ffmpeg` installed and available in your PATH. See also https://github.com/kkroening/ffmpeg-python?tab=readme-ov-file#installing-ffmpeg
10-
11-
## Features
12-
If not otherwise mentioned, all features marked with [x] are considered working, and has been verified with official tools.
13-
14-
Examples are available in [Tests](https://github.com/mos9527/PyCriCodecsEx/tree/main/Tests)
15-
16-
### ACB Cue sheets (also AWB)
17-
- [x] Cue extraction support for most ACBs
18-
- [x] Cue waveform(s) encoding with ADX/HCA support
19-
- [x] Comprehensive Cue metadata editing support (via Python API)
20-
21-
### USM Sofdec2 (Encode & Decode)
22-
#### Audio Stream
23-
For audio to be muxed in, you need a PCM WAV sample with NO metadata, which can be produced with e.g.:
24-
```bash
25-
ffmpeg -i input.mp3 -vn -c:a pcm_s16le -map_metadata -1 output.wav
26-
```
27-
Decoding and Encoded format can be the following:
28-
- [x] HCA
29-
- [x] ADX
30-
#### Video Stream
31-
**NOTE**: You definitely want to tweak these encode settings a bit.
32-
- [x] Sofdec Prime (MPEG1, from `.m1v` container)
33-
- Prepare source file with: `ffmpeg -i <input_file> -c:v mpeg1video -an <output_file>.m1v`
34-
- [x] H264 (from `.h264` raw container)
35-
- Prepare source file with: `ffmpeg -i <input_file> -c:v libx264 -an <output_file>.h264`
36-
- [x] VP9 (from `.ivf` container)
37-
- Prepare source file with: `ffmpeg -i <input_file> -c:v libvpx -an <output_file>.ivf`
38-
### HCA Audio Codec
39-
- [x] Decoding (up to version 3.0)
40-
- [x] Encoding (up to version 3.0)
41-
### ADX Audio Codec
42-
- [x] Decoding
43-
- [x] Encoding
44-
### CPK
45-
- [x] Unpacking
46-
- [x] Packing
47-
48-
## Roadmap
49-
- [x] ACB Extraction (Massive TODO. see also https://github.com/mos9527/PyCriCodecsEx/blob/main/Research/ACBSchema.py)
50-
- [ ] Interface for encode tasks (CLI then maybe GUI?)
51-
- [ ] Documentation
52-
- [ ] C/C++ port + FFI
53-
## Currently Known Bugs
54-
- USM seeking does not work. Though most games don't use it anyways.
55-
- Not important, and might not fix: ADX encoding and decoding at higher bitdepths (11-15) adds popping noise.
56-
- Some CPK's that has the same filename for every file in the entry will overwrite each other.
57-
- Probably many more I am unaware of, report if you find any.
587

598
# Credits
609
- https://github.com/Youjose/PyCriCodecs

docs/source/index.rst

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.. include:: styles.rst
2+
13
PyCriCodecsEx documentation
24
===========================
35

@@ -6,9 +8,92 @@ This site contains automatically generated API documentation for every format `P
68
Most if not all features are verified to work with either commercial games, or official SDK tools. However issues are to be
79
expected - submit bug reports or feature requests on the `Issue Tracker <https://github.com/mos9527/PyCriCodecsEx/issues>`_.
810

9-
PyCriCodecsEx is a fork of `Youjose/PyCriCodecs <https://github.com/Youjose/PyCriCodecs>`_. You can refer to the original repository
11+
PyCriCodecsEx is a fork of `Youjose/PyCriCodecs <https://github.com/Youjose/PyCriCodecs>`_. Refer to the original repository
1012
and its `Wiki <https://github.com/Youjose/PyCriCodecs/wiki/Docs-and-Thoughts>`_ for more information.
1113

14+
The GitHub repository is available at `mos9527/PyCriCodecsEx <https://github.com/mos9527/PyCriCodecsEx>`_
15+
16+
Installation
17+
============
18+
PyCriCodecsEx is available on `PyPI <https://pypi.org/project/PyCriCodecsEx/>`_
19+
20+
.. code-block:: bash
21+
22+
pip install PyCriCodecsEx
23+
24+
For USM features, you need `ffmpeg` installed and available in your PATH, and install the `[usm]` extra - which installs `ffmpeg-python <https://github.com/kkroening/ffmpeg-python>`_.
25+
26+
To make sure `ffmpeg` is available, you can refer to `ffmpeg-python's instructions <https://github.com/kkroening/ffmpeg-python?tab=readme-ov-file#installing-ffmpeg>`_.
27+
28+
.. code-block:: bash
29+
30+
pip install PyCriCodecsEx[usm]
31+
32+
33+
Support Status
34+
========
35+
36+
37+
38+
USM Sofdec2 (Encode & Decode)
39+
-----------------------------
40+
41+
**Audio Stream**
42+
43+
Decoding and Encoded format can be the following:
44+
45+
* |check| HCA
46+
* |check| ADX
47+
48+
**Video Stream**
49+
50+
**NOTE**: You definitely want to tweak these encode settings a bit.
51+
52+
* |check| Sofdec Prime (MPEG1, from ``.m1v`` container)
53+
54+
* Prepare source file with: ``ffmpeg -i <input_file> -c:v mpeg1video -an <output_file>.m1v``
55+
56+
* |check| H264 (from ``.h264`` raw container)
57+
58+
* Prepare source file with: ``ffmpeg -i <input_file> -c:v libx264 -an <output_file>.h264``
59+
60+
* |check| VP9 (from ``.ivf`` container)
61+
62+
* Prepare source file with: ``ffmpeg -i <input_file> -c:v libvpx -an <output_file>.ivf``
63+
64+
CPK
65+
---
66+
* |check| Unpacking
67+
* |check| Packing
68+
69+
ACB Cue sheets (also AWB)
70+
-------------------------
71+
* |check| Cue extraction support for most ACBs
72+
* |check| Cue waveform(s) encoding with ADX/HCA support
73+
* |check| Comprehensive Cue metadata editing support (via Python API)
74+
75+
ADX Audio Codec
76+
---------------
77+
* |check| Decoding
78+
* |check| Encoding
79+
80+
HCA Audio Codec
81+
---------------
82+
* |check| Decoding (up to version 3.0)
83+
* |check| Encoding (up to version 3.0)
84+
85+
Roadmap
86+
=======
87+
* |uncheck| Interface for encode tasks (most probably done in a separate project)
88+
* |uncheck| C/C++ port + FFI
89+
90+
Currently Known Bugs
91+
====================
92+
* USM seeking does not work. Though most games don't use it anyways.
93+
* Not important, and might not fix: ADX encoding and decoding at higher bitdepths (11-15) adds popping noise.
94+
* Some CPK's that has the same filename for every file in the entry will overwrite each other.
95+
* Probably many more I am unaware of, report if you find any.
96+
1297
.. include:: USM.rst
1398

1499
.. include:: CPK.rst

docs/source/styles.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
..
2+
https://stackoverflow.com/questions/6904552/how-to-create-a-checklist-in-restructuredtext-rest
3+
4+
.. |check| raw:: html
5+
6+
<input checked="" disabled="" type="checkbox">
7+
8+
.. |uncheck| raw:: html
9+
10+
<input disabled="" type="checkbox">

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def build_extensions(self):
3939
description="Criware formats library for Python",
4040
long_description=open("README.md", "r", encoding="utf-8").read(),
4141
long_description_content_type="text/markdown",
42-
url='https://github.com/mos9527/PyCriCodecsEx',
42+
url='https://mos9527.github.io/PyCriCodecsEx/',
4343
packages=["PyCriCodecsEx"],
4444
ext_modules=[Extension(
4545
'CriCodecsEx',

0 commit comments

Comments
 (0)