Skip to content
Merged
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
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1697,6 +1697,15 @@ audiocpp_add_model(audiosr
engine::models::audiosr::make_audiosr_loader
)

audiocpp_add_model(builtin_audio_utils
SOURCES
src/models/builtin_audio_utils/session.cpp
INCLUDES
engine/models/builtin_audio_utils/session.h
LOADERS
engine::models::builtin_audio_utils::make_builtin_audio_utils_loader
)

audiocpp_add_model(controlfoley
SOURCES
src/models/controlfoley/assets.cpp
Expand Down
7 changes: 5 additions & 2 deletions app/server/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,14 @@ ServerConfig load_server_config(const std::filesystem::path & path) {
for (const auto & item : models->as_array()) {
ServerModelConfig model;
model.id = engine::io::json::require_string(item, "id");
model.path = resolve_path(base, engine::io::json::require_string(item, "path"));
model.family = engine::io::json::require_string(item, "family");
const auto raw_path = engine::io::json::require_string(item, "path");
model.path = model.family == "builtin_audio_utils"
? std::filesystem::path(raw_path)
: resolve_path(base, raw_path);
if (const auto * value = item.find("model_spec_override")) {
model.model_spec_override = resolve_path(base, value->as_string());
}
model.family = engine::io::json::require_string(item, "family");
model.task = engine::io::json::optional_string(item, "task", model.task);
model.mode = engine::io::json::optional_string(item, "mode", model.mode);
model.lazy = engine::io::json::optional_bool(item, "lazy", config.lazy_load);
Expand Down
53 changes: 52 additions & 1 deletion docs/audio_tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

| Model | Family | Task(s) | Quick Start |
|---|---|---|---|
| Built-in audio utilities | `builtin_audio_utils` | `s2s` denoise/enhance/super-resolution | [Built-in audio utilities](#built-in-audio-utilities) |
| AudioSR | `audiosr` | `s2s` audio super-resolution | [AudioSR](#audiosr) |
| ControlFoley | `controlfoley` | `gen` Foley/SFX generation | [ControlFoley](#controlfoley) |
| GTCRN | `gtcrn`, `gtcrn_dns3`, `gtcrn_vctk`, `gtcrn_streaming` | framework denoise utility | [GTCRN](#gtcrn) |
| GTCRN | `gtcrn`, `gtcrn_dns3`, `gtcrn_vctk`, `gtcrn_streaming` | framework denoise utility API | [GTCRN](#gtcrn) |
| MeanVC2 | `meanvc2` | `vc` | [MeanVC2](#meanvc2) |
| MioCodec | `miocodec` | `vc`, `s2s` | [MioCodec](#miocodec) |
| PersonaPlex | `personaplex` | `s2s` | [PersonaPlex](#personaplex) |
Expand All @@ -29,6 +30,56 @@ Common CLI shape:
audiocpp_cli --task <task> --family <family> --model <model-dir> --backend cuda ...
```

## Built-in Audio Utilities

The `builtin_audio_utils` family exposes the built-in framework audio utility
models through the normal CLI and server model-loading path. These utilities do
not use a GGUF or external model directory as `--model`; pass the utility id
directly.

| Utility id | Operation | Input rate | Output rate |
|---|---|---:|---:|
| `deepfilternet2` | Denoise/enhance | 48 kHz | 48 kHz |
| `rnnoise` | Denoise/enhance | 48 kHz | 48 kHz |
| `zipenhancer` | Denoise/enhance | 16 kHz | 16 kHz |
| `gtcrn` | Denoise/enhance, alias for `gtcrn_streaming` | 16 kHz | 16 kHz |
| `gtcrn_streaming` | Denoise/enhance | 16 kHz | 16 kHz |
| `gtcrn_dns3` | Denoise/enhance | 16 kHz | 16 kHz |
| `gtcrn_vctk` | Denoise/enhance | 16 kHz | 16 kHz |
| `flashsr` | Audio super-resolution | 16 kHz | 48 kHz |

CLI example:

```bash
audiocpp_cli --task s2s --family builtin_audio_utils \
--model rnnoise \
--backend cuda \
--audio input.wav \
--out enhanced.wav \
--log \
--log-file rnnoise.log
```

Server config example:

```json
{
"id": "builtin-rnnoise",
"family": "builtin_audio_utils",
"path": "rnnoise",
"task": "s2s",
"mode": "offline"
}
```

Server request example:

```bash
curl http://127.0.0.1:8080/v1/tasks/run \
-H 'Content-Type: application/json' \
-d '{"model":"builtin-rnnoise","request":{"audio":"input.wav"}}'
```

## AudioSR

AudioSR performs audio super-resolution from an input waveform. See
Expand Down
21 changes: 21 additions & 0 deletions include/engine/framework/audio/utility_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,25 @@
#include "engine/framework/core/backend.h"

#include <filesystem>
#include <optional>
#include <string_view>
#include <utility>
#include <vector>

namespace engine::audio {

enum class BuiltinAudioUtilityKind {
Denoise,
SuperResolve,
};

struct BuiltinAudioUtilityInfo {
std::string_view id;
BuiltinAudioUtilityKind kind = BuiltinAudioUtilityKind::Denoise;
int input_sample_rate = 0;
int output_sample_rate = 0;
};

struct AudioUtilityPaths {
AudioUtilityPaths() = default;
explicit AudioUtilityPaths(std::filesystem::path assets_root_path)
Expand All @@ -25,6 +38,14 @@ struct AudioUtilityBatchResult {
std::vector<std::filesystem::path> outputs;
};

std::filesystem::path default_audio_utility_assets_root();
std::vector<BuiltinAudioUtilityInfo> list_builtin_audio_utilities();
std::optional<BuiltinAudioUtilityInfo> find_builtin_audio_utility(std::string_view model);
BuiltinAudioUtilityInfo require_builtin_audio_utility(std::string_view model);
std::filesystem::path resolve_builtin_audio_utility_asset(
const AudioUtilityPaths & paths,
std::string_view model);

void denoise_file(
const std::filesystem::path & input_wav,
const std::filesystem::path & output_wav,
Expand Down
30 changes: 30 additions & 0 deletions include/engine/models/builtin_audio_utils/session.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include "engine/framework/runtime/model.h"
#include "engine/framework/runtime/session.h"
#include "engine/framework/runtime/session_base.h"

#include <memory>
#include <string>

namespace engine::models::builtin_audio_utils {

class BuiltinAudioUtilsLoadedModel final : public runtime::ILoadedVoiceModel {
public:
explicit BuiltinAudioUtilsLoadedModel(std::string model_id);

const runtime::ModelMetadata & metadata() const noexcept override;
const runtime::CapabilitySet & capabilities() const noexcept override;
std::unique_ptr<runtime::IVoiceTaskSession> create_task_session(
const runtime::TaskSpec & task,
const runtime::SessionOptions & options) const override;

private:
std::string model_id_;
runtime::ModelMetadata metadata_;
runtime::CapabilitySet capabilities_;
};

std::shared_ptr<runtime::IVoiceModelLoader> make_builtin_audio_utils_loader();

} // namespace engine::models::builtin_audio_utils
42 changes: 42 additions & 0 deletions model_specs/builtin_audio_utils.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"schema_version": 1,
"family": "builtin_audio_utils",
"display_name": "Built-in Audio Utilities",
"description": "Built-in denoise, enhancement, and audio super-resolution utilities packaged with audio.cpp.",
"category": "audio_tools",
"status": "experimental",
"tasks": [
"s2s"
],
"modes": [
"offline"
],
"languages": [
"auto"
],
"runtime": {
"tags": [
"cpu",
"cuda"
]
},
"capabilities": {
"s2s": [
"audio_enhancement"
]
},
"options": {
"request": [],
"session": [],
"load": []
},
"packages": [],
"dependencies": [],
"ui": {
"tags": [],
"docs": [
"docs/audio_tools.md"
]
},
"sources": []
}
65 changes: 65 additions & 0 deletions src/framework/audio/utility_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include <algorithm>
#include <cctype>
#include <array>
#include <stdexcept>
#include <string>
#include <string_view>
Expand Down Expand Up @@ -94,8 +95,72 @@ bool is_gtcrn_model(std::string_view model) {
return model == "gtcrn" || model == "gtcrn_dns3" || model == "gtcrn_vctk" || model == "gtcrn_streaming";
}

constexpr std::array<BuiltinAudioUtilityInfo, 8> kBuiltinUtilities{{
{"deepfilternet2", BuiltinAudioUtilityKind::Denoise, 48000, 48000},
{"rnnoise", BuiltinAudioUtilityKind::Denoise, 48000, 48000},
{"zipenhancer", BuiltinAudioUtilityKind::Denoise, 16000, 16000},
{"gtcrn", BuiltinAudioUtilityKind::Denoise, 16000, 16000},
{"gtcrn_streaming", BuiltinAudioUtilityKind::Denoise, 16000, 16000},
{"gtcrn_dns3", BuiltinAudioUtilityKind::Denoise, 16000, 16000},
{"gtcrn_vctk", BuiltinAudioUtilityKind::Denoise, 16000, 16000},
{"flashsr", BuiltinAudioUtilityKind::SuperResolve, 16000, 48000},
}};

} // namespace

std::filesystem::path default_audio_utility_assets_root() {
return std::filesystem::path("assets/framework/audio_utilities");
}

std::vector<BuiltinAudioUtilityInfo> list_builtin_audio_utilities() {
return std::vector<BuiltinAudioUtilityInfo>(kBuiltinUtilities.begin(), kBuiltinUtilities.end());
}

std::optional<BuiltinAudioUtilityInfo> find_builtin_audio_utility(std::string_view model) {
const auto it = std::find_if(
kBuiltinUtilities.begin(),
kBuiltinUtilities.end(),
[&](const BuiltinAudioUtilityInfo & info) {
return info.id == model;
});
if (it == kBuiltinUtilities.end()) {
return std::nullopt;
}
return *it;
}

BuiltinAudioUtilityInfo require_builtin_audio_utility(std::string_view model) {
if (auto info = find_builtin_audio_utility(model)) {
return *info;
}
throw_unsupported_model(
"builtin_audio_utils",
model,
"deepfilternet2, rnnoise, zipenhancer, gtcrn, gtcrn_streaming, gtcrn_dns3, gtcrn_vctk, flashsr");
}

std::filesystem::path resolve_builtin_audio_utility_asset(
const AudioUtilityPaths & paths,
std::string_view model) {
(void) require_builtin_audio_utility(model);
if (model == "deepfilternet2") {
return require_model_dir(paths, "deepfilternet2");
}
if (model == "rnnoise") {
return require_model_dir(paths, "rnnoise") / "rnnoise10Gb_15.safetensors";
}
if (model == "zipenhancer") {
return require_model_dir(paths, "zipenhancer");
}
if (is_gtcrn_model(model)) {
return gtcrn_checkpoint_for(paths, model);
}
if (model == "flashsr") {
return require_model_dir(paths, "flashsr");
}
throw_unsupported_model("builtin_audio_utils", model, "");
}

void denoise_file(
const std::filesystem::path & input_wav,
const std::filesystem::path & output_wav,
Expand Down
9 changes: 8 additions & 1 deletion src/framework/runtime/registry.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "engine/framework/runtime/registry.h"

#include "engine/framework/debug/trace.h"
#include "engine/framework/audio/utility_api.h"
#include "engine/framework/model_spec/package.h"
#include "engine/framework/io/config.h"
#include "engine/framework/io/filesystem.h"
Expand Down Expand Up @@ -149,7 +150,13 @@ std::unique_ptr<ILoadedVoiceModel> ModelRegistry::load(const std::filesystem::pa
}

void ModelRegistry::validate_request(const ModelLoadRequest & request) const {
if (!engine::io::is_existing_file(request.model_path) && !engine::io::is_existing_directory(request.model_path)) {
const bool builtin_audio_utility_id =
request.family_hint.has_value() &&
*request.family_hint == "builtin_audio_utils" &&
engine::audio::find_builtin_audio_utility(request.model_path.generic_string()).has_value();
if (!builtin_audio_utility_id &&
!engine::io::is_existing_file(request.model_path) &&
!engine::io::is_existing_directory(request.model_path)) {
throw std::runtime_error("model path does not exist: " + request.model_path.string());
}
if (request.family_hint.has_value() && !supports_family(*request.family_hint)) {
Expand Down
Loading
Loading