Skip to content

✨ Implement VAB formats and command-line utilities #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 42 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
9afca66
:sparkles: Implement reading of VAG header and body
pleonex Jan 22, 2025
365497f
:bug: Fix issues reading VH
pleonex Jan 23, 2025
5525dcc
:umbrella: Implement snapshot testing for VH format
pleonex Jan 23, 2025
8586d2d
:bug: Fix reading VH with empty entries
pleonex Jan 23, 2025
c9bd0fa
:bug: Fix VH VAG indexes and sizes
pleonex Jan 26, 2025
90ec627
:shirt: Improve implementation of VH reader
pleonex Jan 26, 2025
62e84f5
:book: Document VH models and code improvements
pleonex Jan 26, 2025
5bb7073
:umbrella: Improve test via glob patterns
pleonex Jan 26, 2025
3483011
:sparkles: Implement VH binary writing
pleonex Jan 26, 2025
ed7f40a
:bug: Fix generating identical VH files when program empty
pleonex Jan 27, 2025
b08ce7b
:sparkles: Implement IBinary verifier comparer
pleonex Feb 1, 2025
2a61c06
:bug: Implement VB test and fix issue
pleonex Feb 1, 2025
71a168b
:sparkles: Implement VAB reading
pleonex Feb 2, 2025
a8c5382
:sparkles: Implement writing of VB and VAB
pleonex Feb 2, 2025
746ffee
:bug: Support empty programs in VH
pleonex Feb 2, 2025
90449ab
:bug: Remove extension from VAB nodes
pleonex Feb 4, 2025
db84a7b
:sparkles: Implement export VAB command
pleonex Feb 4, 2025
efc594a
:sparkles: VAB export with file names and length
pleonex Feb 4, 2025
9eb403e
:sparkles: Exported VAB audios with CRC32 in name
pleonex Feb 4, 2025
87e371a
:shirt: Export audio names into separate YAML file
pleonex Feb 10, 2025
09f52a6
:sparkles: VAB export implement reading names from file
pleonex Feb 12, 2025
0a4d9cf
:sparkles: Implement import VAB command
pleonex Feb 12, 2025
ea23a52
:shirt: Implement error handling in Hinox VAB util
pleonex Feb 13, 2025
1b28bfc
:shirt: Implement VAB body safeguards with tests
pleonex Feb 14, 2025
837c2f5
:sparkles: Skip VAG header when writing VAB body
pleonex Feb 14, 2025
f20f4af
:shirt: [VAB] Rename names/info argument to files and MaxLength field
pleonex Feb 14, 2025
267b0d8
:sparkles: [VAB] Improve VAG detection algo
pleonex Feb 14, 2025
faede01
:sparkles: Implement logging in utils app
pleonex Feb 16, 2025
f02c004
:shirt: [VAB] Add option for VAG detection
pleonex Feb 16, 2025
9f46734
:sparkles: [VAB] Add warning on total size
pleonex Apr 6, 2025
1690f09
:sparkles: [VAB] Implement test command for validation
pleonex Apr 13, 2025
7612209
[VAG] :bug: Support empty tones between valid ones
pleonex Apr 13, 2025
4290cd6
[VAB] :sparkles: Implement pattern file for ImHex
pleonex Apr 13, 2025
67412ce
:bug: [VAB] Export tone index and generate empty between tone entries
pleonex Apr 13, 2025
f098993
:sparkles: [VAB] Improve VAB ImHex definition
pleonex Apr 13, 2025
c9ae98a
:bug: [VAB] Fix identical generate when empty tones in between
pleonex Apr 14, 2025
06adf99
[VAB] :sparkles: Support non-complaint VH formats
pleonex Apr 15, 2025
4fd36cf
[VAB] :sparkles: Support non-complaint and improve logs in CLI
pleonex Apr 15, 2025
c708c96
[VAB] :bug: Fail when passing unrecognized options
pleonex Apr 15, 2025
17e7de5
📚 Document structure and tool install
pleonex Apr 29, 2025
e76ecee
📚 Document VAB specification
pleonex May 1, 2025
0602dda
[VAB] 🐛 Fix potential issues with formats lower than 5
pleonex May 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
"rollForward": false
},
"dotnet-reportgenerator-globaltool": {
"version": "5.2.0",
"version": "5.4.5",
"commands": [
"reportgenerator"
],
"rollForward": false
},
"docfx": {
"version": "2.78.2",
"version": "2.78.3",
"commands": [
"docfx"
],
Expand Down
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ indent_style = space
indent_size = 2
max_line_length = 80

# Verify settings
[*.{received,verified}.{json,txt,xml}]
charset = "utf-8-bom"
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = false
tab_width = 8
trim_trailing_whitespace = false

# XML project files
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
indent_size = 2
Expand Down
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.verified.txt text eol=lf working-tree-encoding=UTF-8
*.verified.xml text eol=lf working-tree-encoding=UTF-8
*.verified.json text eol=lf working-tree-encoding=UTF-8
8 changes: 8 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Upload test failure logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: verify-test-results
path: |
**/*.received.*

- name: "Bundle"
if: ${{ matrix.is_main_build }}
run: dotnet run --project build/orchestrator -- --target=Bundle --dotnet-configuration=Release
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@ build/temp/
*.csproj.user
*.DotSettings.user
launchSettings.json

# Test resources
*.received/
*.received.*
resources/tests/
!**/Hinox.Tests/Resources/
5 changes: 5 additions & 0 deletions .vscode/ltex.dictionary.en-US.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
Hinox
SceneGate
uint
ushort
VAG
SPU
VB
32 changes: 23 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,35 @@
 
</p>

_Hinox_ is a library part of the [_SceneGate_](https://github.com/SceneGate)
framework that provides support for **PS1 (PSX) file formats.**
_Hinox_ is a set of libraries and utilities part of the
[_SceneGate_](https://github.com/SceneGate) framework that provides support for
**PS1 (PSX) file formats.**

## Supported formats

🚧 Project in an early development phase. No formats are supported yet.
- :speaker: **VAB** audio containers
- Versions 5, 6 and 7
- Header (VH): read and write
- Body (VB and VAB): read and write

## Usage
## Tool installation

The project provides the following .NET libraries (NuGet packages in nuget.org).
The libraries work on supported versions of .NET.
1. Install [.NET 8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
2. Install the latest version of the tool:
`dotnet tool install -g SceneGate.Hinox.Utils`
- You can update it with `dotnet tool update -g SceneGate.Hinox.Utils`
- To use preview versions, add the argument
`--prerelease --add-source https://pkgs.dev.azure.com/SceneGate/SceneGate/_packaging/SceneGate-Preview/nuget/v3/index.json`

## Library installation

The project provides the following .NET (C#) libraries. Only the latest LTS
version of .NET and higher are supported (no .NET Framework).

- [![SceneGate.Hinox](https://img.shields.io/nuget/v/SceneGate.Hinox?label=SceneGate.Hinox&logo=nuget)](https://www.nuget.org/packages/SceneGate.Hinox)
🚧 **not ready yet**
- `SceneGate.Hinox.Audio`: audio codecs.
- `SceneGate.Hinox.Audio`: audio formats.

Stable releases are published in nuget.org.

Preview releases can be found in this
[Azure DevOps package repository](https://dev.azure.com/SceneGate/SceneGate/_packaging?_a=feed&feed=SceneGate-Preview).
Expand Down Expand Up @@ -62,7 +76,7 @@ your solution file (.sln) with the following content:

## Documentation

Documentation is not yet available, but it will be published in the
Documentation is available in the
[project website](https://scenegate.github.io/Hinox).

Don't hesitate to ask questions in the
Expand Down
3 changes: 0 additions & 3 deletions docs/articles/dev/features/audio.md

This file was deleted.

3 changes: 3 additions & 0 deletions docs/articles/dev/features/vab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# VAB audio converters

TODO
16 changes: 5 additions & 11 deletions docs/articles/dev/toc.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
- name: ✨ Getting started
- name: Introduction
href: ../../index.md
- name: 🚧 Getting started guide
href: tutorial.md

- name: ♻️ Converters
- name: 🚧 Audio
href: features/audio.md
- name: 🚧 VAB audio
href: features/vab.md

# - name: 📃 API docs
# - name: Namespaces
# href: ../../api/toc.yml
- name: 📃 API docs
- name: Namespaces
href: ../../api/toc.yml
3 changes: 0 additions & 3 deletions docs/articles/dev/tutorial.md

This file was deleted.

177 changes: 175 additions & 2 deletions docs/articles/specs/audio/vab.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,176 @@
# VAB: Very Audio Binary
# VAB specification

TODO
_VAB_ (_very audio binary_?) is an audio format. It defines audio _tones_
grouped in _programs_. It also acts as a container of VAG audio files. Tones are
linked to a specific VAG audio. Multiple tones with different parameters may
point to the same audio.

Usually it has the extension `.VAB`. But it may also appear as two separated
files: the header with `.VH` extension and its body (VAG files) with `.VB`
extension.

## Limitations

The format have the following limitations:

- A maximum of 254 waveform files (VAG).
- Up to 128 audio programs with a maximum of 16 tones.
- The body (VB) or total size of waveform files (VAG) must be under 504 KB
(`0x7E000`).
- This is due to a limitation in the hardware of 512 KB in the SPU RAM.

## Format overview

The VAB format is divided in the following sections. The VH file will contain
everything except the last part of the body (VB file).

| Offset | Length | Description |
| ------ | -------- | ------------------------------ |
| 0x0000 | 0x20 | Header information |
| 0x0020 | 0x800 | Programs attributes |
| 0x0820 | variable | Tones attributes |
| ... | 0x200 | Waveforms length table |
| ... | variable | Body with waveforms data (VAG) |

Quick formulas for variable offsets and lengths:

- Tones attributes length: `header.programs * 0x200`
- Offset to waveform length table: `0x820` + tones attributes length
- Header size: waveform length table offset + `0x200`
- Offset to body: header size

## Header (VH)

### Information

| Offset | Format | Description |
| ------ | ------- | --------------------------------------------------------- |
| 0x00 | char[4] | Format ID: `pBAV` (`VABp` in little-endian uint) |
| 0x04 | uint | Format version |
| 0x08 | uint | File ID |
| 0x0C | uint | Total size of header and body (even in header only files) |
| 0x10 | ushort | Reserved |
| 0x12 | ushort | Number of program attributes |
| 0x14 | ushort | Total number of tone attributes |
| 0x16 | ushort | Number of waveforms in body (VAG) |
| 0x18 | byte | Master volume |
| 0x19 | byte | Master pan |
| 0x1A | byte | User-defined bank attribute 1 |
| 0x1B | byte | User-defined bank attribute 2 |
| 0x1C | uint | Reserved |

### Program attributes

After the header information follows a list of program attribute definitions.
There are always 128 program entries in the format, although only a few of them
will be filled. There are always 16 bytes per entry.

| Offset | Format | Description |
| ------ | ------ | ------------------------------------ |
| 0x00 | byte | Number of valid tones in the program |
| 0x01 | byte | Master volume for tones |
| 0x02 | byte | Priority of tones |
| 0x03 | byte | Mode, default: `0xE0` |
| 0x04 | byte | Master panning |
| 0x05 | byte | Reserved |
| 0x06 | ushort | Additional attributes |
| 0x08 | uint | Reserved, default: `-1` |
| 0x0C | uint | Reserved, default: `-1` |

#### Empty programs

_Empty_ programs do not count towards the count in the header and will have a
tone count of `0`. They may appear in any position of the program list, not
necessarily always at the end (e.g., between valid programs).

Usually an _empty_ program repeats the same values of the last valid one
(reference program), except for the following fields:

- Tone count: always 0.
- Master volume: reference program value or 0 for format version 6 and higher.
- Master panning: reference program value or 0 for format version 6 and higher.

Note that some programs that do not appear at the end, may have unpredictable
values. Most likely they were filled at some point of the development process,
but they end up with no tones.

### Tone attributes

After the list of program attributes, there is a list of tones attributes in
order of programs. There are always 16 tones for each program, although as
happen for programs only a few will be not empty. A tone attribute entry has
always 32 bytes.

| Offset | Format | Description |
| ------ | --------- | -------------------------------------------- |
| 0x00 | byte | Priority |
| 0x01 | byte | Mode, 0: normal, 4: reverberation |
| 0x02 | byte | Tone volume |
| 0x03 | byte | Tone panning |
| 0x04 | byte | Centre tone in semitone units |
| 0x05 | byte | Centre note fine-tuning for pitch correction |
| 0x06 | byte | Note minimum value |
| 0x07 | byte | Note maximum value |
| 0x08 | byte | Vibration width |
| 0x09 | byte | Vibration duration |
| 0x0A | byte | Portamento width |
| 0x0B | byte | Portamento duration |
| 0x0C | byte | Minimum pitch bend |
| 0x0D | byte | Maximum pitch bend |
| 0x0E | byte | Reserved |
| 0x0F | byte | Reserved |
| 0x10 | ushort | Envelope settings for attack and decay |
| 0x12 | ushort | Envelope settings for release and sustain |
| 0x14 | ushort | Program index (0-based) |
| 0x16 | ushort | Waveform index (1-based), 0 for empty tone |
| 0x18 | ushort[4] | Reserved |

#### Empty tones

Similar to the empty programs, tones may be empty and be just a placeholder so
it's easier to calculate offsets. Note that an _empty program_ do not have any
tone definitions, as long as a program defines one tone, there will be 16 in the
format.

_Empty_ tones do not count towards the count in program attributes and will have
a waveform index equal to `0`, except for VAB format 5. In that case process the
tones in order with the count of program attributes, the rest would be empty.
Empty tones may appear in any position of the list, not necessarily always at
the end (e.g., between valid tones, good luck detecting for format 5).

The content of an empty tone changes depending on the format version:

- Fields `0x00` to `0x0E`:
- Version 5 (and lower?): reference tone values
- Version 6 and higher: `0x00` byte filled
- Except for note minimum and maximum values that are always `0x00`.
- Reserved fields: reference tone values
- Envelope settings:
- Version 5 (and lower?): reference tone
- Version 6: `0x00` byte filled
- Version 7 and higher: first: `0x80FF`, second: `0x5FC0`.
- Waveform index:
- Version 5 (and lower?): reference tone value
- Version 6 and higher: `0x00`.

Note that some tones that do not appear at the end, may have unpredictable
values. Most likely they were filled at some point of the development process,
but the linked waveform file was removed.

### Waveform length table

The last part of the header is a table with the waveform (VAG) data lengths.
Each length value is a 16-bits unsigned integer 3-bits right-shifted (multiply
by 8 the format value).

The first value should be ignored, and it is always `0x00`. Probably due to
waveform index being 1-based in the tone attributes.

The table is always `0x200` bytes long. The remaining bytes are `0x00` filled.

To calculate a waveform offset, sum the lengths of the previous files.

## Body (VB)

The body contains a set of waveform audio files. The format is `VAG` **without
header**. They usually start with 16-bytes `0x00`.
2 changes: 1 addition & 1 deletion docs/articles/specs/toc.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
- name: 🔉 audio
- name: 🚧 VAB
- name: VAB
href: audio/vab.md
42 changes: 42 additions & 0 deletions docs/articles/tool/install.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# hinox-utils: Installation

**hinox-utils** is a console application delivered as a _dotnet-tool_.

## Prerequisites

The utility requires the
[.NET 8.0 runtime](https://dotnet.microsoft.com/en-us/download/dotnet/8.0). You
can verify the installation by running `dotnet --list-runtimes` from a terminal.
If it says `Microsoft.NETCore.App` 8.0 or higher is installed, it should be
fine.

## Installation

There are two official ways to get the tool. Both methods download the same
binary.

### GitHub release page

Download the latest stable version from the
[GitHub release page](https://github.com/SceneGate/Hinox/releases) of the Hinox
project.

Preview versions can be downloaded for logged GitHub users from the project
_Action_ pipeline artifacts. But they expire after a few days. Using the _.NET
tool_ method may be easier for preview builds.

### .NET tool

If you prefer to use _dotnet tool_, install the program globally for the current
user by running the following command from a terminal:
`dotnet tool install -g SceneGate.Hinox.Utils`

The application will be available to run via `dotnet hinox-utils`.

To try a preview version, add the following argument to any of the above
commands:
`--prerelease --add-source https://pkgs.dev.azure.com/SceneGate/SceneGate/_packaging/SceneGate-Preview/nuget/v3/index.json`

To update the application to the latest version run:
`dotnet tool update -g SceneGate.Hinox.Utils`. Add the above argument to update
to the latest preview.
9 changes: 9 additions & 0 deletions docs/articles/tool/toc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
- name: ✨ Getting started
- name: Introduction
href: ../../index.md

- name: 🛠️ hinox-utils
- name: Installation
href: install.md
- name: 🚧 VAB
href: vab.md
Loading