Skip to content

Commit dfb178f

Browse files
authored
New project file system (#3)
* solve resolution * new audio file system * cleanup tests * tests and bug fix * more examples * annotations for commands * bump lang * pipelines * update package lock * version * 10.0.x * update comment
1 parent 60ef42e commit dfb178f

47 files changed

Lines changed: 2732 additions & 899 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
build-and-test:
11+
runs-on: windows-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Setup .NET
17+
uses: actions/setup-dotnet@v4
18+
with:
19+
dotnet-version: "10.0.x"
20+
cache: true
21+
cache-dependency-path: "**/packages.lock.json"
22+
23+
- name: Restore dependencies
24+
run: dotnet restore
25+
26+
- name: Build
27+
run: dotnet build --no-restore -c Release
28+
29+
- name: Test
30+
run: dotnet test --no-build -c Release --verbosity normal
31+
32+
- name: Publish (win-x64)
33+
run: dotnet publish PckTool -c Release -r win-x64 -o publish-win-x64
34+
35+
- name: Publish (win-arm64)
36+
run: dotnet publish PckTool -c Release -r win-arm64 -o publish-win-arm64
37+
38+
- name: Upload artifact (win-x64)
39+
uses: actions/upload-artifact@v4
40+
with:
41+
name: PckTool-win-x64
42+
path: publish-win-x64/
43+
44+
- name: Upload artifact (win-arm64)
45+
uses: actions/upload-artifact@v4
46+
with:
47+
name: PckTool-win-arm64
48+
path: publish-win-arm64/
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Create Release
2+
3+
on:
4+
workflow_dispatch:
5+
6+
permissions:
7+
contents: write
8+
9+
jobs:
10+
create-tag:
11+
runs-on: windows-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
with:
16+
fetch-depth: 0
17+
18+
- name: Generate tag
19+
id: tag
20+
run: |
21+
$date = Get-Date -Format "yyyy.MM.dd"
22+
$baseTag = "v$date"
23+
$counter = 0
24+
$tag = $baseTag
25+
26+
while (git tag -l $tag) {
27+
$counter++
28+
$tag = "$baseTag.$counter"
29+
}
30+
31+
echo "tag=$tag" >> $env:GITHUB_OUTPUT
32+
echo "Generated tag: $tag"
33+
34+
- name: Create and push tag
35+
run: |
36+
git config user.name "github-actions[bot]"
37+
git config user.email "github-actions[bot]@users.noreply.github.com"
38+
git tag ${{ steps.tag.outputs.tag }}
39+
git push origin ${{ steps.tag.outputs.tag }}

.github/workflows/release.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v[0-9]+.[0-9]+.[0-9]+*"
7+
workflow_dispatch:
8+
inputs:
9+
tag:
10+
description: "Tag to release (e.g. v2026.01.31 or v2026.01.31.1)"
11+
required: true
12+
type: string
13+
14+
permissions:
15+
contents: write
16+
17+
jobs:
18+
build:
19+
runs-on: windows-latest
20+
21+
steps:
22+
- uses: actions/checkout@v4
23+
with:
24+
ref: ${{ inputs.tag || github.ref }}
25+
26+
- name: Setup .NET
27+
uses: actions/setup-dotnet@v4
28+
with:
29+
dotnet-version: "10.0.x"
30+
cache: true
31+
cache-dependency-path: "**/packages.lock.json"
32+
33+
- name: Publish (win-x64)
34+
run: dotnet publish PckTool -c Release -r win-x64 -o publish-win-x64
35+
36+
- name: Publish (win-arm64)
37+
run: dotnet publish PckTool -c Release -r win-arm64 -o publish-win-arm64
38+
39+
- name: Zip artifacts
40+
run: |
41+
Compress-Archive -Path publish-win-x64/* -DestinationPath PckTool-win-x64.zip
42+
Compress-Archive -Path publish-win-arm64/* -DestinationPath PckTool-win-arm64.zip
43+
44+
- name: Create Release
45+
uses: softprops/action-gh-release@v2
46+
with:
47+
files: |
48+
PckTool-win-x64.zip
49+
PckTool-win-arm64.zip
50+
generate_release_notes: true

Directory.Build.props

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<Project>
2+
<PropertyGroup>
3+
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
4+
</PropertyGroup>
5+
</Project>

PckTool.Abstractions/IAudioFile.cs

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
namespace PckTool.Abstractions;
2+
3+
/// <summary>
4+
/// Represents a unified audio file that can be either a PCK package or a standalone BNK soundbank.
5+
/// </summary>
6+
/// <remarks>
7+
/// This interface provides a common abstraction for working with both:
8+
/// <list type="bullet">
9+
/// <item>
10+
/// <description>PCK files - containers with multiple soundbanks and streaming files</description>
11+
/// </item>
12+
/// <item>
13+
/// <description>BNK files - standalone soundbanks with embedded media</description>
14+
/// </item>
15+
/// </list>
16+
/// </remarks>
17+
public interface IAudioFile : IDisposable
18+
{
19+
/// <summary>
20+
/// Gets the source file path this audio file was loaded from, if applicable.
21+
/// </summary>
22+
string? SourcePath { get; }
23+
24+
/// <summary>
25+
/// Gets whether any entries have been modified since loading.
26+
/// </summary>
27+
bool HasModifications { get; }
28+
29+
/// <summary>
30+
/// Gets the type of audio file (PCK or BNK).
31+
/// </summary>
32+
AudioFileType FileType { get; }
33+
34+
/// <summary>
35+
/// Gets the soundbank entries in this audio file.
36+
/// For BNK files, this returns a single-entry collection.
37+
/// </summary>
38+
ISoundBankCollection SoundBanks { get; }
39+
40+
/// <summary>
41+
/// Gets the streaming file entries in this audio file.
42+
/// For BNK files, this returns an empty collection.
43+
/// </summary>
44+
IStreamingFileCollection StreamingFiles { get; }
45+
46+
/// <summary>
47+
/// Gets the external file entries in this audio file.
48+
/// For BNK files, this returns an empty collection.
49+
/// </summary>
50+
IExternalFileCollection ExternalFiles { get; }
51+
52+
/// <summary>
53+
/// Gets the language ID to name mapping.
54+
/// For BNK files, this returns a single-entry mapping.
55+
/// </summary>
56+
IReadOnlyDictionary<uint, string> Languages { get; }
57+
58+
/// <summary>
59+
/// Gets the number of soundbanks contained in this audio file.
60+
/// </summary>
61+
int SoundBankCount { get; }
62+
63+
/// <summary>
64+
/// Gets the number of streaming WEM files in this audio file.
65+
/// </summary>
66+
int StreamingFileCount { get; }
67+
68+
/// <summary>
69+
/// Gets the number of external WEM files in this audio file.
70+
/// </summary>
71+
int ExternalFileCount { get; }
72+
73+
/// <summary>
74+
/// Finds a WEM file by its source ID across all storage locations.
75+
/// </summary>
76+
/// <param name="sourceId">The Wwise source ID of the WEM file.</param>
77+
/// <returns>The WEM data if found; otherwise, null.</returns>
78+
byte[]? FindWem(uint sourceId);
79+
80+
/// <summary>
81+
/// Determines whether a WEM with the specified source ID exists.
82+
/// </summary>
83+
/// <param name="sourceId">The Wwise source ID to search for.</param>
84+
/// <returns>true if the WEM exists; otherwise, false.</returns>
85+
bool ContainsWem(uint sourceId);
86+
87+
/// <summary>
88+
/// Replaces a WEM file's data across all locations where it exists.
89+
/// </summary>
90+
/// <param name="sourceId">The source ID of the WEM to replace.</param>
91+
/// <param name="data">The new WEM data.</param>
92+
/// <param name="updateHircSizes">Whether to update HIRC size references.</param>
93+
/// <returns>A result describing what was replaced.</returns>
94+
WemReplacementResult ReplaceWem(uint sourceId, byte[] data, bool updateHircSizes = true);
95+
96+
/// <summary>
97+
/// Saves the audio file to the specified path.
98+
/// </summary>
99+
/// <param name="path">The file path to save to.</param>
100+
void Save(string path);
101+
102+
/// <summary>
103+
/// Saves the audio file to a stream.
104+
/// </summary>
105+
/// <param name="stream">The stream to write to.</param>
106+
void Save(Stream stream);
107+
}
108+
109+
/// <summary>
110+
/// Specifies the type of audio file.
111+
/// </summary>
112+
public enum AudioFileType
113+
{
114+
/// <summary>
115+
/// A PCK package file containing multiple soundbanks and streaming files.
116+
/// </summary>
117+
Pck,
118+
119+
/// <summary>
120+
/// A standalone BNK soundbank file.
121+
/// </summary>
122+
Bnk
123+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
namespace PckTool.Abstractions;
2+
3+
/// <summary>
4+
/// Factory for creating audio file instances from various sources.
5+
/// </summary>
6+
/// <remarks>
7+
/// This factory automatically detects the file type (PCK or BNK) and returns
8+
/// the appropriate implementation of <see cref="IAudioFile" />.
9+
/// </remarks>
10+
public interface IAudioFileFactory
11+
{
12+
/// <summary>
13+
/// Loads an audio file from the specified path.
14+
/// Automatically detects whether the file is a PCK or BNK based on extension and content.
15+
/// </summary>
16+
/// <param name="path">The path to the audio file.</param>
17+
/// <returns>An audio file instance.</returns>
18+
/// <exception cref="FileNotFoundException">The file does not exist.</exception>
19+
/// <exception cref="InvalidDataException">The file format is not recognized.</exception>
20+
IAudioFile Load(string path);
21+
22+
/// <summary>
23+
/// Loads an audio file from a stream with the specified file type.
24+
/// </summary>
25+
/// <param name="stream">The stream containing the audio file data.</param>
26+
/// <param name="fileType">The type of audio file.</param>
27+
/// <param name="sourcePath">Optional source path for reference.</param>
28+
/// <returns>An audio file instance.</returns>
29+
IAudioFile Load(Stream stream, AudioFileType fileType, string? sourcePath = null);
30+
31+
/// <summary>
32+
/// Determines the audio file type from a file path based on extension.
33+
/// </summary>
34+
/// <param name="path">The file path to check.</param>
35+
/// <returns>The detected audio file type.</returns>
36+
AudioFileType DetectFileType(string path);
37+
38+
/// <summary>
39+
/// Checks if the specified file extension is supported.
40+
/// </summary>
41+
/// <param name="extension">The file extension (with or without leading dot).</param>
42+
/// <returns>true if the extension is supported; otherwise, false.</returns>
43+
bool IsSupportedExtension(string extension);
44+
}

PckTool.Abstractions/PckTool.Abstractions.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<Description>Abstractions and interfaces for PckTool - a Wwise PCK file manipulation library</Description>
1010
<Authors>coconutbird</Authors>
1111
<PackageTags>wwise;pck;audio;bnk;soundbank</PackageTags>
12+
<LangVersion>default</LangVersion>
1213
</PropertyGroup>
1314

1415
</Project>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"version": 1,
3+
"dependencies": {
4+
"net10.0": {}
5+
}
6+
}

PckTool.Core/PckTool.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<Description>Wwise PCK file manipulation library for Halo Wars DE</Description>
1010
<Authors>coconutbird</Authors>
1111
<PackageTags>wwise;pck;audio;bnk;soundbank;halo-wars</PackageTags>
12+
<LangVersion>default</LangVersion>
1213
</PropertyGroup>
1314

1415
<ItemGroup>

0 commit comments

Comments
 (0)