Some checks failed
Linux Build / Linux cpu (push) Has been cancelled
Linux Build / Linux cpu-clang (push) Has been cancelled
Linux Build / Linux vulkan (push) Has been cancelled
mac-build / macOS CPU (push) Has been cancelled
Nix Build / Nix (cpu) (push) Has been cancelled
Nix Build / Nix (vulkan) (push) Has been cancelled
windows-build / Windows CPU (push) Has been cancelled
119 lines
4.8 KiB
C++
119 lines
4.8 KiB
C++
#include "engine/framework/audio/utilities/utility_api.h"
|
|
#include "engine/framework/audio/wav_reader.h"
|
|
#include "engine/framework/audio/wav_writer.h"
|
|
|
|
#include <cmath>
|
|
#include <filesystem>
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#ifndef ENGINE_REPO_ROOT
|
|
#define ENGINE_REPO_ROOT "."
|
|
#endif
|
|
|
|
namespace {
|
|
|
|
std::filesystem::path repo_path(const std::string & relative) {
|
|
return std::filesystem::path(ENGINE_REPO_ROOT) / relative;
|
|
}
|
|
|
|
engine::core::BackendConfig cuda_backend() {
|
|
engine::core::BackendConfig backend;
|
|
#ifdef GGML_USE_CUDA
|
|
backend.type = engine::core::BackendType::Cuda;
|
|
#elif defined(GGML_USE_VULKAN)
|
|
backend.type = engine::core::BackendType::Vulkan;
|
|
#else
|
|
backend.type = engine::core::BackendType::Cpu;
|
|
#endif
|
|
backend.device = 0;
|
|
backend.threads = 1;
|
|
return backend;
|
|
}
|
|
|
|
void require(bool condition, const std::string & message) {
|
|
if (!condition) {
|
|
throw std::runtime_error(message);
|
|
}
|
|
}
|
|
|
|
std::vector<float> tone(int sample_rate, int samples, float base_hz) {
|
|
constexpr float kPi = 3.14159265358979323846f;
|
|
std::vector<float> output(static_cast<size_t>(samples), 0.0f);
|
|
for (int i = 0; i < samples; ++i) {
|
|
const float t = static_cast<float>(i) / static_cast<float>(sample_rate);
|
|
output[static_cast<size_t>(i)] =
|
|
0.18f * std::sin(2.0f * kPi * base_hz * t) +
|
|
0.04f * std::sin(2.0f * kPi * (base_hz * 2.7f) * t + 0.31f);
|
|
}
|
|
return output;
|
|
}
|
|
|
|
void require_wav_shape(const std::filesystem::path & path, int sample_rate) {
|
|
const auto wav = engine::audio::read_wav_f32(path);
|
|
require(wav.sample_rate == sample_rate, "output sample rate mismatch: " + path.string());
|
|
require(wav.channels == 1, "output channel count mismatch: " + path.string());
|
|
require(!wav.samples.empty(), "output WAV is empty: " + path.string());
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int main() {
|
|
try {
|
|
const auto root = std::filesystem::temp_directory_path() / "audio_cpp_audio_utility_api_test";
|
|
std::filesystem::remove_all(root);
|
|
std::filesystem::create_directories(root);
|
|
const engine::audio::AudioUtilityPaths paths{repo_path("assets/framework/audio_utilities"), cuda_backend()};
|
|
|
|
const auto input48 = root / "input48.wav";
|
|
engine::audio::write_pcm16_wav(input48, 48000, 1, tone(48000, 1920, 220.0f));
|
|
const auto rnnoise_out = root / "rnnoise.wav";
|
|
engine::audio::denoise_file(input48, rnnoise_out, "rnnoise", paths);
|
|
require_wav_shape(rnnoise_out, 48000);
|
|
|
|
const auto dfn_out = root / "deepfilternet2.wav";
|
|
engine::audio::denoise_file(input48, dfn_out, "deepfilternet2", paths);
|
|
require_wav_shape(dfn_out, 48000);
|
|
|
|
const auto input16 = root / "input16.wav";
|
|
engine::audio::write_pcm16_wav(input16, 16000, 1, tone(16000, 800, 330.0f));
|
|
const auto zipenhancer_out = root / "zipenhancer.wav";
|
|
engine::audio::denoise_file(input16, zipenhancer_out, "zipenhancer", paths);
|
|
require_wav_shape(zipenhancer_out, 16000);
|
|
|
|
const auto flashsr_out = root / "flashsr.wav";
|
|
engine::audio::super_resolve_file(input16, flashsr_out, "flashsr", paths);
|
|
require_wav_shape(flashsr_out, 48000);
|
|
|
|
const auto input_dir = root / "batch_in";
|
|
const auto output_dir = root / "batch_out";
|
|
std::filesystem::create_directories(input_dir);
|
|
engine::audio::write_pcm16_wav(input_dir / "one.wav", 48000, 1, tone(48000, 1440, 200.0f));
|
|
engine::audio::write_pcm16_wav(input_dir / "two.wav", 48000, 1, tone(48000, 1440, 300.0f));
|
|
const auto rnnoise_batch = engine::audio::denoise_directory(input_dir, output_dir / "rnnoise", "rnnoise", paths);
|
|
require(rnnoise_batch.outputs.size() == 2, "RNNoise directory output count mismatch");
|
|
for (const auto & output : rnnoise_batch.outputs) {
|
|
require_wav_shape(output, 48000);
|
|
}
|
|
|
|
const auto zipenhancer_batch = engine::audio::denoise_directory(input_dir, output_dir / "zipenhancer", "zipenhancer", paths);
|
|
require(zipenhancer_batch.outputs.size() == 2, "ZipEnhancer directory output count mismatch");
|
|
for (const auto & output : zipenhancer_batch.outputs) {
|
|
require_wav_shape(output, 16000);
|
|
}
|
|
|
|
const auto flashsr_batch = engine::audio::super_resolve_directory(input_dir, output_dir / "flashsr", "flashsr", paths);
|
|
require(flashsr_batch.outputs.size() == 2, "FlashSR directory output count mismatch");
|
|
for (const auto & output : flashsr_batch.outputs) {
|
|
require_wav_shape(output, 48000);
|
|
}
|
|
|
|
std::cout << "audio_utility_api_test passed\n";
|
|
} catch (const std::exception & ex) {
|
|
std::cerr << "audio_utility_api_test failed: " << ex.what() << "\n";
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|