diff --git a/.github/workflows/build_docs.yml b/.github/workflows/build_docs.yml index 6a2f47fdee0..9051f2221a8 100644 --- a/.github/workflows/build_docs.yml +++ b/.github/workflows/build_docs.yml @@ -73,7 +73,7 @@ jobs: pip --quiet install git+https://github.com/kpu/kenlm/ flashlight-text # Install build tools - conda install --quiet -y -c conda-forge pandoc doxygen pysoundfile + conda install --quiet -y -c conda-forge sox pandoc doxygen pysoundfile pip install --quiet -r docs/requirements.txt -r docs/requirements-tutorials.txt # Build docs diff --git a/third_party/sox/CMakeLists.txt b/third_party/sox/CMakeLists.txt index b043362925d..a9b6dd65b12 100644 --- a/third_party/sox/CMakeLists.txt +++ b/third_party/sox/CMakeLists.txt @@ -2,155 +2,27 @@ find_package(PkgConfig REQUIRED) include(ExternalProject) +# set(INSTALL_DIR ${CMAKE_BINARY_DIR}/sox) set(INSTALL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../install) set(ARCHIVE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../archives) set(patch_dir ${PROJECT_SOURCE_DIR}/third_party/patches) -set(COMMON_ARGS --quiet --disable-shared --enable-static --prefix=${INSTALL_DIR} --with-pic --disable-dependency-tracking --disable-debug --disable-examples --disable-doc) - -# To pass custom environment variables to ExternalProject_Add command, -# we need to do `${CMAKE_COMMAND} -E env ${envs} `. -# https://stackoverflow.com/a/62437353 -# We constrcut the custom environment variables here -set(envs - "PKG_CONFIG_PATH=${INSTALL_DIR}/lib/pkgconfig" - "LDFLAGS=-L${INSTALL_DIR}/lib $ENV{LDFLAGS}" - "CFLAGS=-I${INSTALL_DIR}/include -fvisibility=hidden $ENV{CFLAGS}" -) - -ExternalProject_Add(amr - PREFIX ${CMAKE_CURRENT_BINARY_DIR} - DOWNLOAD_DIR ${ARCHIVE_DIR} - URL https://sourceforge.net/projects/opencore-amr/files/opencore-amr/opencore-amr-0.1.5.tar.gz - URL_HASH SHA256=2c006cb9d5f651bfb5e60156dbff6af3c9d35c7bbcc9015308c0aff1e14cd341 - PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/amr/ - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/amr/configure ${COMMON_ARGS} - DOWNLOAD_NO_PROGRESS ON - LOG_DOWNLOAD ON - LOG_UPDATE ON - LOG_CONFIGURE ON - LOG_BUILD ON - LOG_INSTALL ON - LOG_MERGED_STDOUTERR ON - LOG_OUTPUT_ON_FAILURE ON -) - -ExternalProject_Add(lame - PREFIX ${CMAKE_CURRENT_BINARY_DIR} - DOWNLOAD_DIR ${ARCHIVE_DIR} - URL https://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz - URL_HASH SHA256=24346b4158e4af3bd9f2e194bb23eb473c75fb7377011523353196b19b9a23ff - PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/lame/ - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/lame/configure ${COMMON_ARGS} --enable-nasm - DOWNLOAD_NO_PROGRESS ON - LOG_DOWNLOAD ON - LOG_UPDATE ON - LOG_CONFIGURE ON - LOG_BUILD ON - LOG_INSTALL ON - LOG_MERGED_STDOUTERR ON - LOG_OUTPUT_ON_FAILURE ON -) - -ExternalProject_Add(ogg - PREFIX ${CMAKE_CURRENT_BINARY_DIR} - DOWNLOAD_DIR ${ARCHIVE_DIR} - URL https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-1.3.3.tar.gz - URL_HASH SHA256=c2e8a485110b97550f453226ec644ebac6cb29d1caef2902c007edab4308d985 - PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/ogg/ - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/ogg/configure ${COMMON_ARGS} - DOWNLOAD_NO_PROGRESS ON - LOG_DOWNLOAD ON - LOG_UPDATE ON - LOG_CONFIGURE ON - LOG_BUILD ON - LOG_INSTALL ON - LOG_MERGED_STDOUTERR ON - LOG_OUTPUT_ON_FAILURE ON -) - -ExternalProject_Add(flac - PREFIX ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS ogg - DOWNLOAD_DIR ${ARCHIVE_DIR} - URL https://ftp.osuosl.org/pub/xiph/releases/flac/flac-1.3.2.tar.xz - URL_HASH SHA256=91cfc3ed61dc40f47f050a109b08610667d73477af6ef36dcad31c31a4a8d53f - PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/flac/ - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/flac/configure ${COMMON_ARGS} --with-ogg --disable-cpplibs - DOWNLOAD_NO_PROGRESS ON - LOG_DOWNLOAD ON - LOG_UPDATE ON - LOG_CONFIGURE ON - LOG_BUILD ON - LOG_INSTALL ON - LOG_MERGED_STDOUTERR ON - LOG_OUTPUT_ON_FAILURE ON -) - -ExternalProject_Add(vorbis - PREFIX ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS ogg - DOWNLOAD_DIR ${ARCHIVE_DIR} - URL https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-1.3.6.tar.gz - URL_HASH SHA256=6ed40e0241089a42c48604dc00e362beee00036af2d8b3f46338031c9e0351cb - PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/vorbis/ - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/vorbis/configure ${COMMON_ARGS} --with-ogg - DOWNLOAD_NO_PROGRESS ON - LOG_DOWNLOAD ON - LOG_UPDATE ON - LOG_CONFIGURE ON - LOG_BUILD ON - LOG_INSTALL ON - LOG_MERGED_STDOUTERR ON - LOG_OUTPUT_ON_FAILURE ON -) - -ExternalProject_Add(opus - PREFIX ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS ogg - DOWNLOAD_DIR ${ARCHIVE_DIR} - URL https://ftp.osuosl.org/pub/xiph/releases/opus/opus-1.3.1.tar.gz - URL_HASH SHA256=65b58e1e25b2a114157014736a3d9dfeaad8d41be1c8179866f144a2fb44ff9d - PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/opus/ - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/opus/configure ${COMMON_ARGS} --with-ogg - DOWNLOAD_NO_PROGRESS ON - LOG_DOWNLOAD ON - LOG_UPDATE ON - LOG_CONFIGURE ON - LOG_BUILD ON - LOG_INSTALL ON - LOG_MERGED_STDOUTERR ON - LOG_OUTPUT_ON_FAILURE ON -) - -ExternalProject_Add(opusfile - PREFIX ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS opus - DOWNLOAD_DIR ${ARCHIVE_DIR} - URL https://ftp.osuosl.org/pub/xiph/releases/opus/opusfile-0.12.tar.gz - URL_HASH SHA256=118d8601c12dd6a44f52423e68ca9083cc9f2bfe72da7a8c1acb22a80ae3550b - PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/opusfile/ - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/opusfile/configure ${COMMON_ARGS} --disable-http - DOWNLOAD_NO_PROGRESS ON - LOG_DOWNLOAD ON - LOG_UPDATE ON - LOG_CONFIGURE ON - LOG_BUILD ON - LOG_INSTALL ON - LOG_MERGED_STDOUTERR ON - LOG_OUTPUT_ON_FAILURE ON -) - -# OpenMP is by default compiled against GNU OpenMP, which conflicts with the version of OpenMP that PyTorch uses. -# See https://github.com/pytorch/audio/pull/1026 -# TODO: Add flags like https://github.com/suphoff/pytorch_parallel_extension_cpp/blob/master/setup.py -set(SOX_OPTIONS +set(COMPILE_ARGS + --quiet + --enable-shared + --disable-static + --prefix=${INSTALL_DIR} + --with-pic + --disable-dependency-tracking + --disable-debug + --disable-examples + --disable-doc --disable-openmp - --with-amrnb - --with-amrwb - --with-flac - --with-lame - --with-oggvorbis - --with-opus + --without-amrnb + --without-amrwb + --without-flac + --without-lame + --without-oggvorbis + --without-opus --without-alsa --without-ao --without-coreaudio @@ -169,33 +41,22 @@ set(SOX_OPTIONS --without-twolame ) -set(SOX_LIBRARIES - ${INSTALL_DIR}/lib/libsox.a - ${INSTALL_DIR}/lib/libopencore-amrnb.a - ${INSTALL_DIR}/lib/libopencore-amrwb.a - ${INSTALL_DIR}/lib/libmp3lame.a - ${INSTALL_DIR}/lib/libFLAC.a - ${INSTALL_DIR}/lib/libopusfile.a - ${INSTALL_DIR}/lib/libopus.a - ${INSTALL_DIR}/lib/libvorbisenc.a - ${INSTALL_DIR}/lib/libvorbisfile.a - ${INSTALL_DIR}/lib/libvorbis.a - ${INSTALL_DIR}/lib/libogg.a - ) - -set(sox_depends - ogg flac vorbis opusfile lame amr - ) +if (APPLE) + set(byproduct ${INSTALL_DIR}/lib/libsox.3.dylib) + set(sox_library ${INSTALL_DIR}/lib/libsox.dylib) +else() + set(byproduct ${INSTALL_DIR}/lib/libsox.so) + set(sox_library ${INSTALL_DIR}/lib/libsox.so) +endif() ExternalProject_Add(sox PREFIX ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS ${sox_depends} DOWNLOAD_DIR ${ARCHIVE_DIR} URL https://downloads.sourceforge.net/project/sox/sox/14.4.2/sox-14.4.2.tar.bz2 URL_HASH SHA256=81a6956d4330e75b5827316e44ae381e6f1e8928003c6aa45896da9041ea149c PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/sox/ - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/sox/configure ${COMMON_ARGS} ${SOX_OPTIONS} - BUILD_BYPRODUCTS ${SOX_LIBRARIES} + CONFIGURE_COMMAND ${CMAKE_CURRENT_BINARY_DIR}/src/sox/configure ${COMPILE_ARGS} + BUILD_BYPRODUCTS ${byproduct} DOWNLOAD_NO_PROGRESS ON LOG_DOWNLOAD ON LOG_UPDATE ON @@ -206,7 +67,19 @@ ExternalProject_Add(sox LOG_OUTPUT_ON_FAILURE ON ) +if (APPLE) + # Modify RPATH, so that they won't be hardcoded + add_custom_command( + OUTPUT ${sox_library} + COMMAND install_name_tool -change ${byproduct} @rpath/libsox.dylib -id @rpath/libsox.dylib ${byproduct} + DEPENDS sox + ) + add_custom_target(_libsox DEPENDS ${sox_library}) +else() + add_custom_target(_libsox DEPENDS sox) +endif() + add_library(libsox INTERFACE) -add_dependencies(libsox sox) +add_dependencies(libsox _libsox) target_include_directories(libsox INTERFACE ${INSTALL_DIR}/include) -target_link_libraries(libsox INTERFACE ${SOX_LIBRARIES}) +target_link_libraries(libsox INTERFACE ${sox_library}) diff --git a/torchaudio/_extension/__init__.py b/torchaudio/_extension/__init__.py index 671074f892e..89c13be36ea 100644 --- a/torchaudio/_extension/__init__.py +++ b/torchaudio/_extension/__init__.py @@ -4,7 +4,15 @@ from torchaudio._internal.module_utils import fail_with_message, is_module_available, no_op -from .utils import _check_cuda_version, _fail_since_no_ffmpeg, _init_dll_path, _init_ffmpeg, _init_sox, _load_lib +from .utils import ( + _check_cuda_version, + _fail_since_no_ffmpeg, + _fail_since_no_sox, + _init_dll_path, + _init_ffmpeg, + _init_sox, + _load_lib, +) _LG = logging.getLogger(__name__) @@ -49,15 +57,14 @@ _IS_KALDI_AVAILABLE = torchaudio.lib._torchaudio.is_kaldi_available() -# Similar to libtorchaudio, sox-related features should be importable when present. -# -# Note: This will be change in the future when sox is dynamically linked. -# At that point, this initialization should handle the case where -# sox integration is built but libsox is not found. +# Initialize libsox-related features _SOX_INITIALIZED = False if is_module_available("torchaudio.lib._torchaudio_sox"): - _init_sox() - _SOX_INITIALIZED = True + try: + _init_sox() + _SOX_INITIALIZED = True + except Exception: + _LG.debug("Failed to initialize libsox bindings", exc_info=True) # Initialize FFmpeg-related features @@ -82,14 +89,7 @@ "requires kaldi extension, but TorchAudio is not compiled with it. Please build TorchAudio with kaldi support." ) ) -fail_if_no_sox = ( - no_op - if _SOX_INITIALIZED - else fail_with_message( - "requires sox extension, but TorchAudio is not compiled with it. Please build TorchAudio with libsox support." - ) -) - +fail_if_no_sox = no_op if _SOX_INITIALIZED else _fail_since_no_sox fail_if_no_ffmpeg = no_op if _FFMPEG_INITIALIZED else _fail_since_no_ffmpeg fail_if_no_rir = ( diff --git a/torchaudio/_extension/utils.py b/torchaudio/_extension/utils.py index 30ef2e4a356..b185331ce02 100644 --- a/torchaudio/_extension/utils.py +++ b/torchaudio/_extension/utils.py @@ -124,6 +124,25 @@ def _check_cuda_version(): return version +def _fail_since_no_sox(func): + @wraps(func) + def wrapped(*_args, **_kwargs): + try: + # Note: + # We run _init_sox again just to show users the stacktrace. + # _init_ffmpeg would not succeed here. + _init_sox() + except Exception as err: + raise RuntimeError( + f"{func.__name__} requires libsox extension which is not available. " + "Please refer to the stacktrace above for how to resolve this." + ) from err + # This should not happen in normal execution, but just in case. + return func(*_args, **_kwargs) + + return wrapped + + def _fail_since_no_ffmpeg(func): @wraps(func) def wrapped(*_args, **_kwargs):