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
3 changes: 3 additions & 0 deletions examples/libtorchaudio/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build
data/output.wav
data/pipeline.zip
20 changes: 20 additions & 0 deletions examples/libtorchaudio/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.5)

project(libtorchaudio-cpp-example)

SET(BUILD_LIBTORCHAUDIO ON CACHE BOOL "Build libtorchaudio")
SET(BUILD_SOX ON CACHE BOOL "Build libsox into libtorchaudio")

SET(BUILD_KALDI OFF CACHE BOOL "Build Kaldi into libtorchaudio")
SET(BUILD_TRANSDUCER OFF CACHE BOOL "Build Python binding")
SET(BUILD_TORCHAUDIO_PYTHON_EXTENSION OFF CACHE BOOL "Build Python binding")

find_package(Torch REQUIRED)
message("libtorchaudio CMakeLists: ${TORCH_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")

add_subdirectory(../.. libtorchaudio)

add_executable(main main.cpp)
target_link_libraries(main "${TORCH_LIBRARIES}" "${TORCHAUDIO_LIBRARY}")
set_property(TARGET main PROPERTY CXX_STANDARD 14)
11 changes: 11 additions & 0 deletions examples/libtorchaudio/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Example usage: libtorchaudio

This example demonstrates how you can use torchaudio's I/O features in C++ application, in addition to PyTorch's operations.

To try this example, simply run `./run.sh`. This script will

1. Create an audio preprocessing pipeline with TorchScript and dump it to a file.
2. Build the application using `libtorch` and `libtorchaudio`.
3. Execute the preprocessing pipeline on an example audio.

The detail of the preprocessing pipeline can be found in [`create_jittable_pipeline.py`](./create_jittable_pipeline.py).
83 changes: 83 additions & 0 deletions examples/libtorchaudio/create_jittable_pipeline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env python3
"""
Create a data preprocess pipeline that can be run with libtorchaudio
"""
import os
import argparse

import torch
import torchaudio


class Pipeline(torch.nn.Module):
"""Example audio process pipeline.

This example load waveform from a file then apply effects and save it to a file.
"""
def __init__(self):
super().__init__()
rir, sample_rate = _load_rir()
self.register_buffer('rir', rir)
self.rir_sample_rate: int = sample_rate

def forward(self, input_path: str, output_path: str):
torchaudio.sox_effects.init_sox_effects()

# 1. load audio
waveform, sample_rate = torchaudio.load(input_path)

# 2. Add background noise
alpha = 0.01
waveform = alpha * torch.randn_like(waveform) + (1 - alpha) * waveform

# 3. Reample the RIR filter to much the audio sample rate
rir, _ = torchaudio.sox_effects.apply_effects_tensor(
self.rir, self.rir_sample_rate, effects=[["rate", str(sample_rate)]])
rir = rir / torch.norm(rir, p=2)
rir = torch.flip(rir, [1])

# 4. Apply RIR filter
waveform = torch.nn.functional.pad(waveform, (rir.shape[1] - 1, 0))
waveform = torch.nn.functional.conv1d(waveform[None, ...], rir[None, ...])[0]

# Save
torchaudio.save(output_path, waveform, sample_rate)


def _create_jit_pipeline(output_path):
module = torch.jit.script(Pipeline())
print("*" * 40)
print("* Pipeline code")
print("*" * 40)
print()
print(module.code)
print("*" * 40)
module.save(output_path)


def _get_path(*paths):
return os.path.join(os.path.dirname(__file__), *paths)


def _load_rir():
path = _get_path("data", "rir.wav")
return torchaudio.load(path)


def _parse_args():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--output-path",
default=_get_path("data", "pipeline.zip"),
help="Output JIT file."
)
return parser.parse_args()


def _main():
args = _parse_args()
_create_jit_pipeline(args.output_path)


if __name__ == '__main__':
_main()
5 changes: 5 additions & 0 deletions examples/libtorchaudio/data/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
The files in this directory are originated from [VOiCES](https://iqtlabs.github.io/voices/) dataset, which is licensed under Creative Commos BY 4.0. They are modified to fit into the tutorial.

* `input.wav`: `VOiCES_devkit/source-16k/train/sp0307/Lab41-SRI-VOiCES-src-sp0307-ch127535-sg0042.wav`

* `rir.wav`: `VOiCES_devkit/distant-16k/room-response/rm1/impulse/Lab41-SRI-VOiCES-rm1-impulse-mc01-stu-clo.wav`
Binary file added examples/libtorchaudio/data/input.wav
Binary file not shown.
Binary file added examples/libtorchaudio/data/rir.wav
Binary file not shown.
21 changes: 21 additions & 0 deletions examples/libtorchaudio/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <torch/script.h>

int main(int argc, char* argv[]) {
if (argc !=4) {
std::cerr << "Usage: " << argv[0] << " <JIT_OBJECT> <INPUT_FILE> <OUTPUT_FILE>" << std::endl;
return -1;
}

torch::jit::script::Module module;
std::cout << "Loading module from: " << argv[0] << std::endl;
try {
module = torch::jit::load(argv[1]);
} catch (const c10::Error &error) {
std::cerr << "Failed to load the module:" << error.what() << std::endl;
return -1;
}

std::cout << "Performing the process ..." << std::endl;
module.forward({c10::IValue(argv[2]), c10::IValue(argv[3])});
std::cout << "Done." << std::endl;
}
24 changes: 24 additions & 0 deletions examples/libtorchaudio/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the goal is to show people how to make one themselves (educational), I'd recommend echoing the steps in the README as comments within the script to make it easier to follow along.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the suggestion. let me follow on that one with another PR.


set -eux

this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

build_dir="${this_dir}/build"
data_dir="${this_dir}/data"
jit_file="${data_dir}/pipeline.zip"
input_file="${data_dir}/input.wav"
output_file="${data_dir}/output.wav"

cd "${this_dir}"
python create_jittable_pipeline.py

mkdir -p "${build_dir}"
cd "${build_dir}"
cmake -GNinja \
-DCMAKE_PREFIX_PATH="$(python -c 'import torch;print(torch.utils.cmake_prefix_path)')" \
-DBUILD_SOX=ON \
-DBUILD_KALDI=OFF \
..
cmake --build . --target main
./main "${jit_file}" "${input_file}" "${output_file}"
1 change: 1 addition & 0 deletions torchaudio/csrc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ if(BUILD_LIBTORCHAUDIO)

target_link_libraries(
libtorchaudio
${TORCH_LIBRARIES}
${TORCHAUDIO_THIRD_PARTIES}
)

Expand Down