Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
# vaudio_lyra
# lyra as a DLL

Speech codec plugin for voice that uses [Lyra](https://github.com/google/lyra), the new voice codec that achieves the best quality-to-bitrate ratio.

This was written for usage with TFORevive, and so may need adjustments for use with other Source Engine games (missing `bool bFinal` param).
This is originally forked from [Lyra](https://github.com/google/lyra), then after some small changes from the TOFRevive team, I tweaked it to be a simple DLL.
Lyra has amazing quality-to-bitrate ratio and has some features that I don't expose (at present) such as automatically generating pleasant noise when packets are late.

## Compile (on Windows)

You have to have [Bazelisk installed](https://bazel.build/install/bazelisk), and also MSVC and Python (that has `numpy` and `six` installed with pip). Replace `C:\\Python311\\python.exe` below with your Python installation.

First run the following to convert model files into a header file that will be bundled into the DLL:
```
C:\\Python311\\python.exe .\models_to_header.py
```
I find that Python and Bazel are not to my liking, so I built everything in a Windows VM using VirtualBox. The steps are relatively straightforward and reproducible.

Then to compile:
Download and install: https://aka.ms/vs/17/release/vs_BuildTools.exe and select Desktop Development with C++
Download and install: https://github.com/git-for-windows/git/releases/download/v2.46.0.windows.1/Git-2.46.0-64-bit.exe just take all defaults.
Download and the Windows exe and rename it to bazel.exe https://github.com/bazelbuild/bazel/releases/tag/5.3.2
Download and install: https://www.python.org/ftp/python/3.12.6/python-3.12.6-amd64.exe

```
bazel build -c opt --action_env PYTHON_BIN_PATH="C:\\Python311\\python.exe" vaudio_lyra:vaudio_lyra
```
Open a GIT BASH command window:
git clone https://github.com/google/lyra.git
cd lyra
export PATH=$PATH:/c/Users/User/AppData/Local/Programs/Python/Python312
python -m pip install setuptools numpy six
python ./models_to_header.py
bazel.exe build -c opt --config=windows --action_env=PYTHON_BIN_PATH="/c/Users/User/AppData/Local/Programs/Python/Python312/python.exe" dll:dll

You can replace `-c opt` with `-c dbg` to build in debug mode (with asserts enabled).

Final file is at `./bazel-bin/vaudio_lyra/vaudio_lyra.dll`
Final file is at `./bazel-bin/dll/lyra_dll.dll`

## Compiling CLI examples

Expand All @@ -40,4 +41,3 @@ Running the built-in unit tests of Lyra might be useful, as we did some changes
bazel test --action_env PYTHON_BIN_PATH="C:\\Python311\\python.exe" //lyra:all
```

We don't currently have any vaudio_lyra-specific unit tests.
10 changes: 10 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,16 @@ maven_install(
)


load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
name = "gflags",
urls = ["https://github.com/gflags/gflags/archive/refs/tags/v2.2.2.tar.gz"],
strip_prefix = "gflags-2.2.2",
sha256 = "34af2f15cf7367513b352bdcd2493ab14ce43692d2dcd9dfc499492966c64dcf",
)


# Begin Tensorflow WORKSPACE subset required for TFLite

git_repository(
Expand Down
6 changes: 1 addition & 5 deletions vaudio_lyra/BUILD → dll/BUILD
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
cc_binary(
name = "vaudio_lyra",
name = "lyra_dll",
srcs = [
"lyravoicecodec.cc",
"dllmain.cc",
"frameencoder.cc",
"ivoicecodec.h",
"iframeencoder.h",
],
#data = [":tflite_testdata"],
linkopts = select({
Expand Down
96 changes: 96 additions & 0 deletions dll/dllmain.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include "Windows.h"

#include "lyra/lyra_config.h"
#include "lyra/lyra_encoder.h"
#include "lyra/lyra_decoder.h"
#include "lyra/model_coeffs/_models.h"

#define BYTES_PER_SAMPLE 2

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

std::unique_ptr<chromemedia::codec::LyraEncoder> m_Encoder = nullptr;
std::unique_ptr<chromemedia::codec::LyraDecoder> m_Decoder = nullptr;

extern "C" __declspec(dllexport) bool Initialize()
{
const int samplerate = 16000;
const int bitrate = 3200;

const chromemedia::codec::LyraModels models = GetEmbeddedLyraModels();

if (!m_Encoder)
{
m_Encoder = chromemedia::codec::LyraEncoder::Create(samplerate, 1, bitrate, false, models);
}
if (!m_Decoder)
{
m_Decoder = chromemedia::codec::LyraDecoder::Create(samplerate, 1, models);
}
return m_Encoder != nullptr && m_Decoder != nullptr;
}

extern "C" __declspec(dllexport) void Shutdown()
{
m_Encoder.reset();
m_Decoder.reset();
}

extern "C" __declspec(dllexport) void Encode(const int16_t* uncompressed, size_t uncompressed_size, uint8_t* compressed, size_t compressed_size)
{
const int num_samples_per_packet = m_Encoder->sample_rate_hz() / m_Encoder->frame_rate();
const int raw_frame_size = num_samples_per_packet * BYTES_PER_SAMPLE;

assert(uncompressed_size >= num_samples_per_packet);

std::vector<int16_t> uncompressed_vector(uncompressed, uncompressed + num_samples_per_packet);
std::optional<std::vector<uint8_t>> encoded = m_Encoder->Encode(uncompressed_vector);

if (!encoded.has_value())
{
return;
}

assert(encoded->size() == chromemedia::codec::BitrateToPacketSize(m_Encoder->bitrate()));
assert(compressed_size >= encoded->size());

memcpy_s(compressed, compressed_size, encoded->data(), encoded->size());
}

extern "C" __declspec(dllexport) void Decode(const int8_t* compressed, size_t compressed_size, uint16_t* uncompressed, size_t uncompressed_size)
{
const int num_samples_per_packet = m_Encoder->sample_rate_hz() / m_Encoder->frame_rate();
const int packet_size = chromemedia::codec::BitrateToPacketSize(m_Encoder->bitrate());

assert(compressed_size == packet_size);

bool valid = m_Decoder->SetEncodedPacket(absl::MakeSpan(reinterpret_cast<const uint8_t*>(compressed), compressed_size));
assert(valid == true);
if (!valid) return;

std::optional<std::vector<int16_t>> decoded = m_Decoder->DecodeSamples(num_samples_per_packet);
if (!decoded.has_value())
{
assert(decoded.has_value());
return;
}

assert(decoded->size() == num_samples_per_packet);
assert(uncompressed_size >= decoded->size());

memcpy_s(uncompressed, uncompressed_size * sizeof(uint16_t), decoded->data(), decoded->size() * sizeof(uint16_t));
}
21 changes: 0 additions & 21 deletions vaudio_lyra/dllmain.cc

This file was deleted.

175 changes: 0 additions & 175 deletions vaudio_lyra/frameencoder.cc

This file was deleted.

Loading