diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml new file mode 100644 index 00000000..cedf8410 --- /dev/null +++ b/.github/workflows/cmake-multi-platform.yml @@ -0,0 +1,100 @@ +# This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform. +# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml +name: CMake on multiple platforms + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ${{ matrix.os }} + + strategy: + # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable. + fail-fast: false + + # Set up a matrix to run the following 3 configurations: + # 1. + # 2. + # 3. + # + # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. + matrix: + os: [ubuntu-latest, windows-latest] + build_type: [Release] + c_compiler: [gcc, clang, cl] + conan_profile: [conan-default, conan-release] + include: + - os: windows-latest + c_compiler: cl + cpp_compiler: cl + conan_profile: conan-default + - os: ubuntu-latest + c_compiler: gcc + cpp_compiler: g++ + conan_profile: conan-release + - os: ubuntu-latest + c_compiler: clang + cpp_compiler: clang++ + conan_profile: conan-release + exclude: + - os: windows-latest + c_compiler: gcc + - os: windows-latest + c_compiler: clang + - os: windows-latest + conan_profile: conan-release + - os: ubuntu-latest + c_compiler: cl + - os: ubuntu-latest + conan_profile: conan-default + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - name: Install conan dependencies for runner + run: pip install conan + + - name: Set reusable strings + # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. + id: strings + shell: bash + run: | + echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + + - name: Install conan dependencies + run: | + conan profile detect --force + conan install ${{ github.workspace }}/conanfile.txt --build=missing --settings=build_type=Release + + - name: Configure CMake under Linux OS + if: matrix.os == 'ubuntu-latest' + run: > + cmake -B ${{ steps.strings.outputs.build-output-dir }} + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/build/Release/generators/conan_toolchain.cmake + -S ${{ github.workspace }} + - name: Configure CMake under Windows + if: matrix.os == 'windows-latest' + run : > + cmake -B ${{ steps.strings.outputs.build-output-dir }} + -S ${{ github.workspace }} + --preset=${{ matrix.conan_profile }} + + - name: Build + # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). + run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} + + - name: Test + working-directory: ${{ steps.strings.outputs.build-output-dir }} + # Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ctest --build-config ${{ matrix.build_type }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..2998bf97 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +build/ +downloads +src/rnnoise_data_little.c +src/rnnoise_data_little.h +src/rnnoise_data.h +src/rnnoise_data.c +CMakeUserPresets.json +.vscode/ +.DS_Store +sample_audios/ +evaluation_output/ +rnnoise_env/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..3b8bf8e8 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,120 @@ +cmake_minimum_required(VERSION 3.21) +project(rnnoise) + +option(RNNOISE_COMPILE_OPUS OFF) +option(RNNOISE_COMPILE_DEMO ON) +option(RNNOISE_BAREMETAL OFF) + +if(NOT RNNOISE_BAREMETAL) + find_package(mimalloc REQUIRED) +endif() + +if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping") +endif() + +if(RNNOISE_COMPILE_OPUS) + add_definitions(-DCOMPILE_OPUS) +endif() + +# Ignore CRT warnings on MSVC +if(MSVC) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) +endif() + +#Pre-Generate library resources +set(RNNOISE_MODEL_VERSION "0b50c45") +set(RNNOISE_MODEL_TAR "rnnoise_data-${RNNOISE_MODEL_VERSION}.tar.gz") +set(FILE_URL "https://media.xiph.org/rnnoise/models/${RNNOISE_MODEL_TAR}") +set(RNNOISE_DATA_DOWNLOADS_DIR ${CMAKE_CURRENT_LIST_DIR}/downloads/) +set(RNNOISE_DOWNLOADED_PATH ${RNNOISE_DATA_DOWNLOADS_DIR}/${RNNOISE_MODEL_TAR}) + + + +if(NOT EXISTS "${RNNOISE_DOWNLOADED_PATH}") + + file(DOWNLOAD ${FILE_URL} ${RNNOISE_DOWNLOADED_PATH} + STATUS RNNOISE_DOWNLOAD_STATUS + TIMEOUT 60 + SHOW_PROGRESS) + + if(RNNOISE_DOWNLOAD_STATUS EQUAL 0) + message("File downloaded successfully.") + else() + message(FATAL_ERROR "Failed to download file: ${RNNOISE_DOWNLOAD_STATUS}") + + endif() + + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xzf ${RNNOISE_DOWNLOADED_PATH} + WORKING_DIRECTORY ${RNNOISE_DATA_DOWNLOADS_DIR} +) + +endif() + +if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/src/rnnoise_data.c") + set(RNNOISE_MODEL_UNPACKED_SOURCE_DIR ${RNNOISE_DATA_DOWNLOADS_DIR}/src) + set(RNNOIDE_MODEL_FILES_DESTINATION ${CMAKE_CURRENT_LIST_DIR}/src) + + file(COPY ${RNNOISE_MODEL_UNPACKED_SOURCE_DIR}/rnnoise_data_little.h DESTINATION ${RNNOIDE_MODEL_FILES_DESTINATION}) + file(COPY ${RNNOISE_MODEL_UNPACKED_SOURCE_DIR}/rnnoise_data_little.c DESTINATION ${RNNOIDE_MODEL_FILES_DESTINATION}) + file(COPY ${RNNOISE_MODEL_UNPACKED_SOURCE_DIR}/rnnoise_data.c DESTINATION ${RNNOIDE_MODEL_FILES_DESTINATION}) + file(COPY ${RNNOISE_MODEL_UNPACKED_SOURCE_DIR}/rnnoise_data.h DESTINATION ${RNNOIDE_MODEL_FILES_DESTINATION}) +endif() + +# Get source files + +set(RN_NOISE_SRC + src/_kiss_fft_guts.h + src/arch.h + src/celt_lpc.h + src/common.h + src/cpu_support.h + src/denoise.h + src/kiss_fft.h + src/nnet_arch.h + src/nnet.h + src/opus_types.h + src/pitch.h + src/rnn.h + src/rnnoise_data_little.h + include/rnnoise.h + src/vec.h + + src/celt_lpc.c + src/nnet_default.c + src/rnn.c + src/rnnoise_tables.c + src/denoise.c + src/kiss_fft.c + src/parse_lpcnet_weights.c + src/rnnoise_data_little.c + #write_weights.c + #dump_features.c + src/nnet.c + src/pitch.c + ) + +add_library(rnnoise STATIC ${RN_NOISE_SRC}) + +add_definitions(-DRNNOISE_BUILD) + +# Include dirs +target_include_directories(rnnoise PUBLIC + $ + $ + PRIVATE src) + + +if(NOT RNNOISE_BAREMETAL) + target_link_libraries(rnnoise PUBLIC mimalloc-static) + target_compile_definitions(rnnoise PUBLIC USE_MIMALLOC_ALLOCATOR) +endif() + +if (UNIX) + target_link_libraries(rnnoise PUBLIC m) +endif(UNIX) + +if(RNNOISE_COMPILE_DEMO) + add_subdirectory(examples) +endif() diff --git a/README b/README index 0a780dac..8eb68466 100644 --- a/README +++ b/README @@ -118,3 +118,8 @@ model, rename rnnoise_data_little.c to rnnoise_data.c. It is possible to build both the regular and little binary weights and load any of them at run time since the little model has the same size as the regular one (except for the increased sparsity). + +## Build with Vitis Xilinx toolchain: +```shell +cmake -G"Unix Makefiles" -DCMAKE_BUILD_TYPE="Release" DCMAKE_TOOLCHAIN_FILE="${PWD}/cmake/vitis_toolchain.cmake" -S="$PWD}" -B="${PWD}/build" -DRNNOISE_COMPILE_DEMO=OFF DRNNOISE_BAREMETAL=ON +``` \ No newline at end of file diff --git a/conanfile.txt b/conanfile.txt new file mode 100644 index 00000000..e7fc292f --- /dev/null +++ b/conanfile.txt @@ -0,0 +1,11 @@ +[requires] +libsndfile/1.2.2 +cxxopts/3.2.0 +fmt/10.2.1 +mimalloc/2.1.2 + +[generators] +CMakeDeps +CMakeToolchain +[layout] +cmake_layout \ No newline at end of file diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 00000000..03a7b850 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,32 @@ +set (CMAKE_CXX_STANDARD 17) + +add_executable(rnnoise_demo rnnoise_demo.c) + +target_link_libraries(rnnoise_demo PRIVATE rnnoise) + +find_package(SndFile REQUIRED) +find_package(cxxopts REQUIRED) +find_package(fmt REQUIRED) +find_package(mimalloc REQUIRED) + +add_executable(rnnoise_libsoundfile + rnnoise_libsndfile.cpp + profiling/xcorr_impl.cpp + profiling/xcorr_offload_kernel.cpp +) + +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + message(WARNING "Compiling RNNOISE for Windows...") + target_compile_definitions(rnnoise_libsoundfile PRIVATE WINDOWS_SPECIFIC_MACRO) +endif() + +target_link_libraries( + rnnoise_libsoundfile + PRIVATE + rnnoise + SndFile::sndfile + cxxopts::cxxopts + fmt::fmt + mimalloc-static +) +target_include_directories(rnnoise_libsoundfile PRIVATE ${CMAKE_CURRENT_LIST_DIR}) \ No newline at end of file diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..67572954 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,15 @@ +## Building with Conan +```shell +pip install conan +mkdir build + +## For debug version of the app +conan install conanfile.txt --build=missing --settings=build_type=Debug +cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=./Debug/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Debug -B build +cmake --build build + +## For Release version: +conan install conanfile.txt --build=missing +cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=./Release/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release -B build +cmake --build buil +``` \ No newline at end of file diff --git a/examples/lazy_file_writer.hpp b/examples/lazy_file_writer.hpp new file mode 100644 index 00000000..0b1337e1 --- /dev/null +++ b/examples/lazy_file_writer.hpp @@ -0,0 +1,33 @@ +#pragma once +#include +#include +#include + +class LazyFileWriter { +private: + std::filesystem::path m_filepath; + std::fstream m_file_stream; + void openFileIfNeeded() { + if (!m_file_stream.is_open()) { + m_file_stream.open(m_filepath, std::ios::out | std::ios::app); + if (!m_file_stream.is_open()) { + throw std::runtime_error("Failed to open the lazy file writer"); + } + } + } + +public: + LazyFileWriter(const std::filesystem::path& filepath) : m_filepath{filepath}{} + + ~LazyFileWriter() { + if (m_file_stream.is_open()) { + m_file_stream.close(); + } + } + + template + void write(TypeToWrite&& data) { + openFileIfNeeded(); + m_file_stream << data << std::endl; + } +}; \ No newline at end of file diff --git a/examples/profiling/xcorr_impl.cpp b/examples/profiling/xcorr_impl.cpp new file mode 100644 index 00000000..5c3dc5fb --- /dev/null +++ b/examples/profiling/xcorr_impl.cpp @@ -0,0 +1,83 @@ +#include "xcorr_impl.h" +#include +#include +#include + +inline float MAC16_16(float c, float a, float b){ + return c+a*b; +} + +void xcorr_native_impl(const float * x, const float * y, float sum[4], int len) +{ + int j; + float y_0, y_1, y_2, y_3; + assert(len>=3); + fmt::print("Xcorr native impl called with len {} \n",len); + auto start = std::chrono::high_resolution_clock::now(); + + y_3=0; /* gcc doesn't realize that y_3 can't be used uninitialized */ + y_0=*y++; + y_1=*y++; + y_2=*y++; + for (j=0;j(end - start); + + fmt::print("Execution time is:{} us\n",duration.count()); +} \ No newline at end of file diff --git a/examples/profiling/xcorr_impl.h b/examples/profiling/xcorr_impl.h new file mode 100644 index 00000000..746d55c2 --- /dev/null +++ b/examples/profiling/xcorr_impl.h @@ -0,0 +1,10 @@ +#ifndef XCORR_IMPL_H +#define XCORR_IMPL_H + +extern "C" +{ + +void xcorr_native_impl(const float * x, const float * y, float sum[4], int len); + +} +#endif \ No newline at end of file diff --git a/examples/profiling/xcorr_offload_kernel.cpp b/examples/profiling/xcorr_offload_kernel.cpp new file mode 100644 index 00000000..aeb9a441 --- /dev/null +++ b/examples/profiling/xcorr_offload_kernel.cpp @@ -0,0 +1,103 @@ +#include +#include +#include "xcorr_offload_kernel.hpp" + +#include + +inline float MAC16_16(float c, float a, float b){ + return c+a*b; +} + +#define MAX_PROCESSING_BLOCK_SIZE 1024 +void xcorr_kernel(const float * x, const float * y, float* sum, int len) +{ + +#pragma HLS INTERFACE mode=s_axilite port=return bundle=CONTROL_BUS +#pragma HLS INTERFACE mode=s_axilite port=len bundle=CONTROL_BUS + +#pragma HLS INTERFACE m_axi port=x offset=slave bundle=INPUT +#pragma HLS INTERFACE m_axi port=y offset=slave bundle=INPUT +#pragma HLS INTERFACE m_axi port=sum offset=slave bundle=OUTPUT + + int j; + float y_0, y_1, y_2, y_3; + assert(len>=3); + + float x_copy[MAX_PROCESSING_BLOCK_SIZE]; + float y_copy[MAX_PROCESSING_BLOCK_SIZE]; + + float sum_copy[4]; + + float* x_arr_ptr = x_copy; + float* y_arr_ptr = y_copy; + + memcpy(x_copy, x, len); + memcpy(y_copy, y, len); + memcpy(sum_copy, sum, 4); + + y_3=0; /* gcc doesn't realize that y_3 can't be used uninitialized */ + y_0=*y_arr_ptr++; + y_1=*y_arr_ptr++; + y_2=*y_arr_ptr++; + +xcoor_1st_loop: + for (j=0;j +#include +#include +#include +#include +#include +#include + +#include "lazy_file_writer.hpp" +#include "profiling/xcorr_impl.h" +#include "profiling/xcorr_offload_kernel.hpp" + +#include + +template +using CustomDeleter = std::integral_constant; + +template +using PointerWrapper = std::unique_ptr>; + + +inline constexpr std::size_t AUDIO_BUFFER_LENGTH = 480; +inline constexpr std::size_t NUM_CHANNELS = 1; +inline constexpr std::size_t SAMPLERATE = 48000; + +inline constexpr float RNNOISE_PCM16_MULTIPLY_FACTOR = 32768.0f; + +using RNNoiseDenoiseStatePtr = DenoiseState*; +using RnnModelPtr = RNNModel*; +using TSamplesBufferArray = std::array; + +RnnModelPtr rnn_model_ptr; +RNNoiseDenoiseStatePtr rnnoise_denoise_state_ptr; + +static void initialize_rnnoise_library(){ + rnnoise_denoise_state_ptr = rnnoise_create(nullptr); + rnnoise_set_xcorr_kernel_cb(rnnoise_denoise_state_ptr,xcorr_kernel); +} + +static void normalize_to_rnnoise_expected_level(TSamplesBufferArray& samples_buffer){ + for(auto& sample : samples_buffer){ + sample *= RNNOISE_PCM16_MULTIPLY_FACTOR; + } +} + +static void denormalize_from_rnnoise_expected_level(TSamplesBufferArray& samples_buffer){ + for(auto& sample : samples_buffer){ + sample /= RNNOISE_PCM16_MULTIPLY_FACTOR; + } +} + +static void dump_vad_prob(LazyFileWriter& lazy_probe_dumper,float vad_probe_value){ + lazy_probe_dumper.write(vad_probe_value); +} +static void process_audio_recording( + LazyFileWriter& lazy_vad_probe_writer, + const std::filesystem::path& input_file, + const std::filesystem::path& output_file +){ + SndfileHandle input_audio_file_handle{SndfileHandle(input_file.c_str())}; + + fmt::println(stdout,"Opened input audio file:{}", input_file.generic_string()); + fmt::println(stdout,"Number of channels:{}", input_audio_file_handle.channels()); + + auto input_samplerate = input_audio_file_handle.samplerate(); + fmt::println(stdout,"Samplerate:{}", input_samplerate); + + const bool samplerate_mistmatch{input_audio_file_handle.samplerate() != SAMPLERATE }; + if(samplerate_mistmatch){ + fmt::println(stderr,"Audio samplerate mistmatch! Expected 48K, got:{}", input_samplerate); + std::exit(-1); + } + SndfileHandle output_audio_file_handle{SndfileHandle{ + output_file.c_str(), + SFM_WRITE, + SF_FORMAT_WAV | SF_FORMAT_PCM_16, + NUM_CHANNELS, + SAMPLERATE + } + }; + + + static TSamplesBufferArray samples_buffer{}; + + fmt::println(stdout,"Processing audio..."); + while (input_audio_file_handle.read (samples_buffer.data(), samples_buffer.size()) != 0) { + normalize_to_rnnoise_expected_level(samples_buffer); + float vad_prob = rnnoise_process_frame(rnnoise_denoise_state_ptr, samples_buffer.data(), samples_buffer.data()); + dump_vad_prob(lazy_vad_probe_writer,vad_prob); + denormalize_from_rnnoise_expected_level(samples_buffer); + output_audio_file_handle.write(samples_buffer.data(),samples_buffer.size()); + } + fmt::println(stdout,"Processing done. WAVE file can be found at: {}", output_file.generic_string()); +} + +#ifdef WINDOWS_SPECIFIC_MACRO +static const std::wstring DEFAULT_VAD_PROBE_FILENAME = L"vad_prob.txt"; +#else +static const std::string DEFAULT_VAD_PROBE_FILENAME = "vad_prob.txt"; +#endif + +int main(int argc, char** argv){ + + + cxxopts::Options options("rnnoise_libsoundfile denoiser", "Simple runner of rnnoise over WAVe files with 48K samplerate"); + const auto DEFAULT_VAD_PROBE_PATH {(std::filesystem::current_path()/DEFAULT_VAD_PROBE_FILENAME).generic_string()}; + + options.add_options() + ("input", "Input file to process",cxxopts::value()) + ("output", "Output file", cxxopts::value()) + ("vad_probe", "Path to store output VAD prob data", cxxopts::value()->default_value(DEFAULT_VAD_PROBE_PATH)) + ("help", "Print usage"); + + auto result = options.parse(argc, argv); + + if (result.count("help")) + { + fmt::print(options.help()); + std::exit(0); + } + + mi_option_enable(mi_option_verbose); + mi_option_enable(mi_option_show_stats); + + + using TOptionalPathHolder = std::optional; + TOptionalPathHolder input_file_path_opt = result["input"].as(); + TOptionalPathHolder output_file_path_opt = result["output"].as(); + TOptionalPathHolder output_vad_probe = result["vad_probe"].as(); + + try{ + input_file_path_opt = result["input"].as(); + output_file_path_opt = result["output"].as(); + output_vad_probe = result["vad_probe"].as(); + } + catch(...){ + std::cerr << "Failed to obtain one of the required CMD args. Check help message below and verify passed options:" << std::endl; + fmt::print(options.help()); + std::exit(-1); + } + + LazyFileWriter vad_file_probe(output_vad_probe.value()); + initialize_rnnoise_library(); + process_audio_recording( + vad_file_probe, + input_file_path_opt.value(), + output_file_path_opt.value() + ); + + mi_stats_print(nullptr); + return 0; +} \ No newline at end of file diff --git a/include/rnnoise.h b/include/rnnoise.h index 2d52b966..d7722467 100644 --- a/include/rnnoise.h +++ b/include/rnnoise.h @@ -79,13 +79,6 @@ RNNOISE_EXPORT int rnnoise_init(DenoiseState *st, RNNModel *model); */ RNNOISE_EXPORT DenoiseState *rnnoise_create(RNNModel *model); -/** - * Free a DenoiseState produced by rnnoise_create. - * - * The optional custom model must be freed by rnnoise_model_free() after. - */ -RNNOISE_EXPORT void rnnoise_destroy(DenoiseState *st); - /** * Denoise a frame of samples * @@ -94,35 +87,12 @@ RNNOISE_EXPORT void rnnoise_destroy(DenoiseState *st); RNNOISE_EXPORT float rnnoise_process_frame(DenoiseState *st, float *out, const float *in); /** - * Load a model from a memory buffer - * - * It must be deallocated with rnnoise_model_free() and the buffer must remain - * valid until after the returned object is destroyed. - */ -RNNOISE_EXPORT RNNModel *rnnoise_model_from_buffer(const void *ptr, int len); - - -/** - * Load a model from a file - * - * It must be deallocated with rnnoise_model_free() and the file must not be - * closed until the returned object is destroyed. + * Sets xcorr_kernel_cb to the default or user_provided one */ -RNNOISE_EXPORT RNNModel *rnnoise_model_from_file(FILE *f); -/** - * Load a model from a file name - * - * It must be deallocated with rnnoise_model_free() - */ -RNNOISE_EXPORT RNNModel *rnnoise_model_from_filename(const char *filename); +typedef void(*xcorr_kernel_cb)(const float * x, const float * y, float sum[4], int len); +RNNOISE_EXPORT void rnnoise_set_xcorr_kernel_cb(DenoiseState *st, xcorr_kernel_cb xcorr_callback); -/** - * Free a custom model - * - * It must be called after all the DenoiseStates referring to it are freed. - */ -RNNOISE_EXPORT void rnnoise_model_free(RNNModel *model); #ifdef __cplusplus } diff --git a/run_evaluation.py b/run_evaluation.py new file mode 100644 index 00000000..f7ceb2fe --- /dev/null +++ b/run_evaluation.py @@ -0,0 +1,71 @@ +import os +import sys +import argparse +import subprocess +import pathlib +import tempfile + +import soundfile as sf +import librosa + +def samplerate_preprocess(input_file:pathlib.Path, desired_samplerate:int)->pathlib.Path: + data, input_sampleraete = librosa.load(input_file, sr=None) + + if input_sampleraete == desired_samplerate: + return input_file + + + with tempfile.TemporaryDirectory(delete=False) as temp_dir: + resampled_data = librosa.resample(data, orig_sr=input_sampleraete, target_sr=desired_samplerate) + output_path = pathlib.Path(temp_dir,input_file.name) + sf.write(output_path, resampled_data.T, desired_samplerate) + return output_path + + +def main(): + + parser = argparse.ArgumentParser(description="Launch rnnoise test app for processing") + parser.add_argument('--rnnoise-binary', type=str, help='Path to the rnnoise compiled binary.') + parser.add_argument('--input-directory', type=str, help='Path to the directory containing noisy audio files.') + parser.add_argument('--output-directory', type=str, help='Path to the directory where to store the results.') + + args = parser.parse_args() + binary_path = args.rnnoise_binary + directory_path = args.input_directory + output_path = args.output_directory + + if not os.path.isfile(binary_path): + print(f"Error: The binary file '{binary_path}' does not exist.") + sys.exit(1) + + if not os.path.isdir(directory_path): + print(f"Error: The directory '{directory_path}' does not exist.") + sys.exit(1) + + if not os.path.exists(output_path): + os.makedirs(output_path) + + for filename in os.listdir(directory_path): + file_path = pathlib.Path(directory_path, filename) + + if os.path.isfile(file_path): + try: + print(f"Processing file: {file_path}") + input_file_path = file_path + if(file_path.suffix == ".wav"): + input_file_path = samplerate_preprocess(file_path,48000) + + execution_cmd = [] + execution_cmd.append(binary_path) + execution_cmd.append(f"--input={input_file_path}") + result_filename = f"{input_file_path.stem}_denoised.wav" + result_path = pathlib.Path(output_path,result_filename) + execution_cmd.append(f"--output={result_path}") + result = subprocess.run(execution_cmd, check=True, capture_output=True, cwd=output_path) + + except subprocess.CalledProcessError as e: + print(f"Error processing {file_path}") + print(e.stderr.decode()) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/sample_audios/babble_15dB.opus b/sample_audios/babble_15dB.opus new file mode 100644 index 00000000..f1d297d0 Binary files /dev/null and b/sample_audios/babble_15dB.opus differ diff --git a/src/celt_lpc.c b/src/celt_lpc.c index 750f9a8a..67fab2d2 100644 --- a/src/celt_lpc.c +++ b/src/celt_lpc.c @@ -95,7 +95,9 @@ int rnn_autocorr( const opus_val16 *window, int overlap, int lag, - int n) + int n, + xcorr_kernel_cb xcorr_kernel_executor + ) { opus_val32 d; int i, k; @@ -142,7 +144,7 @@ int rnn_autocorr( shift = 0; } #endif - rnn_pitch_xcorr(xptr, xptr, ac, fastN, lag+1); + rnn_pitch_xcorr(xptr, xptr, ac, fastN, lag+1,xcorr_kernel_executor); for (k=0;k<=lag;k++) { for (i = k+fastN, d = 0; i < n; i++) diff --git a/src/celt_lpc.h b/src/celt_lpc.h index 5abd61a0..3b1d19df 100644 --- a/src/celt_lpc.h +++ b/src/celt_lpc.h @@ -40,6 +40,6 @@ void rnn_lpc(opus_val16 *_lpc, const opus_val32 *ac, int p); int rnn_autocorr(const opus_val16 *x, opus_val32 *ac, - const opus_val16 *window, int overlap, int lag, int n); + const opus_val16 *window, int overlap, int lag, int n,xcorr_kernel_cb xcorr_kernel_executor); #endif /* PLC_H */ diff --git a/src/common.h b/src/common.h index f9095ca5..e4c9400a 100644 --- a/src/common.h +++ b/src/common.h @@ -5,17 +5,23 @@ #include "stdlib.h" #include "string.h" - +#ifdef USE_MIMALLOC_ALLOCATOR + #include + #include +#endif #define RNN_INLINE inline #define OPUS_INLINE inline - /** RNNoise wrapper for malloc(). To do your own dynamic allocation, all you need t o do is replace this function and rnnoise_free */ #ifndef OVERRIDE_RNNOISE_ALLOC static RNN_INLINE void *rnnoise_alloc (size_t size) { +#ifdef USE_MIMALLOC_ALLOCATOR + return mi_malloc(size); +#else return malloc(size); +#endif } #endif @@ -23,7 +29,11 @@ static RNN_INLINE void *rnnoise_alloc (size_t size) #ifndef OVERRIDE_RNNOISE_FREE static RNN_INLINE void rnnoise_free (void *ptr) { +#ifdef USE_MIMALLOC_ALLOCATOR + mi_free(ptr); +#else free(ptr); +#endif } #endif @@ -52,5 +62,6 @@ static RNN_INLINE void rnnoise_free (void *ptr) # endif # endif +typedef void(*xcorr_kernel_cb)(const float * x, const float * y, float sum[4], int len); #endif diff --git a/src/denoise.c b/src/denoise.c index c2dff7ea..8e9060bd 100644 --- a/src/denoise.c +++ b/src/denoise.c @@ -43,6 +43,11 @@ #include "rnn.h" #include "cpu_support.h" +#ifdef USE_MIMALLOC_ALLOCATOR +#include +#include +#endif + #define SQUARE(x) ((x)*(x)) @@ -64,9 +69,12 @@ const int eband20ms[NB_BANDS+2] = { /*0 100 200 300 400 500 600 750 900 1.1 1.2 1.4 1.6 1.8 2.1 2.4 2.7 3.0 3.4 3.9 4.4 4.9 5.5 6.2 7.0 7.9 8.8 9.9 11.2 12.6 14.1 15.9 17.8 20.0*/ 0, 2, 4, 6, 8, 10, 12, 15, 18, 21, 24, 28, 32, 36, 41, 47, 53, 60, 68, 77, 87, 98, 110, 124, 140, 157, 176, 198, 223, 251, 282, 317, 356, 400}; +#define DENOISE_STATE_STORAGE_SIZE 32696 +static char denoise_state_storage [DENOISE_STATE_STORAGE_SIZE]; struct DenoiseState { RNNoise model; + xcorr_kernel_cb xcorr_callback; #if !TRAINING int arch; #endif @@ -229,51 +237,8 @@ struct RNNModel { const void *const_blob; void *blob; int blob_len; - FILE *file; }; -RNNModel *rnnoise_model_from_buffer(const void *ptr, int len) { - RNNModel *model; - model = malloc(sizeof(*model)); - model->blob = NULL; - model->const_blob = ptr; - model->blob_len = len; - return model; -} - -RNNModel *rnnoise_model_from_filename(const char *filename) { - RNNModel *model; - FILE *f = fopen(filename, "rb"); - model = rnnoise_model_from_file(f); - model->file = f; - return model; -} - -RNNModel *rnnoise_model_from_file(FILE *f) { - RNNModel *model; - model = malloc(sizeof(*model)); - model->file = NULL; - - fseek(f, 0, SEEK_END); - model->blob_len = ftell(f); - fseek(f, 0, SEEK_SET); - - model->const_blob = NULL; - model->blob = malloc(model->blob_len); - if (fread(model->blob, model->blob_len, 1, f) != 1) - { - rnnoise_model_free(model); - return NULL; - } - return model; -} - -void rnnoise_model_free(RNNModel *model) { - if (model->file != NULL) fclose(model->file); - if (model->blob != NULL) free(model->blob); - free(model); -} - int rnnoise_get_size() { return sizeof(DenoiseState); } @@ -284,46 +249,27 @@ int rnnoise_get_frame_size() { int rnnoise_init(DenoiseState *st, RNNModel *model) { memset(st, 0, sizeof(*st)); -#if !TRAINING - if (model != NULL) { - WeightArray *list; - int ret = 1; - parse_weights(&list, model->blob ? model->blob : model->const_blob, model->blob_len); - if (list != NULL) { - ret = init_rnnoise(&st->model, list); - opus_free(list); - } - if (ret != 0) return -1; - } + #ifndef USE_WEIGHTS_FILE - else { - int ret = init_rnnoise(&st->model, rnnoise_arrays); - if (ret != 0) return -1; - } + int ret = init_rnnoise(&st->model, rnnoise_arrays); + if (ret != 0) return -1; #endif st->arch = rnn_select_arch(); -#else - (void)model; -#endif return 0; } DenoiseState *rnnoise_create(RNNModel *model) { int ret; DenoiseState *st; - st = malloc(rnnoise_get_size()); + st = (DenoiseState*) denoise_state_storage; ret = rnnoise_init(st, model); if (ret != 0) { - free(st); return NULL; } + st->xcorr_callback = xcorr_kernel; return st; } -void rnnoise_destroy(DenoiseState *st) { - free(st); -} - #if TRAINING extern int lowpass; extern int band_lp; @@ -359,9 +305,9 @@ int rnn_compute_frame_features(DenoiseState *st, kiss_fft_cpx *X, kiss_fft_cpx * RNN_MOVE(st->pitch_buf, &st->pitch_buf[FRAME_SIZE], PITCH_BUF_SIZE-FRAME_SIZE); RNN_COPY(&st->pitch_buf[PITCH_BUF_SIZE-FRAME_SIZE], in, FRAME_SIZE); pre[0] = &st->pitch_buf[0]; - rnn_pitch_downsample(pre, pitch_buf, PITCH_BUF_SIZE, 1); + rnn_pitch_downsample(pre, pitch_buf, PITCH_BUF_SIZE, 1,st->xcorr_callback); rnn_pitch_search(pitch_buf+(PITCH_MAX_PERIOD>>1), pitch_buf, PITCH_FRAME_SIZE, - PITCH_MAX_PERIOD-3*PITCH_MIN_PERIOD, &pitch_index); + PITCH_MAX_PERIOD-3*PITCH_MIN_PERIOD, &pitch_index,st->xcorr_callback); pitch_index = PITCH_MAX_PERIOD-pitch_index; gain = rnn_remove_doubling(pitch_buf, PITCH_MAX_PERIOD, PITCH_MIN_PERIOD, @@ -499,3 +445,7 @@ float rnnoise_process_frame(DenoiseState *st, float *out, const float *in) { return vad_prob; } +void rnnoise_set_xcorr_kernel_cb(DenoiseState *st, xcorr_kernel_cb xcorr_callback) +{ + st->xcorr_callback = xcorr_callback; +} \ No newline at end of file diff --git a/src/dump_features.c b/src/dump_features.c deleted file mode 100644 index cb0803e6..00000000 --- a/src/dump_features.c +++ /dev/null @@ -1,346 +0,0 @@ -/* Copyright (c) 2024 Jean-Marc Valin - * Copyright (c) 2017 Mozilla */ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - - -#include -#include -#include -#include -#include -#include "rnnoise.h" -#include "common.h" -#include "denoise.h" -#include "arch.h" -#include "kiss_fft.h" -#include "src/_kiss_fft_guts.h" - -int lowpass = FREQ_SIZE; -int band_lp = NB_BANDS; - -#define SEQUENCE_LENGTH 2000 -#define SEQUENCE_SAMPLES (SEQUENCE_LENGTH*FRAME_SIZE) - -#define RIR_FFT_SIZE 65536 -#define RIR_MAX_DURATION (RIR_FFT_SIZE/2) -#define FILENAME_MAX_SIZE 1000 - -struct rir_list { - int nb_rirs; - int block_size; - kiss_fft_state *fft; - kiss_fft_cpx **rir; - kiss_fft_cpx **early; -}; - -kiss_fft_cpx *load_rir(const char *rir_file, kiss_fft_state *fft, int early) { - kiss_fft_cpx *x, *X; - float rir[RIR_MAX_DURATION]; - int len; - int i; - FILE *f; - f = fopen(rir_file, "rb"); - if (f==NULL) { - fprintf(stderr, "cannot open %s: %s\n", rir_file, strerror(errno)); - exit(1); - } - x = (kiss_fft_cpx*)calloc(fft->nfft, sizeof(*x)); - X = (kiss_fft_cpx*)calloc(fft->nfft, sizeof(*X)); - len = fread(rir, sizeof(*rir), RIR_MAX_DURATION, f); - if (early) { - for (i=0;i<240;i++) { - rir[480+i] *= (1 - i/240.f); - } - RNN_CLEAR(&rir[240+480], RIR_MAX_DURATION-240-480); - } - for (i=0;inb_rirs = 0; - allocated = 2; - rirs->fft = rnn_fft_alloc_twiddles(RIR_FFT_SIZE, NULL, NULL, NULL, 0); - rirs->rir = malloc(allocated*sizeof(rirs->rir[0])); - rirs->early = malloc(allocated*sizeof(rirs->early[0])); - while (fgets(rir_filename, FILENAME_MAX_SIZE, f) != NULL) { - /* Chop trailing newline. */ - rir_filename[strcspn(rir_filename, "\n")] = 0; - if (rirs->nb_rirs+1 > allocated) { - allocated *= 2; - rirs->rir = realloc(rirs->rir, allocated*sizeof(rirs->rir[0])); - rirs->early = realloc(rirs->early, allocated*sizeof(rirs->early[0])); - } - rirs->rir[rirs->nb_rirs] = load_rir(rir_filename, rirs->fft, 0); - rirs->early[rirs->nb_rirs] = load_rir(rir_filename, rirs->fft, 1); - rirs->nb_rirs++; - } - fclose(f); -} - -void rir_filter_sequence(const struct rir_list *rirs, float *audio, int rir_id, int early) { - int i; - kiss_fft_cpx x[RIR_FFT_SIZE] = {{0,0}}; - kiss_fft_cpx y[RIR_FFT_SIZE] = {{0,0}}; - kiss_fft_cpx X[RIR_FFT_SIZE] = {{0,0}}; - const kiss_fft_cpx *Y; - if (early) Y = rirs->early[rir_id]; - else Y = rirs->rir[rir_id]; - i=0; - while (ifft, x, X); - for (j=0;jfft, X, y); - for (j=0;j5) { - if (strcmp(argv[1], "-rir_list")==0) { - rir_filename = argv[2]; - argv+=2; - argc-=2; - } - } - if (argc!=5) { - fprintf(stderr, "usage: %s [-rir_list list] \n", argv0); - return 1; - } - f1 = fopen(argv[1], "rb"); - f2 = fopen(argv[2], "rb"); - fout = fopen(argv[3], "wb"); - - fseek(f1, 0, SEEK_END); - speech_length = ftell(f1); - fseek(f1, 0, SEEK_SET); - fseek(f2, 0, SEEK_END); - noise_length = ftell(f2); - fseek(f2, 0, SEEK_SET); - - maxCount = atoi(argv[4]); - if (rir_filename) load_rir_list(rir_filename, &rirs); - for (count=0;count speech_length-(long)sizeof(speech16)) speech_pos = speech_length-sizeof(speech16); - if (noise_pos > noise_length-(long)sizeof(noise16)) noise_pos = noise_length-sizeof(noise16); - speech_pos -= speech_pos&1; - noise_pos -= noise_pos&1; - fseek(f1, speech_pos, SEEK_SET); - fseek(f2, noise_pos, SEEK_SET); - fread(speech16, sizeof(speech16), 1, f1); - fread(noise16, sizeof(noise16), 1, f2); - if (rand()%4) start_pos = 0; - else start_pos = -(int)(1000*log(rand()/(float)RAND_MAX)); - start_pos = IMIN(start_pos, SEQUENCE_LENGTH*FRAME_SIZE); - RNN_CLEAR(speech16, start_pos); - - speech_gain = pow(10., (-40+(rand()%55))/20.); - noise_gain = pow(10., (-30+(rand()%40))/20.); - if (rand()%10==0) noise_gain = 0; - noise_gain *= speech_gain; - rand_resp(a_noise, b_noise); - rand_resp(a_sig, b_sig); - lowpass = FREQ_SIZE * 3000./24000. * pow(50., rand()/(double)RAND_MAX); - for (i=0;i lowpass) { - band_lp = i; - break; - } - } - - for (frame=0;frame 10*FRAME_SIZE) { - speech_rms = sqrt(speech_rms/(SEQUENCE_SAMPLES-start_pos)); - } else { - speech_rms = 3000; - } - if (speech_rms < 300) speech_rms = 300; - noise_rms = sqrt(noise_rms/SEQUENCE_SAMPLES); - - speech_gain *= 3000.f/(1+speech_rms); - noise_gain *= 3000.f/(1+noise_rms); - for (j=0;j 1e9f) vad = 1; - else if (E0 > 1e8f && Eprev > 1e8f && Enext > 1e8f) vad = 1; - else if (E0 < 1e7f && Eprev < 1e7f && Enext < 1e7f) vad = 0; - else vad = .5; - for (i=0;i 1) g[i] = 1; - if (silence || i > band_lp) g[i] = -1; - if (Ey[i] < 5e-2 && Ex[i] < 5e-2) g[i] = -1; - if (vad==0 && noise_gain==0) g[i] = -1; - } -#if 0 - { - short tmp[FRAME_SIZE]; - for (j=0;j -#include -#include "denoise.h" -#include "kiss_fft.h" - -#define OVERLAP_SIZE FRAME_SIZE - -int main(void) { - int i; - FILE *file; - kiss_fft_state *kfft; - float half_window[OVERLAP_SIZE]; - float dct_table[NB_BANDS*NB_BANDS]; - - file=fopen("rnnoise_tables.c", "wb"); - fprintf(file, "/* The contents of this file was automatically generated by dump_rnnoise_tables.c*/\n\n"); - fprintf(file, "#ifdef HAVE_CONFIG_H\n"); - fprintf(file, "#include \"config.h\"\n"); - fprintf(file, "#endif\n"); - - fprintf(file, "#include \"kiss_fft.h\"\n\n"); - - kfft = rnn_fft_alloc_twiddles(WINDOW_SIZE, NULL, NULL, NULL, 0); - - fprintf(file, "static const arch_fft_state arch_fft = {0, NULL};\n\n"); - - fprintf (file, "static const opus_int32 fft_bitrev[%d] = {\n", kfft->nfft); - for (i=0;infft;i++) - fprintf (file, "%d,%c", kfft->bitrev[i],(i+16)%15==0?'\n':' '); - fprintf (file, "};\n\n"); - - fprintf (file, "static const kiss_twiddle_cpx fft_twiddles[%d] = {\n", kfft->nfft); - for (i=0;infft;i++) - fprintf (file, "{%#0.9gf, %#0.9gf},%c", kfft->twiddles[i].r, kfft->twiddles[i].i,(i+3)%2==0?'\n':' '); - fprintf (file, "};\n\n"); - - - fprintf(file, "const kiss_fft_state rnn_kfft = {\n"); - fprintf(file, "%d, /* nfft */\n", kfft->nfft); - fprintf(file, "%#0.8gf, /* scale */\n", kfft->scale); - fprintf(file, "%d, /* shift */\n", kfft->shift); - fprintf(file, "{"); - for (i=0;i<2*MAXFACTORS;i++) { - fprintf(file, "%d, ", kfft->factors[i]); - } - fprintf(file, "}, /* factors */\n"); - fprintf(file, "fft_bitrev, /* bitrev*/\n"); - fprintf(file, "fft_twiddles, /* twiddles*/\n"); - fprintf(file, "(arch_fft_state *)&arch_fft, /* arch_fft*/\n"); - - fprintf(file, "};\n\n"); - - for (i=0;i= memneeded) - st = (kiss_fft_state*)mem; - *lenmem = memneeded; - } - if (st) { - opus_int32 *bitrev; - kiss_twiddle_cpx *twiddles; - - st->nfft=nfft; -#ifdef FIXED_POINT - st->scale_shift = celt_ilog2(st->nfft); - if (st->nfft == 1<scale_shift) - st->scale = Q15ONE; - else - st->scale = (1073741824+st->nfft/2)/st->nfft>>(15-st->scale_shift); -#else - st->scale = 1.f/nfft; -#endif - if (base != NULL) - { - st->twiddles = base->twiddles; - st->shift = 0; - while (st->shift < 32 && nfft<shift != base->nfft) - st->shift++; - if (st->shift>=32) - goto fail; - } else { - st->twiddles = twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(kiss_twiddle_cpx)*nfft); - compute_twiddles(twiddles, nfft); - st->shift = -1; - } - if (!kf_factor(nfft,st->factors)) - { - goto fail; - } - - /* bitrev */ - st->bitrev = bitrev = (opus_int32*)KISS_FFT_MALLOC(sizeof(opus_int32)*nfft); - if (st->bitrev==NULL) - goto fail; - compute_bitrev_table(0, bitrev, 1,1, st->factors,st); - - /* Initialize architecture specific fft parameters */ - if (rnn_fft_alloc_arch(st, arch)) - goto fail; - } - return st; -fail: - rnn_fft_free(st, arch); - return NULL; -} - -kiss_fft_state *rnn_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch) -{ - return rnn_fft_alloc_twiddles(nfft, mem, lenmem, NULL, arch); -} - -void rnn_fft_free_arch_c(kiss_fft_state *st) { - (void)st; -} - -void rnn_fft_free(const kiss_fft_state *cfg, int arch) -{ - if (cfg) - { - rnn_fft_free_arch((kiss_fft_state *)cfg, arch); - opus_free((opus_int32*)cfg->bitrev); - if (cfg->shift < 0) - opus_free((kiss_twiddle_cpx*)cfg->twiddles); - opus_free((kiss_fft_state*)cfg); - } -} - #endif /* CUSTOM_MODES */ void rnn_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout) diff --git a/src/kiss_fft.h b/src/kiss_fft.h index 52387f21..6d809db5 100644 --- a/src/kiss_fft.h +++ b/src/kiss_fft.h @@ -34,8 +34,11 @@ #include "arch.h" #include -#define opus_alloc(x) malloc(x) -#define opus_free(x) free(x) + +#ifdef USE_MIMALLOC_ALLOCATOR +#include +#include +#endif #ifdef __cplusplus extern "C" { @@ -46,7 +49,7 @@ extern "C" { # define kiss_fft_scalar __m128 #define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes) #else -#define KISS_FFT_MALLOC opus_alloc + #endif #ifdef FIXED_POINT @@ -103,35 +106,6 @@ typedef struct kiss_fft_state{ #include "arm/fft_arm.h" #endif -/*typedef struct kiss_fft_state* kiss_fft_cfg;*/ - -/** - * opus_fft_alloc - * - * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. - * - * typical usage: kiss_fft_cfg mycfg=opus_fft_alloc(1024,0,NULL,NULL); - * - * The return value from fft_alloc is a cfg buffer used internally - * by the fft routine or NULL. - * - * If lenmem is NULL, then opus_fft_alloc will allocate a cfg buffer using malloc. - * The returned value should be free()d when done to avoid memory leaks. - * - * The state can be placed in a user supplied buffer 'mem': - * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, - * then the function places the cfg in mem and the size used in *lenmem - * and returns mem. - * - * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), - * then the function returns NULL and places the minimum cfg - * buffer size in *lenmem. - * */ - -kiss_fft_state *rnn_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base, int arch); - -kiss_fft_state *rnn_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch); - /** * opus_fft(cfg,in_out_buf) * @@ -148,11 +122,6 @@ void rnn_ifft_c(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx * void rnn_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout); void rnn_ifft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout); -void rnn_fft_free(const kiss_fft_state *cfg, int arch); - - -void rnn_fft_free_arch_c(kiss_fft_state *st); -int rnn_fft_alloc_arch_c(kiss_fft_state *st); #if !defined(OVERRIDE_OPUS_FFT) /* Is run-time CPU detection enabled on this platform? */ @@ -181,12 +150,6 @@ extern void (*const OPUS_IFFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg, #else /* else for if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10)) */ -#define rnn_fft_alloc_arch(_st, arch) \ - ((void)(arch), rnn_fft_alloc_arch_c(_st)) - -#define rnn_fft_free_arch(_st, arch) \ - ((void)(arch), rnn_fft_free_arch_c(_st)) - #define rnn_fft(_cfg, _fin, _fout, arch) \ ((void)(arch), rnn_fft_c(_cfg, _fin, _fout)) diff --git a/src/parse_lpcnet_weights.c b/src/parse_lpcnet_weights.c index bdd50d7e..5ac95dc8 100644 --- a/src/parse_lpcnet_weights.c +++ b/src/parse_lpcnet_weights.c @@ -51,32 +51,6 @@ static int parse_record(const void **data, int *len, WeightArray *array) { return array->size; } -int parse_weights(WeightArray **list, const void *data, int len) -{ - int nb_arrays=0; - int capacity=20; - *list = calloc(capacity*sizeof(WeightArray), 1); - while (len > 0) { - int ret; - WeightArray array = {NULL, 0, 0, 0}; - ret = parse_record(&data, &len, &array); - if (ret > 0) { - if (nb_arrays+1 >= capacity) { - /* Make sure there's room for the ending NULL element too. */ - capacity = capacity*3/2; - *list = realloc(*list, capacity*sizeof(WeightArray)); - } - (*list)[nb_arrays++] = array; - } else { - free(*list); - *list = NULL; - return -1; - } - } - (*list)[nb_arrays].name=NULL; - return nb_arrays; -} - static const void *find_array_entry(const WeightArray *arrays, const char *name) { while (arrays->name && strcmp(arrays->name, name) != 0) arrays++; return arrays; diff --git a/src/pitch.c b/src/pitch.c index 486a7fc4..135a638a 100644 --- a/src/pitch.c +++ b/src/pitch.c @@ -144,7 +144,7 @@ static void celt_fir5(const opus_val16 *x, void rnn_pitch_downsample(celt_sig *x[], opus_val16 *x_lp, - int len, int C) + int len, int C, xcorr_kernel_cb xcorr_kernel_executor) { int i; opus_val32 ac[5]; @@ -179,7 +179,7 @@ void rnn_pitch_downsample(celt_sig *x[], opus_val16 *x_lp, } rnn_autocorr(x_lp, ac, NULL, 0, - 4, len>>1); + 4, len>>1, xcorr_kernel_executor); /* Noise floor -40 dB */ #ifdef FIXED_POINT @@ -214,7 +214,7 @@ void rnn_pitch_downsample(celt_sig *x[], opus_val16 *x_lp, } void rnn_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y, - opus_val32 *xcorr, int len, int max_pitch) + opus_val32 *xcorr, int len, int max_pitch, xcorr_kernel_cb xcorr_kernel_executor) { #if 0 /* This is a simple version of the pitch correlation that should work @@ -250,7 +250,7 @@ void rnn_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y, for (i=0;i>2, max_pitch>>2); + rnn_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2,xcorr_kernel_executor); find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch #ifdef FIXED_POINT diff --git a/src/pitch.h b/src/pitch.h index 0a9d5e57..bb13f07c 100644 --- a/src/pitch.h +++ b/src/pitch.h @@ -35,12 +35,13 @@ #define PITCH_H #include "arch.h" +#include "common.h" void rnn_pitch_downsample(celt_sig *x[], opus_val16 *x_lp, - int len, int C); + int len, int C,xcorr_kernel_cb xcorr_kernel_executor); void rnn_pitch_search(const opus_val16 *x_lp, opus_val16 *y, - int len, int max_pitch, int *pitch); + int len, int max_pitch, int *pitch, xcorr_kernel_cb xcorr_kernel_executor); opus_val16 rnn_remove_doubling(opus_val16 *x, int maxperiod, int minperiod, int N, int *T0, int prev_period, opus_val16 prev_gain); @@ -142,6 +143,6 @@ static OPUS_INLINE opus_val32 celt_inner_prod(const opus_val16 *x, } void rnn_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y, - opus_val32 *xcorr, int len, int max_pitch); + opus_val32 *xcorr, int len, int max_pitch,xcorr_kernel_cb xcorr_kernel_executor); #endif